1 /* ch2rst.c 1.7 86/03/04 2 * 3 * Font translation to Imagen-style fonts (RST format) from character format. 4 * 5 * Use: ch2rst [ -i -s ] charfile > rstfile 6 * 7 * Takes input from charfile (which must be in the format written 8 * by one of the xxx2ch programs), converts to rst format and writes to 9 * stdout. If charfile is missing, stdin is read. The -i flag tells 10 * ch2rst to ignore the character codes at the start of each glyph 11 * definition, and pack the glyphs in consecutive code positions starting 12 * with 0. The -s flag forces ch2rst to NOT trim off any white space in 13 * the glyph map. This is usefull to make stipples of fixed size. 14 */ 15 16 #include <stdio.h> 17 #include "rst.h" 18 19 20 #define PREAMBLE 44 /* size of preamble */ 21 #define STRINGS 2 /* length of strings at pre. */ 22 #define STARTGLYPH PREAMBLE + STRINGS 23 #define MAXLINE 300 24 #define GLYPHSPACE (MAXLINE * MAXLINE) 25 #define wr1(x) putchar(x) 26 27 28 char * malloc(); 29 30 glyph_dir g[DIRSIZ]; /* directory of glyph definitions */ 31 preamble p; /* set of variables for preamble */ 32 double widthtofix; /* fix conversion factor */ 33 double wordsptemp; /* holds wordsp "fix" `til res. is known */ 34 double linesptemp; /* holds linesp "fix" `til res. is known */ 35 36 int code; /* read in code for a glyph */ 37 int width, length; /* width and length of read-in matrix */ 38 int maxv, minv, maxh, minh; /* extent of "blackness" in glyph */ 39 int refv, refh; /* reference point in matrix */ 40 int bitwidth; 41 42 int ignorecode = 0; /* flag: ignore the code number; successive */ 43 int stipple = 0; /* flag: don't eliminate white-space */ 44 FILE * filep; 45 char ibuff[MAXLINE]; 46 char ebuff[MAXLINE]; 47 char * glyphs[DIRSIZ]; 48 char charbits[GLYPHSPACE]; /* place to store bits for a glyph */ 49 50 51 main(argc, argv) 52 int argc; 53 char **argv; 54 { 55 register int i; 56 register int j; 57 register int codeindex; 58 register char *chp; 59 register char *bitp; 60 float par; 61 62 while (argc > 1 && argv[1][0] == '-') { 63 switch(argv[1][1]) { 64 case 'i': 65 ignorecode = 1; 66 break; 67 68 case 's': 69 stipple = 1; 70 break; 71 default: 72 error("%s, unknown option flag", argv[1]); 73 } 74 argc--; argv++; 75 } 76 77 if (argc > 2) 78 error("too many arguments"); 79 if (argc == 2) { 80 if ((filep = fopen (argv[1], "r")) == NULL) 81 error("can't open file \"%s\"", argv[1]); 82 } else filep = stdin; 83 84 codeindex = 0; 85 for (i = 0; i < DIRSIZ; glyphs[i++] = (char *) 0); 86 87 fgets(ibuff, MAXLINE, filep); 88 if (strcmp(ibuff, "fontheader\n")) 89 error("not a character font file"); 90 91 while (fgets(ibuff, MAXLINE, filep) != NULL) { 92 if (index(ibuff, '\n') == 0) 93 error("input line too long"); 94 95 if (ibuff[0] != ':') { 96 sscanf (ibuff, "%s %f", ebuff, &par); 97 if (strcmp(ebuff, "size") == 0) p.p_size = par + 0.5; 98 else if (strcmp(ebuff, "version") == 0) { 99 if (p.p_version = par + 0.5) 100 error("wrong version (%d) for Font file.", p.p_version); 101 } else if (strcmp(ebuff, "mag") == 0) p.p_mag = par + 0.5; 102 else if (strcmp(ebuff, "desiz") == 0) p.p_desiz = par / FIX + 0.5; 103 else if (strcmp(ebuff, "linesp") == 0) linesptemp = par; 104 else if (strcmp(ebuff, "wordsp") == 0) wordsptemp = par; 105 else if (strcmp(ebuff, "rot") == 0) p.p_rot = par + 0.5; 106 else if (strcmp(ebuff, "cadv") == 0) p.p_cadv = par + 0.5; 107 else if (strcmp(ebuff, "ladv") == 0) p.p_ladv = par + 0.5; 108 else if (strcmp(ebuff, "id") == 0) p.p_id = par + 0.5; 109 else if (strcmp(ebuff, "res") == 0) p.p_res = par + 0.5; 110 /* ignore unrecognized fields */ 111 } else { 112 /* set up for real resolution of font file */ 113 if (p.p_mag) 114 widthtofix = 1000.0 / (FIXIN * p.p_res * p.p_mag); 115 else 116 widthtofix = (1.0 / (FIXIN * p.p_res)); 117 p.p_wordsp = wordsptemp * widthtofix + 0.5; 118 p.p_linesp = linesptemp * widthtofix + 0.5; 119 120 if (sscanf (ibuff, ":%d, width = %f", &code, &par) != 2) 121 error("bad glyph header, %s", ibuff); 122 if (ignorecode) codeindex++; else codeindex = code; 123 g[codeindex].g_pwidth = par * widthtofix + 0.5; 124 125 chp = &charbits[0]; 126 if (fgets(chp, MAXLINE, filep) == NULL) 127 error("unexpected end of input"); 128 width = strlen(chp) - 1; 129 minh = width; 130 maxh = 0; 131 refv = minv = -1; 132 133 for (length = 0; *chp != '\n'; length++) { 134 if ((length + 1) * width > GLYPHSPACE) 135 error ("out of glyph space"); 136 for (i = 0; i < width; i++, chp++) { 137 switch (*chp) { 138 case '.': 139 break; 140 case 'x': 141 if (refv != -1) 142 error("two reference points in glyph %d",code); 143 refh = i; 144 refv = length; 145 *chp = '.'; 146 break; 147 case 'X': 148 if (refv != -1) 149 error("two reference points in glyph %d",code); 150 refh = i; 151 refv = length; 152 case '@': 153 case '*': 154 maxv = length; 155 if (minv < 0) minv = length; 156 if (i < minh) minh = i; 157 if (i > maxh) maxh = i; 158 break; 159 default: 160 error("illegal character '%c' in map.", *chp); 161 } /* switch */ 162 } /* for i */ 163 if (*chp != '\n') 164 error("not all lines equal length in glyph %d", code); 165 if (fgets(chp, MAXLINE, filep) == NULL) 166 error("unexpected end of input"); 167 } /* for length */ 168 169 if (stipple) { /* use the whole box to make a */ 170 minv = 0; /* stipple pattern. */ 171 minh = 0; 172 maxv = length - 1; 173 maxh = width - 1; 174 } 175 176 if (refv < 0) error("no reference point in glyph %d.", code); 177 if (minv < 0) { 178 minv = maxv = refv; 179 minh = maxh = refh; 180 } 181 g[codeindex].g_height = maxv + 1 - minv; 182 g[codeindex].g_width = maxh + 1 - minh; 183 g[codeindex].g_up = refv - minv; 184 g[codeindex].g_left = refh - minh; 185 g[codeindex].g_bitp = 186 g[codeindex].g_height * ((g[codeindex].g_width + 7) / 8); 187 188 bitp = (glyphs[codeindex] = malloc(g[codeindex].g_bitp)) - 1; 189 if (!glyphs[codeindex]) 190 error("out of memory"); 191 for (i = minv; i <= maxv; i++) { 192 chp = &charbits[0] + width * i + minh; 193 bitwidth = 0; 194 for (j = minh; j <= maxh; j++, chp++) { 195 if (--bitwidth < 0) { 196 *++bitp = '\0'; 197 bitwidth = 7; 198 } 199 if (*chp != '.') *bitp |= 1 << bitwidth; 200 } 201 } /* for i */ 202 } /* else */ 203 } /* while */ 204 205 if (ignorecode) { 206 p.p_last = codeindex - 1; 207 p.p_first = 0; 208 } else { 209 for (i = DIRSIZ - 1; glyphs[i] == (char *) 0; i--); 210 p.p_last = i; 211 for (i = 0; glyphs[i] == (char *) 0; i++); 212 p.p_first = i; 213 } 214 bitwidth = STARTGLYPH + 15 * (1 + p.p_last - p.p_first); 215 216 printf("Rast UCB"); 217 wr2(p.p_size); wr1(p.p_version); wr3(STARTGLYPH); 218 wr2(p.p_first); wr2(p.p_last); wr4(p.p_mag); 219 wr4(p.p_desiz); wr4(p.p_linesp); wr4(p.p_wordsp); 220 wr2(p.p_rot); wr1(p.p_cadv); wr1(p.p_ladv); 221 wr4(p.p_id); wr2(p.p_res); 222 for (i = 0; i < STRINGS; i++) putchar('\0'); 223 224 for (i = p.p_first; i <= p.p_last; i++) { 225 if (glyphs[i] == (char *) 0) { 226 for (j = 0; j < 15; j++) putchar('\0'); 227 } else { 228 wr2(g[i].g_height); 229 wr2(g[i].g_width); 230 wr2(g[i].g_up); 231 wr2(g[i].g_left); 232 wr4(g[i].g_pwidth); 233 wr3(bitwidth); 234 bitwidth += g[i].g_bitp; 235 } 236 } /* for i */ 237 fflush(stdout); 238 239 for (i = p.p_first; i <= p.p_last; i++) 240 if (glyphs[i] != (char *) 0) 241 vwrite(glyphs[i], g[i].g_bitp); 242 exit(0); 243 } 244 245 246 /*----------------------------------------------------------------------------* 247 | Routine: vwrite (buffer, buffer_size) 248 | 249 | Results: writes out character array "buffer" of size "buffer_size" 250 | to standard output in small enough chunks that a pipe could 251 | handle them. 252 | 253 | Bugs: this routine shouldn't be needed 254 *----------------------------------------------------------------------------*/ 255 256 vwrite(buf, bufsize) 257 char *buf; 258 int bufsize; 259 { 260 int tsize = 0; 261 262 while (bufsize) { 263 buf += tsize; 264 tsize = bufsize > BUFSIZ ? BUFSIZ : bufsize; 265 if ((tsize = write(1, buf, tsize)) < 0) { 266 perror("ch2rst: write failed"); 267 exit(-1); 268 } 269 bufsize -= tsize; 270 } 271 } 272 273 274 /*----------------------------------------------------------------------------* 275 | Routine: error (format_string, argument1, argument2.... ) 276 | 277 | Results: fprints a message to standard error, then exits with error 278 | code 1 279 | 280 | Side Efct: This routine does NOT return 281 *----------------------------------------------------------------------------*/ 282 283 /*VARARGS1*/ 284 error(string, a1, a2, a3, a4) 285 char *string; 286 { 287 fprintf(stderr, "ch2rst: "); 288 fprintf(stderr, string, a1, a2, a3, a4); 289 fprintf(stderr, "\n"); 290 exit(1); 291 } 292 293 294 /*----------------------------------------------------------------------------* 295 | Routine: wr2, wr3, wr4 (and wr1) 296 | 297 | Results: writes out 2, 3, or 4 byte integers in RST byte order, using 298 | the wr1() routine, which writes one byte to standard output. 299 *----------------------------------------------------------------------------*/ 300 301 wr2(i) 302 unsigned int i; 303 { 304 wr1((i >> 8) & 255); 305 wr1(i & 255); 306 } 307 308 wr3(i) 309 unsigned int i; 310 { 311 wr1((i >> 16) & 255); 312 wr1(( i >> 8) & 255); 313 wr1(i & 255); 314 } 315 316 wr4(i) 317 unsigned int i; 318 { 319 wr1((i >> 24) & 255); 320 wr1((i >> 16) & 255); 321 wr1((i >> 8) & 255); 322 wr1(i & 255); 323 } 324