1 /* makeifont.c (Berkeley) 1.8 86/03/04 2 * 3 * Font description file producer for imagen fonts: David Slattengren 4 * Taken from vfontinfo by Andy Hertzfeld 4/79 5 * 6 * Use: makeifont [ -nNAME ] [ -i -s -a -o -l -c ] [ "-xs1,s2[;s1,s2...]" ] 7 * [ "-ys1,s2[;s1,s2...]" ] [ -p# ] [ -r# ] [ -ddir ] font 8 * 9 * Mkfnt takes the font named "font" and produces a ditroff description 10 * file from it. The -n option takes the 1 or 2 letter troff name to put 11 * the description (default = XX). The -s, -o, -i, -a options select a 12 * different character mapping than for a "roman" font. s = special; 13 * o = math; i = italics; a = ascii. The -l option tells if the font 14 * has ligatures. The -c option tells makeifont that the font is a 15 * constant width one and sets parameters appropriately. 16 * 17 * Both -x and -y options allow character name mapping. A semi-colon 18 * separated list of comma-separated character-name pairs follows the 19 * x or y. Notice that there are no spaces in the -x or -y command. It 20 * is also IMPORTANT to enclose these arguments in single quotes to stop 21 * the cshell from interpretting the contents. A -x pair REPLACES the 22 * definition for s1 by s2. A -y pair creates a synonym for s1 and calls 23 * it s2. -x and -y MUST be sent after -s, -m, -i, or -a if one of them 24 * is used. Some synonyms are defaulted. To remove a synonym or char- 25 * acter, leave out s2. 26 * 27 * The -p# option tells what point size the DESC file has 28 * as it's "unitwidth" argument (default: 40). The -r# option is the 29 * resolution of the device (default: 240, in units/inch). The -d option 30 * tells where to find fonts (default: /usr/src/local/imagen/fonts/raster). 31 */ 32 33 /* 34 * Here's an ascii character set, just in case you need it: 35 36 | 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel| 37 | 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si | 38 | 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb| 39 | 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us | 40 | 20 sp | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' | 41 | 28 ( | 29 ) | 2a * | 2b + | 2c , | 2d - | 2e . | 2f / | 42 | 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 | 43 | 38 8 | 39 9 | 3a : | 3b ; | 3c < | 3d = | 3e > | 3f ? | 44 | 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G | 45 | 48 H | 49 I | 4a J | 4b K | 4c L | 4d M | 4e N | 4f O | 46 | 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W | 47 | 58 X | 59 Y | 5a Z | 5b [ | 5c \ | 5d ] | 5e ^ | 5f _ | 48 | 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g | 49 | 68 h | 69 i | 6a j | 6b k | 6c l | 6d m | 6e n | 6f o | 50 | 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w | 51 | 78 x | 79 y | 7a z | 7b { | 7c | | 7d } | 7e ~ | 7f del| 52 53 * 54 */ 55 56 #include <stdio.h> 57 #include <ctype.h> 58 #include "rst.h" 59 60 char sccsid[] = "@(#)makeifont.c 1.8 (Berkeley) 03/04/86"; 61 62 #define PCNTUP 62 /* percent of maximum height for an ascender */ 63 #define PCNTDOWN 73 /* percent of maximum droop for a descender */ 64 #ifndef BITDIR 65 #define BITDIR "/usr/src/local/imagen/fonts/raster" 66 #endif 67 #define POINTSIZE 40 /* this is the "unitwidth" point size */ 68 #define MINSIZE 6 /* the minimum and maximum point size values */ 69 #define MAXSIZE 36 /* acceptible for use as "unitwidth"s */ 70 #define MINRES 10 /* check up on resolution input by setting */ 71 #define MAXRES 100000 /* absurdly out-of-range limits on them */ 72 #define MAXLAST 127 /* highest character code allowed */ 73 #define SYNON 100 /* number of entries in a synonym table. */ 74 /* equals twice the number of pairs. */ 75 76 77 unsigned char *idstrings; /* place for identifying strings */ 78 unsigned char *endstring; /* points to end of id strings */ 79 double fixtowdth; /* "fix" and magnification conversion factor */ 80 glyph_dir g[DIRSIZ]; /* directory of glyph definitions */ 81 preamble p; /* set of variables for preamble */ 82 83 int res = RES; /* resolution of the device (units/inch) */ 84 double fixpix = FIXPIX; /* conversion factor "fix"es to pixels */ 85 int pointsize = POINTSIZE; /* point size being used for unitwidth */ 86 int psize; /* point size of font actually used */ 87 int psizelist[] = { 40, 36, 28, 24, 22, 20, 18, 16, 88 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0 }; 89 90 char *fontname = "XX"; /* troff name of font - set on command line */ 91 char *fontdir = BITDIR; /* place to look for fonts */ 92 char IName[100]; /* input file name put here */ 93 char *rdchar (); /* function makes strings for ascii */ 94 FILE * FID = NULL; /* input file number */ 95 96 int maxdown = 0; /* size of the most "droopy" character */ 97 int maxup = 0; /* size of the tallest character */ 98 int type; /* 1, 2, or 3 for type of ascend/descending */ 99 int ligsf = 0; /* flag "does this font have ligatures?" */ 100 int constant = 0; /* flag constant width font (spacewidth, etc.)*/ 101 102 /* following are the character maps for */ 103 /* ascii code-conversion to printables... */ 104 char **charmap; 105 char **synonyms; 106 int numsyn; 107 108 char *iregular[] = { 109 "*G", "*D", "*H", "*L", "*C", "*P", "*S", "*U", "*F", "*Q", "*W", 110 "id", "ij", "ga", "aa", "^", "d^", "hc", "rn", "..", "~", "ve", 111 "im", "de", "ce", "tl", "ar", "fb", "ae", "oe", "AE", "OE", "o/", 112 "!", "\"", "fm", "ft", "%", "&", "'", "(", ")", "*", "+", ",", "hy", 113 ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", 114 "<", "=", ">", "?", 115 "es", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 116 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 117 "b\"", "]", "\\-", "em", "`", "a", "b", "c", "d", "e", "f", "g", "h", 118 "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", 119 "w", "x", "y", "z", "ff", "fi", "fl", "Fi", "Fl" 120 }; 121 int nregular = 14; 122 char *sregular[SYNON] = { 123 "A", "*A", "B", "*B", "E", "*E", "H", "*Y", 124 "I", "*I", "K", "*K", "M", "*M", "N", "*N", 125 "O", "*O", "P", "*R", "T", "*T", "X", "*X", 126 "Z", "*Z", "hy", "-" 127 }; 128 129 char *iascii[] = { 130 "m.", "da", "*a", "*b", "an", "no", "mo", "*p", "*l", "*g", "*d", 131 "is", "+-", "O+", "if", "pd", "sb", "sp", "ca", "cu", "fa", "te", 132 "OX", "<>", "<-", "->", "ap", "!=", "<=", ">=", "==", "or", "", 133 "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", 134 ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", 135 "<", "=", ">", "?", 136 "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 137 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 138 "\\", "]", "^", "em", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", 139 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 140 "x", "y", "z", "{", "|", "}", "~", "dm" 141 }; 142 int nascii = 2; 143 char *sascii[SYNON] = { 144 "-", "hy", "-", "\\-" 145 }; 146 147 char *ispecial[] = { 148 "mi", "m.", "mu", "**", "\\", "ci", "+-", "-+", "O+", "O-", "OX", "O/", 149 "O.", "di", "ht", "bu", "pe", "==", "ib", "ip", "<=", ">=", "(=", ")=", 150 "ap", "pt", "sb", "sp", "!=", ".=", "((", "))", "<-", "->", "ua", "da", 151 "<>", "<<", ">>", "~=", "lh", "rh", "Ua", "Da", "><", "uL", "uR", "lR", 152 "fm", "if", "mo", "!m", "0/", "ul", "al", ")(", "fa", "te", "no", "?0", 153 "?1", "?2", "cr", "", "/", "A", "B", "C", "D", "E", "F", "G", "H", "I", 154 "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", 155 "X", "Y", "Z", "cu", "ca", "c+", "an", "or", "|-", "-|", "lf", "rf", 156 "lc", "rc", "{", "}", "<", ">", "br", "||", "[[", "]]", "", "", "sr", 157 "#", "gr", "is", "ux", "dx", "rx", "dm", "sc", "dg", "dd", "pp", "@", 158 "co", "", "$" 159 }; 160 int nspecial = 2; 161 char *sspecial[SYNON] = { 162 "lh", "La", "rh", "Ra" 163 }; 164 165 char *imath[] = { 166 "Bl", "Br", "LT", "RT", "LB", "RB", "rt", "rk", "rb", "lt", "lk", "lb", 167 "rc", "lc", "rf", "lf", "bv", "ci", "^R", "^S", "^T", "^U", "^V", "^W", 168 "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", 169 " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", 170 ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", 171 "<", "=", ">", "?", 172 "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 173 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 174 "\\", "]", "^", "em", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", 175 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 176 "x", "y", "z", "{", "|", "}", "~", "dm" 177 }; 178 int nmath = 0; 179 char *smath[SYNON] = { 180 "","" 181 }; 182 183 char *iitalics[] = { 184 "*G", "*D", "*H", "*L", "*C", "*P", "*S", "*U", "*F", "*Q", "*W", 185 "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", 186 "*m", "*n", "*c", "*p", "*r", "*s", "*t", "*u", "*f", "*x", "id", 187 "!", "\"", "el", "Fi", "pd", "&", "'", "(", ")", "*", "+", ",", "hy", 188 ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", 189 "<", "=", ">", "?", 190 "id", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 191 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 192 "ff", "]", "fi", "fl", "`", "a", "b", "c", "d", "e", "f", "g", "h", 193 "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", 194 "w", "x", "y", "z", "*q", "*w", "?2", "?1", "Fl" 195 }; 196 int nitalics = 15; 197 char *sitalics[SYNON] = { 198 "A", "*A", "B", "*B", "E", "*E", "H", "*Y", 199 "I", "*I", "K", "*K", "M", "*M", "N", "*N", 200 "O", "*O", "P", "*R", "T", "*T", "X", "*X", 201 "Z", "*Z", "o", "*o", "hy", "-" 202 }; 203 204 205 206 main (argc, argv) 207 int argc; 208 char **argv; 209 { 210 register int i; /* two indexes */ 211 register int j; 212 register char *ptr; /* string traveller */ 213 register char delimit; /* place for delemiters on command-line */ 214 char *replacelist = NULL; /* list of character-name replacements */ 215 char *synonymlist = NULL; /* list of synonym entries */ 216 char tostring(); /* function makes string */ 217 char *nextstring(); /* moves to next string on list */ 218 char *operand(); /* reads operands from commandline */ 219 220 charmap = iregular; /* default character map */ 221 synonyms = sregular; 222 numsyn = nregular; 223 while (--argc > 0 && *(*(++argv)) == '-') { /* do options... */ 224 switch ((*argv)[1]) { 225 226 case 's': charmap = ispecial; /* special font */ 227 synonyms = sspecial; 228 numsyn = nspecial; 229 break; 230 231 case 'o': charmap = imath; /* math font */ 232 synonyms = smath; 233 numsyn = nmath; 234 break; 235 236 case 'i': charmap = iitalics; /* italics font */ 237 synonyms = sitalics; 238 numsyn = nitalics; 239 break; 240 241 case 'a': charmap = iascii; /* ascii font */ 242 synonyms = sascii; 243 numsyn = nascii; 244 break; 245 246 case 'c': constant = 1; /* constant width font */ 247 break; 248 249 case 'l': ligsf = 1; /* ascii font */ 250 break; 251 252 case 'n': fontname = operand(&argc, &argv); /* troff font name */ 253 break; 254 255 case 'x': replacelist = operand(&argc, &argv); /* replacements */ 256 break; 257 258 case 'y': synonymlist = operand(&argc, &argv); /* synonyms */ 259 break; 260 261 case 'd': fontdir = operand(&argc, &argv); /* directory */ 262 break; 263 264 case 'p': pointsize = atoi(operand(&argc, &argv)); /* point size */ 265 if (pointsize < MINSIZE || pointsize > MAXSIZE) 266 error("illegal point size: %d", pointsize); 267 break; 268 269 case 'r': res = atoi(operand(&argc, &argv)); /* resolution */ 270 if (res < MINRES || res > MAXRES) 271 error("illegal resolution: %d", res); 272 fixpix = (FIXIN * res); /* pixels per fix */ 273 break; 274 275 default: error("bad option: %c", **argv); 276 } 277 } 278 279 if (replacelist != NULL) { 280 ptr = replacelist; 281 while (delimit = tostring(ptr, ',')) { /* get s1 */ 282 for (i = 0; i <= MAXLAST; i++) /* search for match */ 283 if (strcmp (charmap[i], ptr) == 0) 284 break; 285 if (i > MAXLAST) error("-x option: no match"); 286 charmap[i] = ptr = nextstring(ptr); /* replace s1 */ 287 delimit = tostring(ptr, ':'); /* with string s2 */ 288 if (delimit) ptr = nextstring(ptr); 289 } 290 } 291 292 if (synonymlist != NULL) { 293 ptr = synonymlist; 294 while (delimit = tostring(ptr, ',')) { /* get s1 */ 295 synonyms[2 * numsyn] = ptr; /* set on end of list */ 296 ptr = nextstring(ptr); /* get string s2 */ 297 delimit = tostring(ptr, ':'); 298 if (*ptr) { /* if something there */ 299 synonyms[2 * numsyn++ + 1] = ptr; /* add to list */ 300 } else { /* otherwise */ 301 for (i = 0; i < numsyn; i++) { /* remove from list */ 302 if (!strcmp(synonyms[2*i],synonyms[2*numsyn])) { 303 numsyn--; 304 for (j = i--; j < numsyn; j++) { 305 synonyms[2 * j] = synonyms[2 * (j+1)]; 306 synonyms[2*j + 1] = synonyms[2*j + 3]; 307 } 308 } 309 } 310 } 311 if (delimit) ptr = nextstring(ptr); 312 if (numsyn > SYNON) error("out of synonym space"); 313 } 314 } 315 316 if (argc != 1) /* open font file */ 317 error("An RST font filename must be the last option"); 318 for (i = 0; FID == NULL && (psize = psizelist[i]) > 0; i++) { 319 sprintf (IName, "%s/%s.r%d", fontdir, *argv, psize); 320 FID = fopen (IName, "r"); 321 } 322 if (FID == NULL) 323 error("can't find %s", *argv); 324 325 for (i = 0; i < FMARK; filemark[i++] = getc(FID)); 326 if (strncmp(filemark, "Rast", 4)) 327 error("bad File Mark in Font file."); 328 329 p.p_size = rd2(); 330 p.p_version = rd1(); 331 if (p.p_version) 332 error("wrong version of Font file."); 333 p.p_glyph = rd3(); 334 p.p_first = rd2(); 335 p.p_last = rd2(); 336 if (p.p_last > MAXLAST) { 337 fprintf(stderr, "truncating from %d to %d\n", p.p_last, MAXLAST); 338 p.p_last = MAXLAST; 339 } 340 p.p_mag = rd4(); 341 p.p_desiz = rd4(); 342 p.p_linesp = rd4(); 343 p.p_wordsp = rd4(); 344 p.p_rot = rd2(); 345 p.p_cadv = rd1(); 346 p.p_ladv = rd1(); 347 p.p_id = rd4(); 348 p.p_res = rd2(); 349 if (p.p_res != res) 350 error("wrong resolution in Font file."); 351 352 i = p.p_glyph - 44; 353 idstrings = (unsigned char *) malloc (i); 354 endstring = idstrings + i; 355 while (i--) if (getc(FID) == EOF) 356 error("bad preamble in Font file."); 357 358 for (i = p.p_first; i <= p.p_last; i++) { 359 g[i].g_height = rd2(); 360 g[i].g_width = rd2(); 361 g[i].g_up = rd2(); 362 g[i].g_left = rd2(); 363 g[i].g_pwidth = rd4(); 364 g[i].g_bitp = rd3(); 365 } 366 367 368 if ((fixtowdth = fixpix * p.p_mag / 1000.0) == 0.0) 369 fixtowdth = fixpix; 370 371 printf("# Font %s\n# size %.2f, ", IName, p.p_desiz * FIX); 372 printf("first %d, last %d, res %d, ", p.p_first, p.p_last, p.p_res); 373 printf("mag %.2f\n", fixtowdth / fixpix); 374 375 printf("name %s\n", fontname); 376 if (ligsf) 377 printf ("ligatures ff fl fi ffl ffi 0\n"); 378 if ((i = (pointsize * p.p_wordsp * fixtowdth) / psize) > 127) i = 127; 379 printf("spacewidth %d\n", i); 380 printf ("# char width u/d octal\ncharset\n"); 381 /* the octal values for the following characters are */ 382 /* purposefully OUT of the range of characters (128) */ 383 printf ("\\| %4d 0 0%o\n\\^ %4d 0 0%o\n", 384 (constant ? i : i/3), DIRSIZ, (constant ? 0 : i/6), DIRSIZ); 385 386 for (j = p.p_first; j <= p.p_last; j++) { 387 if (g[j].g_bitp != 0) { 388 if (g[j].g_up > maxup) maxup = g[j].g_up; 389 if ((i = g[j].g_height - (g[j].g_up + 1)) > maxdown) maxdown = i; 390 } 391 } 392 if (maxdown == 0) maxdown = 1; 393 394 /******************************************************************************* 395 396 `type' is used to determine overhangs (up/down) from percentage of 397 the maximum heights and dips. Ascenders are higher than PCNTUP% 398 of the highest, as descenders are more than PCNTDOWN%. 399 widths [i = f(width)] are calculated from the definition point 400 size (pointsize) and the one from this font (psize). 401 402 *******************************************************************************/ 403 404 for (j=0; j<DIRSIZ; j++) { 405 if (g[j].g_bitp != 0) { 406 type = (int) (((g[j].g_up * 100) / maxup) > PCNTUP) * 2 | (int) 407 ((((g[j].g_height - (g[j].g_up+1)) * 100)/maxdown) > PCNTDOWN); 408 if (*(ptr = charmap[j])) { 409 printf ("%s %4d %d 0%o\n", ptr, (int) (pointsize 410 * g[j].g_pwidth * fixtowdth / psize), type, j); 411 for (i = 0; i < numsyn; i++) 412 if (strcmp (ptr, synonyms[2 * i]) == 0) 413 printf ("%s \"\n", synonyms[2 * i + 1]); 414 } 415 } 416 } /* for j */ 417 exit(0); 418 } 419 420 421 /*----------------------------------------------------------------------------* 422 | Routine: char * operand (& argc, & argv) 423 | 424 | Results: returns address of the operand given with a command-line 425 | option. It uses either "-Xoperand" or "-X operand", whichever 426 | is present. The program is terminated if no option is present. 427 | 428 | Side Efct: argc and argv are updated as necessary. 429 *----------------------------------------------------------------------------*/ 430 431 char *operand(argcp, argvp) 432 int * argcp; 433 char ***argvp; 434 { 435 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */ 436 if ((--*argcp) <= 0) /* no operand */ 437 error("command-line option operand missing."); 438 return(*(++(*argvp))); /* operand operand */ 439 } 440 441 442 /*----------------------------------------------------------------------------* 443 | Routine: char tostring (pointer, delimitter) 444 | 445 | Results: checks string pointed to by pointer and turns it into a 446 | string at 'delimitter' by replacing it with '\0'. If the 447 | end of the string is found first, '\0' is returned; otherwise 448 | the delimitter found there is returned. 449 | 450 *----------------------------------------------------------------------------*/ 451 452 char tostring(p, d) 453 register char *p; 454 register char d; 455 { 456 while (*p && *p != d) p++; 457 d = *p; 458 *p = '\0'; 459 return d; 460 } 461 462 463 /*----------------------------------------------------------------------------* 464 | Routine: char * nextstring (pointer) 465 | 466 | Results: returns address of next string after one pointed to by 467 | pointer. The next string is after the '\0' byte. 468 | 469 *----------------------------------------------------------------------------*/ 470 471 char *nextstring(p) 472 register char *p; 473 { 474 while (*(p++)); 475 return p; 476 } 477 478 479 /*VARARGS1*/ 480 error(string, a1, a2, a3, a4) 481 char *string; 482 { 483 fprintf(stderr, "makefont: "); 484 fprintf(stderr, string, a1, a2, a3, a4); 485 fprintf(stderr, "\n"); 486 exit(8); 487 } 488 489 rd1() 490 { 491 int i; 492 493 if((i = getc(FID)) == EOF) error("file read error"); 494 return i; 495 } 496 497 rd2() 498 { 499 register int i = rd1() << 8; 500 501 return i + rd1(); 502 } 503 504 rd3() 505 { 506 register int i = rd2() << 8; 507 508 return i + rd1(); 509 } 510 511 rd4() 512 { 513 register int i = rd2() << 16; 514 515 return i + rd2(); 516 } 517