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