|
|
1.1 ! root 1: /* ! 2: * fwt_PS.c ! 3: * 6/7/91 ! 4: * Build troff font width table from PostScript AFM file. ! 5: * Reference: "Adobe Font Metric Files Specification Version 3.0", 3/8/90. ! 6: */ ! 7: ! 8: #include <stdio.h> ! 9: #include <canon.h> ! 10: #include <ctype.h> ! 11: #include <stdlib.h> ! 12: #include <string.h> ! 13: #include "fwtable.h" ! 14: ! 15: /* ! 16: * Recognized keywords. ! 17: * Most of the AFM file is ignored, recognized keys are listed here. ! 18: */ ! 19: #define OTHER 0 /* anything other than listed below */ ! 20: #define COMMENT 1 ! 21: #define ENDCHAR 2 ! 22: #define ENDFONT 3 ! 23: #define FONTNAME 4 ! 24: #define FULLNAME 5 ! 25: #define STARTCHAR 6 ! 26: #define STARTFONT 7 ! 27: #define WEIGHT 8 ! 28: typedef struct key { ! 29: char *key_name; ! 30: int key_val; ! 31: size_t key_len; ! 32: } KEY; ! 33: KEY keys[] = { ! 34: "Comment", COMMENT, 7, ! 35: "EndCharMetrics", ENDCHAR, 14, ! 36: "EndFontMetrics", ENDFONT, 14, ! 37: "FontName", FONTNAME, 8, ! 38: "FullName", FULLNAME, 8, ! 39: "StartCharMetrics", STARTCHAR, 16, ! 40: "StartFontMetrics", STARTFONT, 16, ! 41: "Weight", WEIGHT, 6 ! 42: }; ! 43: #define NKEYS (sizeof keys/sizeof (struct key)) ! 44: ! 45: /* Globals. */ ! 46: char *bufp; /* buffer pointer */ ! 47: int chartab[NWIDTH]; /* character movement table */ ! 48: char *FontName; /* AFM FontName */ ! 49: char *FullName; /* AFM FullName */ ! 50: int lineno; /* input line number */ ! 51: int maxwidth; /* maximum character movement */ ! 52: char *Weight; /* AFM Weight */ ! 53: ! 54: /* ! 55: * Process an AFM file character metric line ! 56: * and store the character width in the width table. ! 57: * Very ad hoc. ! 58: * Understands only "C", "CH", "W", "WX"; everything else is ignored. ! 59: * Should probably understand "WX0" as well. ! 60: */ ! 61: void ! 62: character() ! 63: { ! 64: register char *s, *next; ! 65: int code, width, base; ! 66: ! 67: code = -2; /* -1 to 255 are legal */ ! 68: width = -1; ! 69: for (s = buf; s != NULL; s = next) { ! 70: if ((next = strchr(s, ';')) != NULL) ! 71: *next++ = '\0'; ! 72: while(isspace(*s)) ! 73: s++; ! 74: if (*s == 'C') { ! 75: ++s; ! 76: if (*s == 'H') { ! 77: ++s; ! 78: base = 16; ! 79: } else ! 80: base = 10; ! 81: code = (int)strtol(s, NULL, base); ! 82: if (code < -1 || code >= NWIDTH) ! 83: fatal("illegal character code %d\n", code); ! 84: } else if (*s == 'W' && isspace(*(s+1))) ! 85: width = atoi(s+2); ! 86: else if (*s == 'W' && *(s+1) == 'X') ! 87: width = atoi(s+2); ! 88: } ! 89: if (code == -2) ! 90: fatal("missing character code"); ! 91: if (width == -1) ! 92: fatal("missing character width"); ! 93: if (code != -1) { ! 94: chartab[code] = width; ! 95: if (width > maxwidth) ! 96: maxwidth = width; ! 97: } ! 98: } ! 99: ! 100: /* ! 101: * Process the AFM file character metrics section. ! 102: */ ! 103: void ! 104: charmetrics() ! 105: { ! 106: register int cmsize, nchars; ! 107: ! 108: cmsize = atoi(bufp); /* number of chars to expect */ ! 109: nchars = 0; /* number of chars seen so far */ ! 110: while (fgets(buf, sizeof buf, ifp) != NULL) { ! 111: ++lineno; ! 112: switch(lookup()) { ! 113: case COMMENT: ! 114: continue; ! 115: case ENDCHAR: ! 116: if (nchars != cmsize) ! 117: nonfatal("warning: %d chars in character metrics section, expected %d\n", ! 118: nchars, cmsize); ! 119: return; ! 120: default: ! 121: ++nchars; ! 122: character(); ! 123: break; ! 124: } ! 125: } ! 126: fatal("missing EndCharMetrics"); ! 127: } ! 128: ! 129: /* ! 130: * Process AFM input file. ! 131: * Most of the specifications are ignored. ! 132: */ ! 133: void ! 134: inputPS() ! 135: { ! 136: register int n, flag; ! 137: ! 138: for (flag = 1; fgets(buf, sizeof buf, ifp) != NULL; ) { ! 139: ++lineno; ! 140: if ((n = lookup()) == COMMENT) ! 141: continue; ! 142: else if (flag) { ! 143: if (n != STARTFONT) ! 144: fatal("not an AFM file (no StartFontMetrics)"); ! 145: flag = 0; ! 146: continue; ! 147: } ! 148: switch(n = lookup()) { ! 149: case OTHER: /* ignored... */ break; ! 150: case ENDCHAR: fatal("unexpected EndCharMetrics"); break; ! 151: case ENDFONT: return; ! 152: case FONTNAME: FontName = newstring(bufp); break; ! 153: case FULLNAME: FullName = newstring(bufp); break; ! 154: case STARTCHAR: charmetrics(); break; ! 155: case STARTFONT: fatal("unexpected StartFontMetrics"); break; ! 156: case WEIGHT: Weight = newstring(bufp); break; ! 157: default: fatal("lookup botch %d", n); break; ! 158: } ! 159: } ! 160: } ! 161: ! 162: /* ! 163: * See if the line in buf[] starts with a recognized keyword. ! 164: * If so, set bufp to point past it and return its key_val. ! 165: * If not, return OTHER. ! 166: * This does not skip leading whitespace in the line, ! 167: * if whitespace is legal then it should. ! 168: */ ! 169: int ! 170: lookup() ! 171: { ! 172: register KEY *kp; ! 173: register size_t n; ! 174: char *s; ! 175: ! 176: if ((s = strrchr(buf, '\n')) != NULL) ! 177: *s = '\0'; /* zap trailing newline */ ! 178: for (kp = keys; kp < &keys[NKEYS]; kp++) { ! 179: n = kp->key_len; ! 180: if (strncmp(buf, kp->key_name, n) == 0) { ! 181: bufp = buf + n; ! 182: if (*bufp != '\0') { ! 183: if (!isspace(*bufp)) ! 184: continue; /* no match */ ! 185: while (isspace(*bufp)) ! 186: bufp++; /* skip trailing whitespace */ ! 187: } ! 188: return kp->key_val; ! 189: } ! 190: } ! 191: return OTHER; ! 192: } ! 193: ! 194: /* ! 195: * Return pointer to allocated copy of string s. ! 196: */ ! 197: char * ! 198: newstring(s) register char *s; ! 199: { ! 200: return strcpy(alloc(strlen(s) + 1), s); ! 201: } ! 202: ! 203: /* ! 204: * Write a font width table for troff. ! 205: * Most of the fields in the binary FWT are for PCL and are zeroed here. ! 206: */ ! 207: void ! 208: outputPS() ! 209: { ! 210: register int i, mul; ! 211: char *fullname; ! 212: int spacing, width; ! 213: ! 214: if (FontName == NULL) ! 215: fatal("no FontName specified"); ! 216: fullname = (FullName == NULL) ? FontName : FullName; ! 217: ! 218: /* Verbose output. */ ! 219: if (vflag) { ! 220: if (FullName != NULL) ! 221: fprintf(stderr, "FullName = %s\n", FullName); ! 222: fprintf(stderr, "FontName = %s\n", FontName); ! 223: if (Weight != NULL) ! 224: fprintf(stderr, "Weight = %s\n", Weight); ! 225: } ! 226: ! 227: /* Descriptive name. */ ! 228: if (cflag) { ! 229: fprintf(ofp, "{\n\t\"%s", fullname); ! 230: fprintf(ofp, "\",\n"); ! 231: } else { ! 232: fputs(fullname, ofp); ! 233: fputc(0, ofp); ! 234: } ! 235: ! 236: /* Font name. */ ! 237: if (cflag) ! 238: fprintf(ofp, "\t\"%s\",\n", FontName); ! 239: else { ! 240: fputs(FontName, ofp); ! 241: fputc(0, ofp); ! 242: } ! 243: ! 244: /* Determine if fixed or variable spacing. */ ! 245: width = spacing = 0; /* assume fixed spacing */ ! 246: for (i = 0; i < NWIDTH; i++) { ! 247: if (chartab[i] == 0) ! 248: continue; ! 249: else if (width == 0) ! 250: width = chartab[i]; /* first nonzero width */ ! 251: else if (width != chartab[i]) { ! 252: spacing = 1; /* variable spacing */ ! 253: break; ! 254: } ! 255: } ! 256: ! 257: /* ! 258: * Write FWTAB fields. ! 259: * All but spacing, pitch, ptsize, num, den are zeroed. ! 260: * This uses a nominal point size of 10, for no particular reason. ! 261: */ ! 262: putshort(FLAG_PS); ! 263: putshort(0); ! 264: putshort(0); ! 265: putshort(spacing); /* spacing */ ! 266: putshort(0); ! 267: putshort(44); /* pitch */ ! 268: putshort(100); /* 10 * ptsize */ ! 269: putshort(0); /* style */ ! 270: putshort(0); /* weight */ ! 271: putshort(0); /* face */ ! 272: mul = (maxwidth / 256) + 1; /* scale factor */ ! 273: putshort(mul); /* mul */ ! 274: putshort(1000); /* div */ ! 275: ! 276: /* Write width table. */ ! 277: if (cflag) { ! 278: fprintf(ofp, "\t{"); ! 279: for (i = 0; i < NWIDTH; i++) { ! 280: if (i % 8 == 0) ! 281: fprintf(ofp, "\n\t\t"); ! 282: fprintf(ofp, "%3d, ", chartab[i]/mul); ! 283: } ! 284: fprintf(ofp, "\n\t}\n}\n"); ! 285: } else { ! 286: for (i = 0; i < NWIDTH; i++) ! 287: fputc(chartab[i]/mul, ofp); ! 288: } ! 289: } ! 290: ! 291: /* end of fwt_PS.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.