|
|
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.