|
|
1.1 root 1: /*
2: * Copyright (c) 1984, 1985, 1986 Xerox Corp.
3: *
4: * Handle troff metrics here.
5: *
6: * note that Troff uses "fat points" of which there are exactly 72 per inch.
7: *
8: * HISTORY
9: * 15-Apr-86 Lee Moore (lee) at Xerox Webster Research Center
10: * Now prints out the number of special character names in the
11: * DESC file.
12: *
13: * Nov, 1985 Lee Moore, Xerox Webster Research Center
14: * Created.
15: */
16:
17: #include <stdio.h>
18: #include <math.h>
19: #include "stack.h"
20: #include "token.h"
21: #include "config.h"
22: #include "ipmetrics.h"
23: #include "troff.h"
24: #include "strings.h"
25:
26: #define TRUE 1
27: #define FALSE 0
28:
29:
30: /* the following value should be choosen so that none of the widths
31: * is greater than 256
32: */
33: #define UNITWIDTH 5 /* was 10 */
34:
35:
36: #define MAXSPECIALNAMES 221 /* maximum number of special characters.
37: * this constant is fixed in Troff
38: */
39:
40: #define public
41: #define private static
42:
43: public char *malloc();
44:
45: public char *DeviceName,
46: *LibraryDirectory;
47:
48: struct CharElement {
49: struct CharElement *Next;
50: char CharName[3]; };
51:
52: private struct CharElement *CharSet = NULL;
53:
54: private int SetOfPointSizes[MAXPOINTSIZE],
55: FontCount = 0;
56:
57:
58: /*
59: * Clean up our state
60: */
61: public
62: CleanUpTroff(configChain)
63: struct FontConfig *configChain; {
64: struct FontConfig *p;
65:
66: WriteDescFile(configChain);
67: WriteFontMapFile(configChain);
68: WriteInstallFile(configChain);
69: WriteCleanUpFile(configChain);
70:
71: /* if we haven't seen a font, say so! */
72: for( p = configChain; p != NULL; p = p->Next )
73: if( !p->SeenFlag )
74: printf("couldn't find: %s/%s/%s\n",
75: p->FontPt1, p->FontPt2, p->FontPt3);
76: }
77:
78:
79: /*
80: * Write the DESC file
81: */
82: private
83: WriteDescFile(configChain)
84: struct FontConfig *configChain; {
85: int i;
86: FILE *deviceFile;
87: struct FontConfig *p;
88:
89: if( (deviceFile = fopen("DESC", "w")) == NULL ) {
90: printf("can't open 'DESC' for writing\n");
91: exit(1); }
92:
93: /* output boiler plate */
94: fprintf(deviceFile, "# describe the '%s' interpress device\n", DeviceName);
95: fprintf(deviceFile, "res %d\n", MICAS_PER_INCH);
96: fprintf(deviceFile, "hor 1\n");
97: fprintf(deviceFile, "vert 1\n");
98: fprintf(deviceFile, "unitwidth %d\n", UNITWIDTH);
99: fprintf(deviceFile, "paperwidth %d\n", PAGE_WIDTH_IN_MICAS);
100: fprintf(deviceFile, "paperlength %d\n", PAGE_HEIGHT_IN_MICAS);
101:
102: /* output sizes */
103: fprintf(deviceFile, "sizes ");
104:
105: for( i = 1; i < MAXPOINTSIZE; i++ )
106: if( SetOfPointSizes[i] )
107: fprintf(deviceFile," %d", i);
108:
109: fprintf(deviceFile, " 0\n");
110:
111: /* output fonts */
112: fprintf(deviceFile, "fonts %d ", FontCount);
113:
114: for( p = configChain; p != NULL; p = p->Next )
115: if( p->SeenFlag )
116: fprintf(deviceFile, "%s ", p->TargetName);
117:
118: fprintf(deviceFile, "\n");
119: PrintCharSet(deviceFile);
120: (void) fclose(deviceFile); }
121:
122:
123:
124: /*
125: * Write the file that shows the relationship between Troff names and
126: * Interpress names
127: */
128: private
129: WriteFontMapFile(configChain)
130: struct FontConfig *configChain; {
131: FILE *fontMapFile;
132: struct FontConfig *p;
133:
134: if( (fontMapFile = fopen(FONTMAPFILENAME, "w")) == NULL ) {
135: fprintf(stderr, "can't open the file '%s' for writing\n", FONTMAPFILENAME);
136: return; }
137:
138: for( p = configChain; p != NULL; p = p->Next )
139: if( p->SeenFlag )
140: fprintf(fontMapFile, "%s %s/%s/%s\n", p->TargetName,
141: p->FontPt1, p->FontPt2, p->FontPt3);
142:
143: (void) fclose(fontMapFile);
144: (void) chmod(FONTMAPFILENAME, 0755); }
145:
146:
147: /*
148: * Create a shell script that will install all these things
149: */
150: private
151: WriteInstallFile(configChain)
152: struct FontConfig *configChain; {
153: FILE *installFile;
154: struct FontConfig *p;
155:
156: if( (installFile = fopen(INSTALLNAME, "w")) == NULL ) {
157: fprintf(stderr, "can't open the file 'install' for writing\n");
158: return; }
159:
160: fprintf(installFile, "#! /bin/sh\n");
161: fprintf(installFile, "if test ! -d %s/fonts/%s\n", LibraryDirectory, DeviceName);
162: fprintf(installFile, " then\n");
163: fprintf(installFile, " mkdir %s/fonts/%s\n", LibraryDirectory, DeviceName);
164: fprintf(installFile, " fi\n");
165: fprintf(installFile, "if test ! -d %s/fonts/%s/devipress\n", LibraryDirectory, DeviceName);
166: fprintf(installFile, " then\n");
167: fprintf(installFile, " mkdir %s/fonts/%s/devipress\n", LibraryDirectory, DeviceName);
168: fprintf(installFile, " fi\n");
169:
170:
171: for( p = configChain; p != NULL; p = p->Next )
172: if( p->SeenFlag )
173: fprintf(installFile, "cp %s %s/fonts/%s/devipress\n",
174: p->TargetName, LibraryDirectory, DeviceName);
175:
176: fprintf(installFile, "cp DESC %s/fonts/%s/devipress\n", LibraryDirectory,
177: DeviceName);
178: fprintf(installFile, "cp %s %s/fonts/%s/devipress\n", FONTMAPFILENAME,
179: LibraryDirectory, DeviceName);
180: fprintf(installFile, "cd %s/fonts/%s/devipress\n", LibraryDirectory,
181: DeviceName);
182: (void) fprintf(installFile, "makedev DESC\n");
183: (void) fprintf(installFile, "makextdev DESC\n");
184: (void) fclose(installFile);
185: (void) chmod(INSTALLNAME, 0755); }
186:
187:
188: /*
189: * write a file that rm's all the files created by this program
190: */
191:
192: private
193: WriteCleanUpFile(configChain)
194: struct FontConfig *configChain; {
195: FILE *cleanupFile;
196: struct FontConfig *p;
197:
198: if( (cleanupFile = fopen(CLEANUPNAME, "w")) == NULL ) {
199: fprintf(stderr, "can't open the file 'cleanup' for writing\n");
200: return; }
201:
202: fprintf(cleanupFile, "#! /bin/sh\n");
203:
204: for( p = configChain; p != NULL; p = p->Next )
205: if( p->SeenFlag )
206: fprintf(cleanupFile, "rm %s\n", p->TargetName);
207:
208: fprintf(cleanupFile, "rm DESC\n");
209: fprintf(cleanupFile, "rm %s\n", INSTALLNAME);
210: fprintf(cleanupFile, "rm %s\n", FONTMAPFILENAME);
211: fprintf(cleanupFile, "rm %s\n", CLEANUPNAME);
212: (void) fclose(cleanupFile);
213: (void) chmod(CLEANUPNAME, 0755); }
214:
215: /*
216: * called once per font on the stack
217: */
218:
219: public
220: PerTroffFont(configChain, fontDescVec)
221: struct FontConfig *configChain;
222: unsigned char *fontDescVec; {
223: unsigned char *charMetricsProperty,
224: *metricsProperty,
225: *width,
226: *charMetric;
227: char iSender[MAXTOKENSIZE],
228: iCharName[MAXTOKENSIZE],
229: fileType[MAXTOKENSIZE],
230: *fontName[3],
231: iCharSet[MAXTOKENSIZE],
232: iCharCode[MAXTOKENSIZE];
233: FILE *descFile,
234: *modelFile;
235: struct FontConfig *p;
236: struct TokenState *ts;
237: int charSet,
238: charNumber,
239: charIndex,
240: xWidth;
241:
242: if( !GetFontNameProperty(fontDescVec, fontName) ) {
243: fprintf(stderr, "ipmetrics: can't get font name\n");
244: return;
245: }
246:
247: if( (charMetricsProperty = GetStringProp("characterMetrics", fontDescVec))
248: == NULL ) {
249: printf("ipmetrics: can't find 'characterMetrics' property\n");
250: return; }
251:
252: for( p = configChain; p != NULL; p = p->Next ) {
253: if( !(strcmp(p->FontPt1, fontName[0]) == 0 &&
254: strcmp(p->FontPt2, fontName[1]) == 0 &&
255: strcmp(p->FontPt3, fontName[2]) == 0) )
256: continue;
257:
258: if( (descFile = fopen(p->TargetName , "w")) == NULL ) {
259: printf("ipmetrics: can't open %s for writing\n", p->TargetName);
260: return;}
261:
262: printf("\t%s\n", p->TargetName);
263:
264: if( (modelFile = fopen(p->MapFile, "r")) == NULL ) {
265: printf("ipmetrics: can't open %s for reading\n", p->MapFile);
266: return;}
267:
268: p->SeenFlag = TRUE;
269: FontCount++;
270:
271: ts = InitTokenStream(modelFile);
272:
273: fprintf(descFile, "#\n");
274: fprintf(descFile, "# %s/%s/%s for Interpress device %s\n", p->FontPt1, p->FontPt2, p->FontPt3, DeviceName);
275: fprintf(descFile, "name %s\n", p->TargetName);
276: fprintf(descFile, "internalname %d\n", FontCount);
277:
278: GetToken(ts, fileType, MAXTOKENSIZE);
279:
280: if( strcmp(fileType, "special") == 0 )
281: fprintf(descFile, "special\n");
282: else
283: ProcessTroffLigatures(charMetricsProperty, descFile);
284:
285: fprintf(descFile, "charset\n");
286:
287: while( !EndOfFile(ts) ) {
288: GetToken(ts, iCharSet, MAXTOKENSIZE);
289:
290: if( sscanf(iCharSet, "%o", &charSet) != 1 )
291: printf("ipmetrics: couldn't convert iCharSet number. Token was: %s\n", iCharSet);
292:
293: if( EndOfLine(ts) ) {
294: printf("ipmetrics: premature end of line in map file: %s!\n", p->MapFile);
295: printf("\tlast token was iCharSet: `%s'\n", iCharSet);
296: continue; }
297:
298: GetToken(ts, iCharCode, MAXTOKENSIZE);
299:
300: if( sscanf(iCharCode, "%o", &charNumber) != 1 )
301: printf("ipmetrics: couldn't convert iCharCode. Token was: %s\n", iCharCode);
302:
303: if( EndOfLine(ts) ) {
304: printf("ipmetrics: premature end of line in map file: %s!\n", p->MapFile);
305: printf("\tlast token was iCharCode: `%s'\n", iCharCode);
306: continue; }
307:
308: GetToken(ts, iSender, MAXTOKENSIZE);
309:
310: if( EndOfLine(ts) ) {
311: printf("ipmetrics: premature end of line in map file: %s!\n", p->MapFile);
312: printf("\tlast token was iSender: `%s'\n", iSender);
313: continue; }
314:
315: GetToken(ts, iCharName, MAXTOKENSIZE);
316: charIndex = Make16BitChar(charSet, charNumber);
317:
318: /* skip the rest of this loop if it's not in this font */
319: if( (charMetric =
320: GetIntegerProp(charIndex, charMetricsProperty)) == NULL ) {
321: EatRestOfLine(ts);
322: continue; }
323:
324: if( (width = GetStringProp("widthX", charMetric)) == NULL ){
325: printf("ipmetrics: can't find widthX property of %d\n",
326: charIndex);
327: EatRestOfLine(ts);
328: continue;}
329:
330: if( gettype(width) != type_number ) {
331: printf("ipmetrics: width not of type number for %d\n",
332: charIndex);
333: EatRestOfLine(ts);
334: continue;}
335:
336: if( getsubtype(width) != subtype_rational ) {
337: printf("ipmetrics: width not of subtype rational for %d\n",
338: charIndex);
339: EatRestOfLine(ts);
340: continue;}
341:
342: xWidth = (getnumerator(width)*UNITWIDTH*MICAS_PER_INCH +
343: (getdenominator(width) * POINTS_PER_INCH)/2)/
344: (getdenominator(width) * POINTS_PER_INCH);
345:
346: if( xWidth >= 256 )
347: printf("ipmetrics: warning width >= 256\n");
348:
349: fprintf(descFile, "%s\t%d\t%s\t", iCharName, xWidth,
350: iSender);
351:
352: if( charIndex < 0377 )
353: fprintf(descFile, "%d\n", charIndex);
354: else
355: fprintf(descFile, "0377\t0%o\n", charIndex);
356:
357: CheckForSpecialness(iCharName);
358:
359: while( !EndOfLine(ts) ) {
360: GetToken(ts, iCharName, MAXTOKENSIZE);
361: fprintf(descFile, "%s\t\"\n", iCharName);
362: CheckForSpecialness(iCharName);}}
363:
364: CloseTokenStream(ts);
365: (void) fclose(descFile);
366: (void) fclose(modelFile);
367: }
368:
369: if( (metricsProperty = GetStringProp("metrics", fontDescVec))
370: != NULL ) {
371: unsigned char *easyProperty;
372:
373: if( (easyProperty = GetStringProp("easy", metricsProperty))
374: != NULL )
375: ProcessEasy(easyProperty);
376: }
377: }
378:
379:
380: /*
381: * read the rest of the tokens off the current line
382: */
383: EatRestOfLine(ts)
384: struct TokenState *ts; {
385: char byteBucket[MAXTOKENSIZE];
386:
387: while( !EndOfLine(ts) )
388: GetToken(ts, byteBucket, MAXTOKENSIZE); }
389:
390: /*
391: * assume that the font is in XC1-1-1 standard and find the ligatures
392: * that troff wants
393: */
394:
395: private
396: ProcessTroffLigatures(charMetricsVec, descFile)
397: unsigned char *charMetricsVec;
398: FILE *descFile; {
399: char ligatureNames[21];
400:
401: (void) strcpy(ligatureNames, "");
402:
403: if( GetIntegerProp(Make16BitChar(0360, 044), charMetricsVec) != NULL )
404: (void) strcat(ligatureNames, " fi");
405:
406: if( GetIntegerProp(Make16BitChar(0360, 045), charMetricsVec) != NULL )
407: (void) strcat(ligatureNames, " fl");
408:
409: if( GetIntegerProp(Make16BitChar(0360, 041), charMetricsVec) != NULL )
410: (void) strcat(ligatureNames, " ff");
411:
412: if( GetIntegerProp(Make16BitChar(0360, 042), charMetricsVec) != NULL )
413: (void) strcat(ligatureNames, " ffi");
414:
415: if( GetIntegerProp(Make16BitChar(0360, 043), charMetricsVec) != NULL )
416: (void) strcat(ligatureNames, " ffl");
417:
418: if( strcmp(ligatureNames, "") != 0 )
419: fprintf(descFile, "ligatures %s 0\n", ligatureNames);}
420:
421: /*
422: * Check to see if a character is special and add it to the "charset"
423: * in the DESC file if it is.
424: */
425:
426: private
427: CheckForSpecialness(s)
428: char *s; {
429: /* right now, if it two characters long, then it must be special */
430: if( strlen(s) == 2 )
431: AddToCharSet(s); }
432:
433: /*
434: * add a special character to the set of special characters. The set
435: * is implemented as a linked list.
436: */
437:
438: private
439: AddToCharSet(s)
440: char *s; {
441: struct CharElement **p,
442: *q;
443:
444: p = &CharSet;
445:
446: while( *p != NULL ) {
447: if( strcmp(s, (*p)->CharName) == 0 )
448: return;
449:
450: p = &(*p)->Next; }
451:
452: q = (struct CharElement *) malloc((unsigned) sizeof(struct CharElement));
453: (void) strcpy(q->CharName, s);
454: q->Next = NULL;
455: *p = q; }
456:
457: /*
458: * print out the list of special characters to the DESC file
459: */
460:
461: private
462: PrintCharSet(file)
463: FILE *file; {
464: int itemsPerLine,
465: total; /* total number of special chars */
466: struct CharElement *p;
467:
468: /* test to see if there is a char. set. ditroff requires this!
469: * you just can't have a null charset! */
470: if( CharSet == NULL )
471: return;
472:
473: fprintf(file, "charset\n");
474: itemsPerLine = 0;
475: total = 0;
476:
477: for( p = CharSet; p != NULL; p = p->Next ) {
478: fprintf(file, " %s", p->CharName);
479: total++;
480:
481: if( itemsPerLine++ > 20 ) {
482: (void) fputc('\n', file);
483: itemsPerLine = 0; } }
484:
485: if( itemsPerLine != 0 )
486: (void) fputc('\n', file);
487:
488: printf("\tthere were %d special characters (out of a max of 221)\n", total); }
489:
490: /*
491: * Process the "easy" property of the "metrics" property. This
492: * will tell us what (viewing) sizes the font is available in.
493: */
494:
495: private
496: ProcessEasy(easyProperty)
497: unsigned char *easyProperty; {
498: int depth,
499: i;
500: unsigned char **array;
501:
502: if( gettype(easyProperty) != type_vector ||
503: getsubtype(easyProperty) != subtype_general ) {
504: printf("ipmetrics: wrong vector type in 'easy'\n");
505: return; }
506:
507: depth = getdepth(easyProperty);
508: array = getvector(easyProperty);
509:
510: for( i = 0; i < depth; i++ ) {
511: double *transform,
512: fPointSize;
513: int iPointSize;
514:
515: if( gettype(array[i]) != type_transformation ) {
516: printf("ipmetrics: transforms not found in 'easy'\n");
517: return; }
518:
519: transform = gettransformation(array[i]);
520:
521: if( transform[0] != transform[4] ) {
522: printf("ipmetrics: only square transforms in 'easy'\n");
523: return; }
524:
525: if( transform[1] != 0 || transform[2] != 0 ||
526: transform[3] != 0 || transform[5] != 0 ) {
527: printf("ipmetrics: troff doesn't support rotations\n");
528: return; }
529:
530: fPointSize = transform[0]*72*100000/2540;
531: iPointSize = fPointSize + 0.5;
532:
533: if( fabs(fPointSize - iPointSize) > .25 ) {
534: printf("ipmetrics: troff doesn't support fractional points: %f6.2\n", fPointSize);
535: return; }
536:
537: SetOfPointSizes[iPointSize] = 1;
538: free((char *) transform);
539: }
540:
541: free((char *) array);
542: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.