1 /* makevfont.c (Berkeley) 85/05/03 1.6 2 * 3 * Font description file producer for versatec fonts: David Slattengren 4 * Taken from vfontinfo by Andy Hertzfeld 4/79 5 * 6 * Use: makevfont [ -nNAME ] [ -s -a -o -l -c -p# -r# -f# -ddir ] 7 * [ "-xs1,s2[;s1,s2...]" ] [ "-ys1,s2[;s1,s2...]" ] font 8 * 9 * Makefont takes the font named "font" (with or without pointsize 10 * extension on the filename) and produces a ditroff description file 11 * from it. The -n option takes the 1 or 2 letter troff name to put 12 * the description (default = XX). The -f option takes an integer per- 13 * centage factor to multiply widths by. The -s, -o and -a options select 14 * a different character mapping than for a "roman" font. s = special; 15 * o = otimespecal; a = ascii. The -l option indicates it has ligatures. 16 * The -c option tells makevfont that the font is constant width and 17 * will set parameters appropriately. 18 * 19 * Both -x and -y options allow character name mapping. A colon separated 20 * list of comma-separated character-name pairs follows the x or y. 21 * Notice that there are no spaces in the -x or -y command. A -x pair 22 * REPLACES the definition for s1 by s2. A -y pair creates a synonym for 23 * s1 and calls it s2. -x and -y MUST be sent after -s, -m, -i, or -a 24 * if one of them is used. Some synonyms are defaulted. To remove a 25 * synonym or character, leave out s2. 26 * 27 * The -p# option tells what point size the DESC file has as it's 28 * "unitwidth" argument (default: 36). The -r# option is the resolution 29 * of the device (default: 200, in units/inch). The -d option tells 30 * where to find fonts (default: /usr/lib/vfont). 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 <vfont.h> 59 #include <strings.h> 60 61 char sccsid[] = "@(#)makevfont.c 1.6 (Berkeley) 05/03/85"; 62 63 #define MAGICN 0436 /* font file magic number */ 64 #define PCNTUP 62 /* percent of maximum height for an ascender */ 65 #define PCNTDOWN 73 /* percent of maximum droop for a descender */ 66 #ifndef BITDIR 67 #define BITDIR "/usr/lib/vfont" 68 #endif 69 #define POINTSIZE 36 /* this is the "unitwidth" point size */ 70 #define MINSIZE 6 /* the minimum and maximum point size values */ 71 #define MAXSIZE 36 /* acceptible for use as "unitwidth"s */ 72 #define RESOLUTION 200 /* resolution of versatec (dots/inch) */ 73 #define MINRES 10 /* check up on resolution input by setting */ 74 #define MAXRES 100000 /* absurdly out-of-range limits on them */ 75 #define APOINT 72 /* 1/APOINT inches = 1 point */ 76 #define SYNON 100 /* 2 * pairs allowed in synonym table */ 77 78 79 struct header FontHeader; 80 struct dispatch disptable[256]; 81 82 int res = RESOLUTION; /* resolution of the device (units/inch) */ 83 int pointsize = POINTSIZE; /* point size being used for unitwidth */ 84 int factor = 100; /* percent for magnifying (shrinking) widths */ 85 int psize; /* point size of font actually used */ 86 int psizelist[] = { 36,24,22,20,18,16,14,28,12,11,10,9,8,7,6,0 }; 87 88 char *fontname = "XX"; /* troff font name - set on command line */ 89 char *fontdir = BITDIR; /* place to look for fonts */ 90 char IName[100]; /* input file name put here */ 91 char *rdchar (); /* function makes strings for ascii */ 92 int FID = -1; /* input file number */ 93 94 int maxdown = 0; /* size of the most "droopy" character */ 95 int maxup = 0; /* size of the tallest character */ 96 int type; /* 1, 2, or 3 for type of ascend/descending */ 97 int nullchar = -1; /* finds non-existant character in the font */ 98 int ligsf = 0; /* flag "does this font have ligatures?" */ 99 int constant = 0; /* flag constant width font (spacewidth, etc.)*/ 100 101 /* following are the character maps for */ 102 /* ascii code-conversion to printables... */ 103 char **charmap; 104 char **synonyms; 105 int numsyn; 106 107 char *vregular[] = { 108 109 "??", "fi", "fl", "ff", "\\-", "ru", "em", "bu", "sq", "Fi", "Fl", "de", 110 "dg", "fm", "co", "rg", "ct", "14", "12", "34", "^T", "^U", "^V", "^W", 111 "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", "", "!", "\"", "#", 112 "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", 113 "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", 114 "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 115 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 116 "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", 117 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 118 "x", "y", "z", "{", "|", "}", "~", "^?", 119 (char *) 0 120 }; 121 int nregular = 2; 122 char *sregular[SYNON] = { 123 "-", "hy", "_", "\\_" 124 }; 125 126 char *vspecial[] = { 127 128 "??", "if", "ip", "pt", "rh", "cu", "rn", "bs", "+-", "<=", ">=", "sr", 129 "ts", "is", "sl", "bv", "lf", "rf", "lc", "rc", "lt", "lb", "rt", "rb", 130 "lk", "rk", "sb", "sp", "ca", "no", "lh", "mo", "", "!", "\"", "#", 131 "$", "%", "&", "aa", "gr", ")", "mu", "pl", ",", "mi", ".", "di", "==", 132 "~=", "ap", "!=", "<-", "->", "ua", "da", "sc", "**", ":", ";", "<", 133 "eq", ">", "?", "@", "*A", "*B", "*G", "*D", "*E", "*Z", "*Y", "*H", 134 "*I", "*K", "*L", "*M", "*N", "*C", "*O", "*P", "*R", "*S", "*T", "*U", 135 "*F", "*X", "*Q", "*W", "dd", "br", "ib", "\\", "ci", "^", "ul", "ga", 136 "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", "*m", 137 "*n", "*c", "*o", "*p", "*r", "*s", "*t", "*u", "es", "*x", "*q", "*w", 138 "pd", "*f", "{", "|", "}", "~", "^?", 139 (char *) 0 140 }; 141 int nspecial = 0; 142 char *sspecial[SYNON] = { 143 "","" 144 }; 145 146 char *vtimes[] = { 147 148 "??", "if", "ip", "pt", "rh", "cu", "rn", "bs", "+-", "<=", ">=", "mi", 149 "**", "pl", "eq", "gr", "lt", "lk", "lb", "rt", "rk", "rb", "ap", "mo", 150 "br", "rk", "sb", "sp", "ca", "no", "~=", "mo", "", "da", "no", "ua", 151 "sc", "dd", "if", "pd", "sb", "sp", "mu", "+-", "ca", "cu", "<-", "di", 152 "->", 153 "!=", "sr", "<=", ">=", "==", "or", "is", "bv", "lc", "rc", "lf", "rf", 154 "~=", "_", "ib", "ul", "rn", "ip", "*G", "*D", "*E", "*F", "*G", "*H", 155 "*I", "??", "*L", "*L", "*N", "*C", "*O", "*P", "*H", "*S", "*S", "*U", 156 "*U", "*X", "*W", "*C", "*Q", "br", "ib", "ga", "aa", "^", "ul", "ga", 157 "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", "*m", 158 "*n", "*c", "*o", "*p", "*r", "*s", "*t", "*u", "es", "*x", "*q", "*w", 159 "pd", "*f", "{", "|", "}", "~", "^?", 160 (char *) 0 161 }; 162 int ntimes = 0; 163 char *stimes[SYNON] = { 164 "","" 165 }; 166 167 168 char *vascii[] = { 169 "", "da", "*a", "*b", "an", "no", "mo", "*p", "*l", "*g", "*d", 170 "ua", "+-", "O+", "if", "pd", "sb", "sp", "ca", "cu", "fa", "te", 171 "OX", "<>", "<-", "->", "!=", "ap", "<=", ">=", "==", "or", "", 172 "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", 173 ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", 174 "<", "=", ">", "?", 175 "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 176 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", 177 "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", 178 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 179 "x", "y", "z", "{", "|", "}", "~", "??", 180 (char *)0 181 }; 182 int nascii = 3; 183 char *sascii[SYNON] = { 184 "-", "hy", "-", "\\-", "_", "\\_" 185 }; 186 187 188 main (argc, argv) 189 int argc; 190 char **argv; 191 { 192 register int i; /* two indexes */ 193 register int j; 194 register char *ptr; /* string traveler */ 195 register char delimit; /* place for delimiters on command line */ 196 char *replacelist = NULL; /* string of character name replacements */ 197 char *synonymlist = NULL; /* string of synonym entries */ 198 char tostring(); /* function makes a string */ 199 char *nextstring(); /* moves to next string on list */ 200 char *operand(); 201 202 203 charmap = vregular; /* default character map */ 204 synonyms = sregular; 205 numsyn = nregular; 206 while (--argc > 0 && *(*(++argv)) == '-') { /* do options... */ 207 switch ((*argv)[1]) { 208 209 case 's': charmap = vspecial; /* special font */ 210 synonyms = sspecial; 211 numsyn = nspecial; 212 break; 213 214 case 'o': charmap = vtimes; /* times special font */ 215 synonyms = stimes; 216 numsyn = ntimes; 217 break; 218 219 case 'a': charmap = vascii; /* ascii font */ 220 synonyms = sascii; 221 numsyn = nascii; 222 break; 223 224 case 'c': constant = 1; /* constant width font */ 225 break; 226 227 case 'l': ligsf = 1; /* ascii font */ 228 break; 229 230 case 'n': fontname = operand(&argc, &argv); /* troff font name */ 231 break; 232 233 case 'x': replacelist = operand(&argc, &argv); /* replacements */ 234 break; 235 236 case 'y': synonymlist = operand(&argc, &argv); /* synonyms */ 237 break; 238 239 case 'd': fontdir = operand(&argc, &argv); /* directory */ 240 break; 241 242 case 'p': pointsize = atoi(operand(&argc, &argv)); /* point size */ 243 if (pointsize < MINSIZE || pointsize > MAXSIZE) 244 error("Illegal point size: %d", pointsize); 245 break; 246 247 case 'f': factor = atoi(operand(&argc, &argv)); /* % reduction */ 248 if (factor < 1 || factor > 1000) 249 error("Illegal factor: %d", factor); 250 break; 251 252 case 'r': res = atoi(operand(&argc, &argv)); /* resolution */ 253 if (res < MINRES || res > MAXRES) 254 error("Illegal resolution: %d", res); 255 break; 256 257 default: error("Bad option: %c", **argv); 258 } 259 } 260 /* do character name replacements */ 261 if (replacelist != NULL) { 262 ptr = replacelist; 263 while (delimit = tostring(ptr, ',')) { /* get s1 */ 264 for (i = 0; charmap[i] != 0; i++) /* search for match */ 265 if (strcmp (charmap[i], ptr) == 0) 266 break; 267 if (!charmap[i]) error("-x option: no match"); 268 charmap[i] = ptr = nextstring(ptr); /* replace s1 */ 269 delimit = tostring(ptr, ':'); /* with string s2 */ 270 if (delimit) ptr = nextstring(ptr); 271 } 272 } 273 /* do the synonym list */ 274 if (synonymlist != NULL) { 275 ptr = synonymlist; 276 while (delimit = tostring(ptr, ',')) { /* get s1 */ 277 synonyms[2 * numsyn] = ptr; /* set on end of list */ 278 ptr = nextstring(ptr); /* get string s2 */ 279 delimit = tostring(ptr, ':'); 280 if (*ptr) { /* if something there */ 281 synonyms[2 * numsyn++ + 1] = ptr; /* add to list */ 282 } else { /* otherwise remove */ 283 for (i = 0; i < numsyn; i++) { /* from list */ 284 if (!strcmp(synonyms[2*i],synonyms[2*numsyn])) { 285 numsyn--; 286 for (j = i--; j < numsyn; j++) { 287 synonyms[2 * j] = synonyms[2 * (j+1)]; 288 synonyms[2*j + 1] = synonyms[2*j + 3]; 289 } 290 } 291 } 292 } 293 if (delimit) ptr = nextstring(ptr); 294 if (numsyn > SYNON) error("out of synonym space"); 295 } 296 } 297 298 if (argc != 1) /* open font file */ 299 error("A vfont filename must be the last operand."); 300 if (ptr = rindex(*argv, '.')) ptr++; 301 if (ptr && *ptr <= '9' && *ptr >= '0') { 302 psize = atoi(ptr); 303 if (psize < MINSIZE || psize > MAXSIZE) 304 error("point size of file \"%s\" out of range", *argv); 305 sprintf (IName, "%s/%s", fontdir, *argv); 306 FID = open (IName, 0); 307 } else { 308 for (i = 0; FID < 0 && (psize = psizelist[i]) > 0; i++) { 309 sprintf (IName, "%s/%s.%d", fontdir, *argv, psize); 310 FID = open (IName, 0); 311 } 312 } 313 if (FID < 0) 314 error ("Can't open %s", *argv); 315 316 /* read font width table */ 317 if (read (FID, &FontHeader, sizeof FontHeader) != sizeof FontHeader) 318 error("Bad header in Font file."); 319 if (read (FID, &disptable[0], sizeof disptable) != sizeof disptable) 320 error("Bad dispatch table in Font file"); 321 if (FontHeader.magic != MAGICN) 322 printf ("Magic number %o wrong\n", FontHeader.magic); 323 324 325 printf ("# Font %s, ", IName); /* head off the file */ 326 printf ("max width %d, max height %d\n", 327 FontHeader.maxx, FontHeader.maxy); 328 printf ("name %s\n", fontname); 329 if (ligsf) 330 printf ("ligatures ff fl fi ffl ffi 0\n"); 331 332 /* pass 1 - set up maximums for ups and downs */ 333 for (j=0; j<256; j++) { /* and find out constant width if requested */ 334 if (disptable[j].nbytes != 0) { 335 if (disptable[j].up > maxup) maxup = disptable[j].up; 336 if (disptable[j].down > maxdown) maxdown = disptable[j].down; 337 if (constant && disptable[j].width) constant = disptable[j].width; 338 } else /* find a non-existant character to put \| in */ 339 if (nullchar < 0) nullchar = j; 340 } 341 if (maxdown == 0) maxdown = 1; 342 343 if (constant) { 344 constant = (factor * (pointsize * constant + psize/2) / psize) / 100; 345 printf ("spacewidth %d\n", constant); 346 } 347 printf ("# char width u/d octal\ncharset\n"); 348 if (nullchar >= 0) { 349 printf ("\\| %4d 0 0%o\n\\^ %4d 0 0%o\n", 350 constant ? constant : (res*pointsize / APOINT + 4)/6, nullchar, 351 constant ? 0 : (res * pointsize / APOINT + 7) / 12, nullchar); 352 } 353 354 /******************************************************************************* 355 356 `type' is used to determine overhangs (up/down) from percentage of 357 the maximum heights and dips. Ascenders are higher than PCNTUP% 358 of the highest, as descenders are more than PCNTDOWN%. 359 widths [i = f(width)] are calculated from the definition point 360 size (pointsize) and the one from this font (psize). 361 362 *******************************************************************************/ 363 364 for (j=0; j<256; j++) { 365 if (disptable[j].nbytes != 0) { 366 type = (int) (((disptable[j].up * 100) / maxup) > PCNTUP) * 2 | 367 (int) (((disptable[j].down * 100) / maxdown) > PCNTDOWN); 368 if (*(ptr = charmap[j])) { 369 printf ("%s %4d %d 0%o\n", ptr, (factor * 370 (pointsize * disptable[j].width + psize/2) / psize)/100, 371 type, j); 372 for (i = 0; i < numsyn; i++) 373 if (strcmp (ptr, synonyms[2 * i]) == 0) 374 printf ("%s \"\n", synonyms[2 * i + 1]); 375 } 376 } 377 } /* for j */ 378 exit(0); 379 } 380 381 382 /*----------------------------------------------------------------------------* 383 | Routine: char * operand (& argc, & argv) 384 | 385 | Results: returns address of the operand given with a command-line 386 | option. It uses either "-Xoperand" or "-X operand", whichever 387 | is present. The program is terminated if no option is present. 388 | 389 | Side Efct: argc and argv are updated as necessary. 390 *----------------------------------------------------------------------------*/ 391 392 char *operand(argcp, argvp) 393 int * argcp; 394 char ***argvp; 395 { 396 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */ 397 if ((--*argcp) <= 0) /* no operand */ 398 error("command-line option operand missing."); 399 return(*(++(*argvp))); /* operand next word */ 400 } 401 402 403 /*----------------------------------------------------------------------------* 404 | Routine: char tostring (pointer, delimitter) 405 | 406 | Results: checks string pointed to by pointer and turns it into a 407 | string at 'delimitter' by replacing it with '\0'. If the 408 | end of the string is found first, '\0' is returned; otherwise 409 | the delimitter found there is returned. 410 | 411 *----------------------------------------------------------------------------*/ 412 413 char tostring(p, d) 414 register char *p; 415 register char d; 416 { 417 while (*p && *p != d) p++; 418 d = *p; 419 *p = '\0'; 420 return d; 421 } 422 423 424 /*----------------------------------------------------------------------------* 425 | Routine: char * nextstring (pointer) 426 | 427 | Results: returns address of next string after one pointed to by 428 | pointer. The next string is after the '\0' byte. 429 | 430 *----------------------------------------------------------------------------*/ 431 432 char *nextstring(p) 433 register char *p; 434 { 435 while (*(p++)); 436 return p; 437 } 438 439 440 error(s, a1, a2, a3, a4, a5) 441 char *s; 442 { 443 fprintf(stderr, "makefont: "); 444 fprintf(stderr, s, a1, a2, a3, a4); 445 fprintf(stderr, "\n"); 446 exit(8); 447 } 448