|
|
1.1 root 1: /* $Header: fc.c,v 1.4 87/07/24 14:50:35 toddb Exp $ */
2:
3: #include <stdio.h>
4: #include <errno.h>
5: /* #include <malloc.h> */ extern char *malloc(), *realloc();
6:
7: #include "misc.h"
8: #include "X.h"
9: #include "Xproto.h"
10: #include "fontstruct.h"
11: #include "font.h"
12:
13: #include "fc.h" /* used by converters only */
14:
15: /*
16: * DESCRIPTION
17: * pure filter; filename argument only
18: *
19: * DISCLAIMER
20: * not much thought has been given to error recovery.
21: */
22: #define INDICES 256
23: #define MAXENCODING 0xFFFF
24:
25: extern char *gets(), *index();
26:
27: static char *myname; /* initialized from argv[0] */
28: static char *currentfont;
29:
30: int linenum = 0; /* for error messages */
31: int or_glyphPad = 0; /* override glyphPading?? */
32: int or_bitorder = 0; /* override bitorder?? */
33:
34:
35: int glyphPad = DEFAULTGLPAD;
36: int bitorder = DEFAULTBITORDER;
37:
38: /*
39: * read the next line and keep a count for error messages
40: */
41: char *
42: getline(s)
43: char *s;
44: {
45: s = gets(s);
46: linenum++;
47: while (s) {
48: int len = strlen(s);
49: if (len && s[len-1] == '\015')
50: s[--len] = '\0';
51: if ((len==0) || prefix(s, "COMMENT")) {
52: s = gets(s);
53: linenum++;
54: } else break;
55: }
56: return(s);
57: }
58:
59: /*
60: * malloc and copy a string value. Handle quoted strings.
61: */
62: char *
63: remember(s)
64: char *s;
65: {
66: char *p, *pp;
67:
68: /* strip leading white space */
69: while (*s && (*s == ' ' || *s == '\t'))
70: s++;
71: if (*s == 0)
72: return "";
73: if (*s != '"') {
74: pp = s;
75: /* no white space in value */
76: for (pp=s; *pp; pp++)
77: if (*pp == ' ' || *pp == '\t' || *pp == '\015' || *pp == '\n') {
78: *pp = 0;
79: break;
80: }
81: p = malloc(strlen(s)+1);
82: strcpy(p, s);
83: return p;
84: }
85: /* quoted string: strip outer quotes and undouble inner quotes */
86: s++;
87: pp = p = malloc(strlen(s)+1);
88: while (*s) {
89: if (*s == '"') {
90: if (*(s+1) != '"') {
91: *p++ = 0;
92: return pp;
93: } else {
94: s++;
95: }
96: }
97: *p++ = *s++;
98: }
99: *p++ = 0; /* just in case; space for it allocated above */
100: return pp;
101: }
102:
103: /*
104: * Invert bit order within each BYTE of an array.
105: * "In" and "out" may point to the same array.
106: */
107: void
108: bitorderinvert( in, out, nbytes)
109: register unsigned char *in;
110: register unsigned char *out;
111: register int nbytes;
112: {
113: static int BOTableInitialized = 0;
114: static unsigned char BOTable[256];
115:
116:
117: if ( !BOTableInitialized)
118: {
119: int btabi;
120: int biti;
121:
122: for ( btabi=0; btabi<256; btabi++)
123: for ( biti=0; biti<8; biti++)
124: if (btabi & 1<<biti)
125: BOTable[btabi] |= (unsigned)0x80 >> biti;
126: BOTableInitialized++;
127: }
128: while ( nbytes--)
129: *out++ = BOTable[ *in++];
130:
131: }
132:
133: /*
134: * return TRUE if str is a prefix of buf
135: */
136: prefix(buf, str)
137: char *buf, *str;
138: {
139: return strncmp(buf, str, strlen(str))? FALSE : TRUE;
140: }
141:
142: /*
143: * return TRUE if strings are equal
144: */
145: streq(a, b)
146: char *a, *b;
147: {
148: return strcmp(a, b)? FALSE : TRUE;
149: }
150:
151: /*
152: * make a byte from the first two hex characters in s
153: */
154: unsigned char
155: hexbyte(s)
156: char *s;
157: {
158: unsigned char b = 0;
159: register char c;
160: int i;
161:
162: for (i=2; i; i--) {
163: c = *s++;
164: if ((c >= '0') && (c <= '9'))
165: b = (b<<4) + (c - '0');
166: else if ((c >= 'A') && (c <= 'F'))
167: b = (b<<4) + 10 + (c - 'A');
168: else if ((c >= 'a') && (c <= 'f'))
169: b = (b<<4) + 10 + (c - 'a');
170: else
171: return 0; /* bad data */
172: }
173: return b;
174: }
175:
176: /*
177: * fatal error. never returns.
178: */
179: fatal(msg, p1, p2, p3, p4)
180: char *msg;
181: {
182: fprintf(stderr, "%s: %s:", myname, currentfont);
183: fprintf(stderr, msg, p1, p2, p3, p4);
184: if (linenum)
185: fprintf(stderr, " at line %d\n", linenum);
186: else
187: fprintf(stderr, "\n");
188: exit(1);
189: }
190:
191: /*
192: * these properties will be generated if not already present.
193: */
194: #define NULLPROP (FontPropPtr)0;
195:
196: FontPropPtr pointSizeProp = NULLPROP;
197: FontPropPtr familyProp = NULLPROP;
198: FontPropPtr resolutionProp = NULLPROP;
199: FontPropPtr xHeightProp = NULLPROP;
200: FontPropPtr weightProp = NULLPROP;
201: FontPropPtr quadWidthProp = NULLPROP;
202: #define GENPROPS 6
203:
204: BOOL haveFontAscent = FALSE;
205: BOOL haveFontDescent = FALSE;
206:
207: /*
208: * check for known property values
209: */
210:
211: int
212: specialproperty(pfp, pfi)
213: FontPropPtr pfp;
214: FontInfoPtr pfi;
215: {
216: if (streq(pfp->name, "FONT_ASCENT") && !pfp->indirect)
217: {
218: pfi->fontAscent = pfp->value;
219: haveFontAscent = TRUE;
220: return 0;
221: }
222: else if (streq(pfp->name, "FONT_DESCENT") && !pfp->indirect)
223: {
224: pfi->fontDescent = pfp->value;
225: haveFontDescent = TRUE;
226: return 0;
227: }
228: else if (streq(pfp->name, "DEFAULT_CHAR") && !pfp->indirect)
229: {
230: pfi->chDefault = pfp->value;
231: return 0;
232: }
233: else if (streq(pfp->name , "POINT_SIZE"))
234: pointSizeProp = pfp;
235: else if (streq(pfp->name , "FAMILY_NAME"))
236: familyProp = pfp;
237: else if (streq(pfp->name , "RESOLUTION"))
238: resolutionProp = pfp;
239: else if (streq(pfp->name , "X_HEIGHT"))
240: xHeightProp = pfp;
241: else if (streq(pfp->name , "WEIGHT"))
242: weightProp = pfp;
243: else if (streq(pfp->name , "QUAD_WIDTH"))
244: quadWidthProp = pfp;
245: return 1;
246: }
247:
248: computeweight(font)
249: TempFont *font;
250: {
251: int i;
252: int width = 0, area, bits = 0;
253: register b;
254: register unsigned char *p;
255:
256: for (i=0; i<n1dChars(font->pFI); i++)
257: width += font->pCI[i].metrics.characterWidth;
258: area = width*(font->pFI->fontAscent+font->pFI->fontDescent);
259: for (i=0,p=font->pGlyphs; i<font->pFI->maxbounds.byteOffset; i++,p++)
260: for (b=(*p); b; b >>= 1)
261: bits += b & 1;
262: return (int)((bits*1000.0)/area);
263: }
264:
265: main(argc, argv)
266: int argc;
267: char * argv[];
268: {
269: TempFont font;
270: FontInfoRec fi;
271: CharInfoPtr cinfos[INDICES]; /* rows waiting to be allocated */
272: int bytesGlAlloced = 1024; /* amount now allocated for glyphs
273: (bytes) */
274: unsigned char *pGl = (unsigned char *)malloc( bytesGlAlloced);
275: int bytesGlUsed = 0;
276: int nGl = 0;
277: int nchars;
278: float pointSize;
279: int xRes, yRes;
280: char linebuf[BUFSIZ];
281: char namebuf[100];
282: char family[100];
283: char *bdffile = NULL;
284: unsigned int attributes;
285: int digitWidths = 0, digitCount = 0, ex = 0;
286: int char_row, char_col;
287: int i;
288: CharInfoRec emptyCharInfo;
289:
290: myname = argv[0];
291: argc--, argv++;
292: while (argc--) {
293: if (argv[0][0] == '-') {
294: switch (argv[0][1]) {
295: case 'p': /* Pad Glyphs to Word boundaries */
296: switch (argv[0][2]) {
297: default:
298: goto usage;
299: case '1':
300: case '2':
301: case '4':
302: case '8':
303: glyphPad = argv[0][2] - '0';
304: break;
305: }
306: or_glyphPad = 1;
307: break;
308: case 'm':
309: or_bitorder = 1;
310: bitorder = MSBFirst;
311: break;
312:
313: case 'l':
314: or_bitorder = 1;
315: bitorder = LSBFirst;
316: break;
317:
318: default:
319: fprintf(stderr, "bad flag -%c\n", argv[0][1]);
320: break;
321: }
322: } else {
323: if (bdffile)
324: usage:
325: fatal("usage: %s [-p#] [bdf file]", myname);
326: bdffile = argv[0];
327: if (freopen( bdffile, "r", stdin) == NULL)
328: fatal("could not open file %s\n", bdffile);
329: }
330: argv++;
331: }
332: emptyCharInfo.metrics.leftSideBearing = 0;
333: emptyCharInfo.metrics.rightSideBearing = 0;
334: emptyCharInfo.metrics.ascent = 0;
335: emptyCharInfo.metrics.descent = 0;
336: emptyCharInfo.metrics.characterWidth = 0;
337: emptyCharInfo.byteOffset = 0;
338: emptyCharInfo.exists = FALSE;
339: emptyCharInfo.metrics.attributes = 0;
340:
341: for (i = 0; i < INDICES; i++)
342: cinfos[i] = (CharInfoPtr)NULL;
343:
344: font.pFI = &fi;
345: fi.firstRow = INDICES;
346: fi.lastRow = 0;
347: fi.chFirst = INDICES;
348: fi.chLast = 0;
349: fi.pixDepth = 1;
350: fi.glyphSets = 1;
351: fi.chDefault = 0; /* may be overridden by a property */
352:
353: getline(linebuf);
354:
355: if ((sscanf(linebuf, "STARTFONT %s", namebuf) != 1) ||
356: !streq(namebuf, "2.1"))
357: fatal("bad 'STARTFONT'");
358: getline(linebuf);
359:
360: if (sscanf(linebuf, "FONT %s", family) != 1)
361: fatal("bad 'FONT'");
362: getline(linebuf);
363:
364: if (!prefix(linebuf, "SIZE"))
365: fatal("missing 'SIZE'");
366: if ((sscanf(linebuf, "SIZE %f%d%d", &pointSize, &xRes, &yRes) != 3))
367: fatal("bad 'SIZE'");
368: if (xRes != yRes)
369: fatal("x and y resolution must be equal");
370: getline(linebuf);
371:
372: if (!prefix(linebuf, "FONTBOUNDINGBOX"))
373: fatal("missing 'FONTBOUNDINGBOX'");
374: getline(linebuf);
375:
376: if (prefix(linebuf, "STARTPROPERTIES")) {
377: int nprops;
378: FontPropPtr pfp;
379:
380: sscanf(linebuf, "%*s%d", &nprops);
381: fi.nProps = nprops;
382: pfp = (FontPropPtr)malloc((nprops+GENPROPS) * sizeof(FontPropRec));
383: font.pFP = pfp;
384: getline(linebuf);
385: while((nprops-- > 0) && !prefix(linebuf, "ENDPROPERTIES")) {
386: if (sscanf(linebuf, "%s%d", namebuf, &pfp->value) == 2) {
387: /* integer value */
388: pfp->indirect = FALSE;
389: } else {
390: /* value is (possibly quoted) string */
391: pfp->indirect = TRUE;
392: pfp->value = (INT32)remember(linebuf+strlen(namebuf)+1);
393: }
394: pfp->name = (CARD32)remember(namebuf);
395: if (specialproperty(pfp, &fi))
396: pfp++;
397: else
398: fi.nProps--;
399: getline(linebuf);
400: }
401: if (!prefix(linebuf, "ENDPROPERTIES"))
402: fatal("missing 'ENDPROPERTIES'");
403: if (!haveFontAscent || !haveFontDescent)
404: fatal("must have 'FONT_ASCENT' and 'FONT_DESCENT' properties");
405: if (nprops != -1)
406: fatal("%d too few properties", nprops+1);
407: if (!familyProp) {
408: fi.nProps++;
409: pfp->name = (CARD32)("FAMILY_NAME");
410: pfp->value = (INT32)family;
411: pfp->indirect = TRUE;
412: familyProp = pfp++;
413: }
414: if (!pointSizeProp) {
415: fi.nProps++;
416: pfp->name = (CARD32)("POINT_SIZE");
417: pfp->value = (INT32)(pointSize*10.0);
418: pfp->indirect = FALSE;
419: pointSizeProp = pfp++;
420: }
421: if (!weightProp) {
422: fi.nProps++;
423: pfp->name = (CARD32)("WEIGHT");
424: pfp->value = -1; /* computed later */
425: pfp->indirect = FALSE;
426: weightProp = pfp++;
427: }
428: if (!resolutionProp) {
429: fi.nProps++;
430: pfp->name = (CARD32)("RESOLUTION");
431: pfp->value = (INT32)((xRes*100.0)/72.27);
432: pfp->indirect = FALSE;
433: resolutionProp = pfp++;
434: }
435: if (!xHeightProp) {
436: fi.nProps++;
437: pfp->name = (CARD32)("X_HEIGHT");
438: pfp->value = -1; /* computed later */
439: pfp->indirect = FALSE;
440: xHeightProp = pfp++;
441: }
442: if (!quadWidthProp) {
443: fi.nProps++;
444: pfp->name = (CARD32)("QUAD_WIDTH");
445: pfp->value = -1; /* computed later */
446: pfp->indirect = FALSE;
447: quadWidthProp = pfp++;
448: }
449: } else { /* no properties */
450: fatal("missing 'PROPERTIES'");
451: }
452: getline(linebuf);
453:
454: if (!prefix(linebuf, "CHARS"))
455: fatal("missing 'CHARS'");
456: sscanf(linebuf, "%*s%d", &nchars);
457: getline(linebuf);
458:
459: while ((nchars-- > 0) && prefix(linebuf, "STARTCHAR")) {
460: int t;
461: int ix; /* counts bytes in a glyph */
462: int wx; /* x component of width */
463: int bw; /* bounding-box width */
464: int bh; /* bounding-box height */
465: int bl; /* bounding-box left */
466: int bb; /* bounding-box bottom */
467: int enc, enc2; /* encoding */
468: char *p; /* temp pointer into linebuf */
469: int bytesperrow, row;
470: char charName[100];
471:
472: if (sscanf(linebuf, "STARTCHAR %s", charName) != 1)
473: fatal("bad character name");
474:
475: getline( linebuf);
476: if ((t=sscanf(linebuf, "ENCODING %d %d", &enc, &enc2)) < 1)
477: fatal("bad 'ENCODING'");
478: if (t == 2 && enc == -1)
479: enc = enc2;
480: if (enc == -1) {
481: fprintf(stderr,
482: "character '%s'with encoding = -1 ignored at line %d\n",
483: charName, linenum);
484: do {
485: char *s = getline(linebuf);
486: if (!s)
487: fatal("Unexpected EOF");
488: } while (!prefix(linebuf, "ENDCHAR"));
489: getline(linebuf);
490: continue;
491: }
492: if (enc > MAXENCODING)
493: fatal("character '%s' has encoding(=%d) too large", charName, enc);
494: char_row = (enc >> 8) & 0xFF;
495: char_col = enc & 0xFF;
496: fi.firstRow = MIN(fi.firstRow, char_row);
497: fi.lastRow = MAX(fi.lastRow, char_row);
498: fi.chFirst = MIN(fi.chFirst, char_col);
499: fi.chLast = MAX(fi.chLast, char_col);
500: if (!cinfos[char_row])
501: {
502: cinfos[char_row] =
503: (CharInfoPtr)malloc(sizeof(CharInfoRec)*INDICES);
504: bzero(cinfos[char_row], sizeof(CharInfoRec)*INDICES);
505: }
506:
507: getline( linebuf);
508: if (!prefix(linebuf, "SWIDTH"))
509: fatal("bad 'SWIDTH'");
510:
511: getline( linebuf);
512: sscanf( linebuf, "DWIDTH %d %*d", &wx);
513:
514: getline( linebuf);
515: sscanf( linebuf, "BBX %d %d %d %d", &bw, &bh, &bl, &bb);
516:
517: getline( linebuf);
518: if (prefix(linebuf, "ATTRIBUTES"))
519: {
520: for (p = linebuf + strlen("ATTRIBUTES ");
521: (*p == ' ') || (*p == '\t');
522: p ++)
523: /* empty for loop */ ;
524: attributes = hexbyte(p)<< 8 + hexbyte(p+2);
525: getline( linebuf); /* set up for BITMAP which follows */
526: }
527: else
528: attributes = 0;
529: if (!prefix(linebuf, "BITMAP"))
530: fatal("missing 'BITMAP'");
531:
532: /* collect data for generated properties */
533: if ((strlen(charName) == 1)){
534: if ((charName[0] >='0') && (charName[0] <= '9')) {
535: digitWidths += wx;
536: digitCount++;
537: } else if (charName[0] == 'x') {
538: ex = (bh+bb)<=0? bh : bh+bb ;
539: }
540: }
541:
542: cinfos[char_row][char_col].metrics.leftSideBearing = bl;
543: cinfos[char_row][char_col].metrics.rightSideBearing = bl+bw;
544: cinfos[char_row][char_col].metrics.ascent = bh+bb;
545: cinfos[char_row][char_col].metrics.descent = -bb;
546: cinfos[char_row][char_col].metrics.characterWidth = wx;
547: cinfos[char_row][char_col].byteOffset = bytesGlUsed;
548: cinfos[char_row][char_col].exists = FALSE; /* overwritten later */
549: cinfos[char_row][char_col].metrics.attributes = attributes;
550:
551: bytesperrow = GLWIDTHBYTESPADDED(bw,glyphPad);
552: for (row=0; row < bh; row++) {
553: getline(linebuf);
554: p = linebuf;
555: for ( ix=0; ix < bytesperrow; ix++)
556: {
557: if ( bytesGlUsed >= bytesGlAlloced)
558: pGl = (unsigned char *)realloc( pGl, (bytesGlAlloced *= 2));
559: pGl[bytesGlUsed] = hexbyte(p);
560: p += 2;
561: bytesGlUsed++;
562: }
563: /*
564: * Now pad the glyph row our pad boundary.
565: */
566: bytesGlUsed = GLWIDTHBYTESPADDED(bytesGlUsed<<3,glyphPad);
567: }
568: getline( linebuf);
569: if (!prefix(linebuf, "ENDCHAR"))
570: fatal("missing 'ENDCHAR'");
571: nGl++;
572: getline( linebuf); /* get STARTCHAR or ENDFONT */
573: }
574:
575: if (!prefix(linebuf, "ENDFONT"))
576: fatal("missing 'ENDFONT'");
577: if (nchars != -1)
578: fatal("%d too few characters", nchars+1);
579: if (nGl == 0)
580: fatal("No characters with valid encodings");
581:
582: fi.maxbounds.byteOffset = bytesGlUsed;
583: font.pGlyphs = pGl;
584:
585: font.pCI = (CharInfoPtr)malloc(sizeof(CharInfoRec)*n2dChars(font.pFI));
586: i = 0;
587: for (char_row = fi.firstRow; char_row <= fi.lastRow; char_row++)
588: {
589: if (!cinfos[char_row])
590: for (char_col = fi.chFirst; char_col <= fi.chLast; char_col++)
591: {
592: font.pCI[i] = emptyCharInfo;
593: i++;
594: }
595: else
596: for (char_col = fi.chFirst; char_col <= fi.chLast; char_col++)
597: {
598: font.pCI[i] = cinfos[char_row][char_col];
599: i++;
600: }
601: }
602: computeNaccelerators(&font);
603:
604: /* generate properties */
605: if (xHeightProp && (xHeightProp->value == -1))
606: xHeightProp->value = ex? ex : fi.minbounds.metrics.ascent;
607: if (quadWidthProp && (quadWidthProp->value == -1))
608: quadWidthProp->value = digitCount?
609: (INT32)((float)digitWidths/(float)digitCount) :
610: (fi.minbounds.metrics.characterWidth+fi.maxbounds.metrics.characterWidth)/2;
611: if (weightProp && (weightProp->value == -1))
612: weightProp->value = computeweight(&font);
613:
614: if (bitorder == LSBFirst)
615: bitorderinvert( pGl, pGl, bytesGlUsed);
616: #ifdef UNSPECIFIED
617: if (!or_glyphPad || !or_bitorder) {
618: fprintf(stderr, "%s: ", currentfont);
619: if (!or_glyphPad && !or_bitorder)
620: fprintf(stderr, "bit order/pad unspecified:\n\t");
621: else if (!or_glyphPad)
622: fprintf(stderr, "pad unspecified:\n\t");
623: else
624: fprintf(stderr, "bit order unspecified:\n\t");
625: fprintf(stderr, "using ");
626:
627: if (!or_bitorder)
628: fprintf(stderr, "order=%s",
629: bitorder == LSBFirst ? "LSBFirst" : "MSBFirst");
630: if (!or_glyphPad && !or_bitorder)
631: fprintf(stderr, ", ");
632: if (!or_glyphPad)
633: fprintf(stderr, "pad=%d", glyphPad);
634: fprintf(stderr, "\n");
635: }
636: #endif
637:
638: WriteNFont( stdout, &font);
639: exit(0);
640: }
641:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.