|
|
1.1 ! root 1: ! 2: ! 3: /* ! 4: * ! 5: * Reads specially formatted ASCII files, called control files, and uses ! 6: * them to build raster and font files that can be used by troff and its ! 7: * post-processors. The program reads raster files in Imagen's format from ! 8: * directory *rastdir and uses them, along with the information in the ! 9: * the control files to build new raster files and also font and device ! 10: * files for troff. The ASCII control files must list a target device. ! 11: * The new raster files will be put in directory *nrastdir/"rast"*device ! 12: * and the new font files will go in *fontdir/"dev"*device. ! 13: * ! 14: * Individual fonts or sizes can be selected using the -f and -s options. ! 15: * If they're not used all the font 'build' sections in the ASCII control ! 16: * files will be processed for all the sizes listed under 'sizes'. ASCII ! 17: * files will only be built when the current size is equal to the value ! 18: * set in unitwidth. ! 19: * ! 20: * The raster source, new raster, and new font directories can be selected ! 21: * using options -S, -R, and -F respectively. By default they're all set to ! 22: * ".". ! 23: * ! 24: * As an example I used this program and the RASTi300 file to build the ! 25: * tables in this package. The command line was, ! 26: * ! 27: * ! 28: * buildrast -S /usr/spool/imagen_src/fonts/raster/300 RASTi300 ! 29: * ! 30: * ! 31: * The original raster files that we got from Imagen were kept in directory ! 32: * /usr/spool/imagen_src/fonts/raster/300. ! 33: * ! 34: */ ! 35: ! 36: ! 37: #include <stdio.h> ! 38: #include <ctype.h> ! 39: #include <fcntl.h> ! 40: ! 41: #include "gen.h" /* general purpose definitions */ ! 42: #include "ext.h" /* external variable declarations */ ! 43: #include "init.h" /* printer and system definitions */ ! 44: #include "rast.h" /* raster file definitions */ ! 45: #include "buildrast.h" /* definitions for building files */ ! 46: ! 47: ! 48: char *nrastdir = "."; /* new raster files go here - sort of */ ! 49: ! 50: FILE *fp_in; /* current ASCII control file */ ! 51: char buff[100]; /* buffer for reads from fp_in */ ! 52: ! 53: int dodesc = ON; /* build troff's DESC file? */ ! 54: int gotspecial = FALSE; /* recorded all special characters */ ! 55: int dofont = ON; /* same but for ASCII font files */ ! 56: ! 57: char device[20] = ""; /* everything's built for this printer */ ! 58: ! 59: Charset charset[256]; /* records all special character names */ ! 60: char *fontlist[50]; /* only do stuff for these fonts */ ! 61: int sizelist[50]; /* and these point sizes */ ! 62: int unitwidth = -1; /* troff tables built from this size */ ! 63: int res = -1; /* target device's resolution */ ! 64: char ligatures[50]; /* ligatures strings stored here */ ! 65: char comment[100]; /* comments for each font */ ! 66: int internalname = 1; /* for troff's ASCII font files */ ! 67: int isspecial = FALSE; /* is this a special font */ ! 68: char ascender[10]; /* used to get ascender data */ ! 69: char spacechar[10]; /* spacewidth = width of this character */ ! 70: int spacewidth = -1; /* it's index in charinfo[] */ ! 71: ! 72: int above; /* has an ascender if yref > above */ ! 73: int below; /* used to set descender value */ ! 74: ! 75: int charcount = 0; /* number of chars in charset[] */ ! 76: int fontcount = 0; /* number of entries in fonts[] */ ! 77: int sizecount = 0; /* same but for sizelist[] */ ! 78: ! 79: int first = 1; /* glyph number endpoints */ ! 80: int last = 0; ! 81: ! 82: int fontoutput; /* process current font if ON */ ! 83: ! 84: char glyphdir[GLYDIR_SIZE]; /* new raster file glyph directory */ ! 85: Charinfo charinfo[MAX_INDEX+1]; /* data about characters in new font */ ! 86: ! 87: ! 88: /*****************************************************************************/ ! 89: ! 90: ! 91: main(agc, agv) ! 92: ! 93: ! 94: int agc; ! 95: char *agv[]; ! 96: ! 97: ! 98: { ! 99: ! 100: ! 101: /* ! 102: * ! 103: * Builds raster tables and troff's ASCII files from Imagen supplied raster ! 104: * files in directory *rastdir. All this stuff is done under the control of ! 105: * specially formatted ASCII files which are named as command line arguments. ! 106: * The source raster files are found in *rastdir, which can be changed using ! 107: * the -S option. ! 108: * ! 109: */ ! 110: ! 111: ! 112: argc = agc; /* other routines may want them */ ! 113: argv = agv; ! 114: ! 115: prog_name = argv[0]; /* really just for error messages */ ! 116: ! 117: rastdir = "."; /* source raster file directory */ ! 118: nrastdir = "."; /* new raster file directory */ ! 119: fontdir = "."; /* font directory for new files */ ! 120: ! 121: options(); /* first get command line options */ ! 122: arguments(); /* then process non-option arguments */ ! 123: ! 124: exit(x_stat); /* everything probably went OK */ ! 125: ! 126: } /* End of main */ ! 127: ! 128: ! 129: /*****************************************************************************/ ! 130: ! 131: ! 132: options() ! 133: ! 134: ! 135: { ! 136: ! 137: ! 138: int ch; /* return value from getopt() */ ! 139: char *names = "DIF:R:S:s:r:u:f:d"; ! 140: ! 141: extern char *optarg; /* used by getopt() */ ! 142: extern int optind; ! 143: ! 144: ! 145: /* ! 146: * ! 147: * Reads and processes the command line options. Right now the recognized ! 148: * options are, ! 149: * ! 150: */ ! 151: ! 152: ! 153: while ( (ch = getopt(argc, argv, names)) != EOF ) { ! 154: ! 155: switch ( ch ) { ! 156: ! 157: case 'r': /* set device resolution */ ! 158: res = atoi(optarg); ! 159: break; ! 160: ! 161: case 'u': /* font table unitwidth */ ! 162: unitwidth = atoi(optarg); ! 163: break; ! 164: ! 165: case 's': /* do stuff for these sizes only */ ! 166: get_sizes(optarg); ! 167: break; ! 168: ! 169: case 'f': /* and these fonts */ ! 170: get_fonts(optarg); ! 171: break; ! 172: ! 173: case 'd': /* don't build troff's DESC file */ ! 174: dodesc = OFF; ! 175: break; ! 176: ! 177: case 'F': /* new troff font directory */ ! 178: fontdir = optarg; ! 179: break; ! 180: ! 181: case 'R': /* directory for new raster files */ ! 182: nrastdir = optarg; ! 183: break; ! 184: ! 185: case 'S': /* source raster files found here */ ! 186: rastdir = optarg; ! 187: break; ! 188: ! 189: case 'D': /* debug flag */ ! 190: debug = ON; ! 191: break; ! 192: ! 193: case 'I': /* ignore FATAL errors */ ! 194: ignore = ON; ! 195: break; ! 196: ! 197: case '?': /* don't understand the option */ ! 198: error(FATAL, ""); ! 199: break; ! 200: ! 201: default: /* don't know what to do for ch */ ! 202: error(FATAL, "missing case for option %c\n", ch); ! 203: break; ! 204: ! 205: } /* End switch */ ! 206: ! 207: } /* End while */ ! 208: ! 209: argc -= optind; /* get ready for non-option args */ ! 210: argv += optind; ! 211: ! 212: } /* End of options */ ! 213: ! 214: ! 215: /*****************************************************************************/ ! 216: ! 217: ! 218: get_sizes(str) ! 219: ! 220: ! 221: char *str; /* comma or blank spearated size list */ ! 222: ! 223: ! 224: { ! 225: ! 226: ! 227: char *tok; /* next token in *str */ ! 228: ! 229: char *strtok(); ! 230: ! 231: ! 232: /* ! 233: * ! 234: * Converts a comma or blank separated list of point sizes to integers ! 235: * and stores the results in sizelist[]. Used to control how many of the ! 236: * raster files are built. If the -s options isn't used to select point ! 237: * sizes, raster files for all the sizes listed in the ASCII control files ! 238: * will be built. ! 239: * ! 240: */ ! 241: ! 242: ! 243: while ( (tok = strtok(str, " ,")) != NULL ) { ! 244: sizelist[sizecount++] = atoi(tok); ! 245: str = NULL; ! 246: } /* End while */ ! 247: ! 248: } /* End of get_sizes */ ! 249: ! 250: ! 251: /*****************************************************************************/ ! 252: ! 253: ! 254: get_fonts(str) ! 255: ! 256: ! 257: char *str; /* list of fonts to process */ ! 258: ! 259: ! 260: { ! 261: ! 262: ! 263: char *tok; /* next font name from *str */ ! 264: ! 265: ! 266: /* ! 267: * ! 268: * Called from options() to convert a comma or blank separated list of ! 269: * font names into pointers that can be stored in fontlist[]. Overrides ! 270: * the selection of fonts listed in the ASCII control files. ! 271: * ! 272: */ ! 273: ! 274: ! 275: while ( (tok = strtok(str, " ,")) != NULL ) { ! 276: fontlist[fontcount++] = tok; ! 277: str = NULL; ! 278: } /* End while */ ! 279: ! 280: } /* End of get_fonts */ ! 281: ! 282: ! 283: /*****************************************************************************/ ! 284: ! 285: ! 286: arguments() ! 287: ! 288: ! 289: { ! 290: ! 291: ! 292: /* ! 293: * ! 294: * All the rest of the comand line arguments are the names of ASCII control ! 295: * files. If there are no arguments left when we get here stdin will be ! 296: * read. ! 297: * ! 298: * Although the program accepts more than one control file name, I haven't ! 299: * really tested things using several control files. Probably needs more ! 300: * some more work. ! 301: * ! 302: */ ! 303: ! 304: ! 305: if ( argc < 1 ) { ! 306: fp_in = stdin; ! 307: readcontrol(); ! 308: } else { ! 309: while ( argc > 0 ) { ! 310: if ( (fp_in = fopen(*argv, "r")) == NULL ) ! 311: error(FATAL, "can't open %s", *argv); ! 312: readcontrol(); ! 313: fclose(fp_in); ! 314: argc--; ! 315: argv++; ! 316: } /* End while */ ! 317: } /* End else */ ! 318: ! 319: } /* End of arguments */ ! 320: ! 321: ! 322: /*****************************************************************************/ ! 323: ! 324: ! 325: readcontrol() ! 326: ! 327: ! 328: { ! 329: ! 330: ! 331: long pos; /* where build section starts in fp_in */ ! 332: int i; /* loop index for sizelist[] */ ! 333: ! 334: ! 335: /* ! 336: * ! 337: * Starts reading the ASCII description file fp_in. The stuff at the ! 338: * beginning is primarily for the DESC file and is just skipped, although ! 339: * the sizes, res, and unitwidth fields are used if the values haven't been ! 340: * set by options. Lines are read and processed by this routine until ! 341: * EOF is reached or the first build command is found. If we process the ! 342: * first part of the file and don't have res, unitwidth, and sizecount set ! 343: * an error message will be printed and we'll quit. ! 344: * ! 345: * After we break out of the first while loop, usually because a 'build' ! 346: * command was read, we record our position in file *fp_in and then enter ! 347: * a for loop that processes the rest of the file - once for each of the ! 348: * requested sizes. gotspecial controls whether we record special character ! 349: * names for the DESC file. We only need to do it on the first complete read ! 350: * of file *fp_in. ! 351: * ! 352: */ ! 353: ! 354: ! 355: while ( fscanf(fp_in, "%s", buff) != EOF ) ! 356: if ( sizecount <= 0 && strcmp(buff, "sizes") == 0 ) { ! 357: while ( fscanf(fp_in, "%d", &sizelist[sizecount]) == 1 && sizelist[sizecount] != 0 ) ! 358: sizecount++; ! 359: } else if ( unitwidth <= 0 && strcmp(buff, "unitwidth") == 0 ) ! 360: fscanf(fp_in, "%d", &unitwidth); ! 361: else if ( res <= 0 && strcmp(buff, "res") == 0 ) ! 362: fscanf(fp_in, "%d", &res); ! 363: else if ( strcmp(buff, "device") == 0 ) ! 364: fscanf(fp_in, "%s", device); ! 365: else if ( strcmp(buff, "build") == 0 ) ! 366: break; ! 367: else skipline(fp_in); ! 368: ! 369: if ( res <= 0 || unitwidth <= 0 || sizecount <= 0 ) ! 370: error(FATAL, "Missing res, unitwidth, or size specification"); ! 371: ! 372: if ( device[0] == '\0' ) ! 373: error(FATAL, "no device name given"); ! 374: ! 375: pos = (long) ftell(fp_in); /* probably want to get back here */ ! 376: ! 377: for ( i = 0; i < sizecount; i++ ) { ! 378: build(sizelist[i]); ! 379: fseek(fp_in, pos, 0); ! 380: gotspecial = TRUE; ! 381: } /* End for */ ! 382: ! 383: builddesc(); ! 384: rastdata(); ! 385: ! 386: } /* End of readcontrol */ ! 387: ! 388: ! 389: /*****************************************************************************/ ! 390: ! 391: ! 392: build(size) ! 393: ! 394: ! 395: int size; /* building files for this size */ ! 396: ! 397: ! 398: { ! 399: ! 400: ! 401: char name[40]; /* name of font we're building */ ! 402: char *ptr; /* used to pick up font comment field */ ! 403: int i, n; /* used for font size selection */ ! 404: int lsize; /* last valid size in font size list */ ! 405: int osize; /* original size - reset in the loop */ ! 406: ! 407: ! 408: /* ! 409: * ! 410: * Called from readcontrol() when we want to build font and raster files. At the ! 411: * top of the main loop we've read a 'build' command but haven't processed the ! 412: * name of the font yet. Once we get the name we initialize some variables, ! 413: * throw out all raster files we may already have read, skip the rest of the ! 414: * current line in *fp_in, and then enter a loop that processes all the ! 415: * allowed commands in a build section. The most important of these commands ! 416: * is 'using', which allows us to select particular characters from named ! 417: * raster files. It's assumed that we're finished with the current build ! 418: * section when we return from using() or when we read another 'build' ! 419: * command. When we exit the inner loop we're ready to build the new ! 420: * raster file. If size == unitwidth we'll also want to construct an ASCII ! 421: * font file for font *name. ! 422: * ! 423: * Actually that's not quite right. I've added code, that's really not very ! 424: * clear, that handles fonts with less than a complete set of raster files. ! 425: * Although much of the stuff can be done by hand, I think it's important ! 426: * to have buildrast handle everything. Logos will usually come in only ! 427: * one size and we may eventually want to add more logos to the raster file. ! 428: * That in itself would be difficult to do by hand, and adding more font ! 429: * font positions isn't all that clean either. There are a bunch of other ! 430: * ways it could have been handled, but I think adding the code to buildrast ! 431: * was the best choice. Fonts that don't come in all the sizes are described ! 432: * in the 'build' section by a command that looks like, ! 433: * ! 434: * sizes 12 18 36 0 ! 435: * ! 436: * This lists the point sizes that are available for building the font. ! 437: * All output will only be turned OFF unless the size that we're currently ! 438: * working on is in the list. The sizes can come in any order as long as ! 439: * the list is terminated by 0. The ASCII font files are built when the ! 440: * current size is equal to the first size in the list. Widths are properly ! 441: * scaled to the correct unitwidth. The ascender and descender stuff also ! 442: * had to be changed. ! 443: * ! 444: * Turning the output OFF when a given size wasn't available turned out ! 445: * to be tricky, and that's where lsize is used. If the size isn't available ! 446: * we'll still have work to do in addition to reading the file, especially ! 447: * the first time through. So all the stuff works properly I set size to ! 448: * lsize before going on to the 'using' section. It's a kludge but the ! 449: * raster files should be available in lsize even if we're not building ! 450: * any files. Anyway that's sort of what's happening in the new stuff. ! 451: * ! 452: */ ! 453: ! 454: ! 455: osize = size; /* in case we change size */ ! 456: ! 457: while ( fscanf(fp_in, "%s", name) != EOF ) { ! 458: fontoutput = wantfont(name); ! 459: size = osize; ! 460: first = 1; ! 461: last = 0; ! 462: comment[0] = '\0'; ! 463: ligatures[0] = '\0'; ! 464: ascender[0] = '\0'; ! 465: spacechar[0] = '\0'; ! 466: spacewidth = -1; ! 467: isspecial = FALSE; ! 468: dofont = (size == unitwidth) ? ON : OFF; ! 469: resetrast(); ! 470: skipline(fp_in); ! 471: while ( fscanf(fp_in, "%s", buff) != EOF ) ! 472: if ( strcmp(buff, "using") == 0 ) { ! 473: using(name, size); ! 474: break; ! 475: } else if ( strcmp(buff, "build") == 0 ) ! 476: break; ! 477: else if ( strcmp(buff, "special") == 0 ) ! 478: isspecial = TRUE; ! 479: else if ( strcmp(buff, "ascender") == 0 ) ! 480: fscanf(fp_in, "%s", ascender); ! 481: else if ( strcmp(buff, "spacewidth") == 0 ) ! 482: fscanf(fp_in, "%s", spacechar); ! 483: else if ( strcmp(buff, "start") == 0 ) { ! 484: fscanf(fp_in, "%d", &first); ! 485: last = first - 1; ! 486: } else if ( strcmp(buff, "sizes") == 0 ) { ! 487: for ( i = 0, lsize = 0; fscanf(fp_in, "%d", &n) == 1 && n != 0 && n != size; i++, lsize = n ) ; ! 488: lsize = (lsize == 0 ) ? n : lsize; ! 489: fontoutput = (fontoutput == ON && n == size) ? ON : OFF; ! 490: dofont = (fontoutput == ON && i == 0 ) ? ON : OFF; ! 491: size = (fontoutput == ON) ? size : lsize; ! 492: skipline(fp_in); ! 493: } else if ( strcmp(buff, "comment") == 0 ) { ! 494: for ( ptr = comment; (*ptr = getc(fp_in)) != '\n' && *ptr != EOF; ptr++ ) ; ! 495: *ptr = '\0'; ! 496: } else if ( buff[0] == '#' ) ! 497: skipline(fp_in); ! 498: else error(FATAL, "don't understand command %s", buff); ! 499: writerast(name, size); ! 500: buildfont(name, size); ! 501: } /* End while */ ! 502: ! 503: } /* End of build */ ! 504: ! 505: ! 506: /*****************************************************************************/ ! 507: ! 508: ! 509: using(name, size) ! 510: ! 511: ! 512: char name[]; /* building things for this font */ ! 513: int size; /* and in this size */ ! 514: ! 515: ! 516: { ! 517: ! 518: ! 519: char chname[10]; /* special character name */ ! 520: ! 521: ! 522: /* ! 523: * ! 524: * Called after we've read a 'using' command. The input file is read until ! 525: * we reach EOF of find another build command. The format of a 'using' command ! 526: * can be either, ! 527: * ! 528: * using name take ascii characters n to m ! 529: * ! 530: * or, ! 531: * ! 532: * using name take characters ! 533: * 12 fl ! 534: * 13 ff ! 535: * 103 *a ! 536: * ! 537: * ! 538: * where name refers to one of the raster files in *rastdir. It's assumed ! 539: * that the ascii characters n to m are in positions n to m in raster file ! 540: * name. If that's not the case the more general form given in the second ! 541: * example should be used. That's also the form that will be needed for troff's ! 542: * special characters. ! 543: * ! 544: * Synonyms are also allowed and can be specified by having the character ! 545: * '"' in the first index field as the following example illustrates. ! 546: * ! 547: * using name take characters ! 548: * 38 & ! 549: * 39 aa ! 550: * " ' ! 551: * 119 14 ! 552: * " 34 ! 553: * " 12 ! 554: * 91 [ ! 555: * ! 556: * The list of synonyms for a particular character is recorded in the ! 557: * Charinfo structure for that character and is only used when we build the ! 558: * ASCII font files. ! 559: * ! 560: * There can be as many 'using' commands for a particular font as you want ! 561: * and you can intermix the two formats. We'll continue building the current ! 562: * raster file up until we find another 'build' command or reach EOF. ! 563: * ! 564: */ ! 565: ! 566: ! 567: if ( fontoutput == ON ) ! 568: fprintf(stdout, "Building tables for %s size %d\n", name, size); ! 569: ! 570: while ( fscanf(fp_in, "%s", buff) != EOF ) { ! 571: getrastdata(buff, size); ! 572: ! 573: if ( fscanf(fp_in, " take %s", buff) != 1 ) ! 574: error(FATAL, "syntax error in using()"); ! 575: ! 576: if ( strcmp(buff, "ascii") == 0 ) ! 577: getascii(); ! 578: ! 579: skipline(fp_in); ! 580: while ( fscanf(fp_in, "%s", buff) != EOF ) { ! 581: if ( isdigit(buff[0]) ) { ! 582: fscanf(fp_in, "%s", chname); ! 583: recordchar(chname, atoi(buff)); ! 584: } else if ( buff[0] == '"' ) ! 585: getsynonym(); ! 586: else if ( strcmp(buff, "using") == 0 ) ! 587: break; ! 588: else if ( strcmp(buff, "build") == 0 ) ! 589: return; ! 590: else if ( strcmp(buff, "edit") == 0 ) { ! 591: skipline(fp_in); ! 592: edit(fp_in); ! 593: return; ! 594: } else if ( buff[0] == '#' ) ! 595: skipline(fp_in); ! 596: else error(FATAL, "don't understand command %s", buff); ! 597: } /* End while */ ! 598: } /* End while */ ! 599: ! 600: } /* End of using */ ! 601: ! 602: ! 603: /*****************************************************************************/ ! 604: ! 605: ! 606: getascii() ! 607: ! 608: ! 609: { ! 610: ! 611: ! 612: int start; /* first character's ASCII code */ ! 613: int stop; /* last character's code */ ! 614: char name[2]; /* name of the character - string */ ! 615: ! 616: ! 617: /* ! 618: * ! 619: * Called when we want to take a bunch of ASCII characters from the current ! 620: * raster file. As I mentioned before the expected format is, ! 621: * ! 622: * using name take ascii characters start to stop ! 623: * ! 624: * where name is the name of the raster file we want to use, while start ! 625: * and stop and the indices of the ASCII characters we want to steal from ! 626: * font name. Obviously start should be less than or equal to stop otherwise ! 627: * nothing will be done. ! 628: * ! 629: */ ! 630: ! 631: ! 632: if ( fscanf(fp_in, "%*s %d to %d", &start, &stop) != 2 ) ! 633: error(FATAL, "syntax error in getascii()"); ! 634: ! 635: name[1] = '\0'; /* terminate the string */ ! 636: ! 637: for ( ; start <= stop; start++ ) { ! 638: name[0] = start; ! 639: recordchar(name, start); ! 640: } /* End for */ ! 641: ! 642: } /* End of getascii */ ! 643: ! 644: ! 645: /*****************************************************************************/ ! 646: ! 647: ! 648: recordchar(name, index) ! 649: ! 650: ! 651: char *name; /* name of the character */ ! 652: int index; /* its glyph number in *fam */ ! 653: ! 654: ! 655: { ! 656: ! 657: ! 658: char *gptr1, *gptr2; /* glyph directory pointers */ ! 659: int height, width; /* of the bitmap */ ! 660: int i; /* used to copy directory entry */ ! 661: ! 662: ! 663: /* ! 664: * ! 665: * Called when we want to record information about character *name. Its ! 666: * number in the current raster file is index. Most of the information about ! 667: * the character is stored in charinfo[++last]. We'll need to remember its ! 668: * name, pointer to its bitmap, size of the bitmap, and pointer to the new ! 669: * glyph directory entry. Data about the bitmap comes directly from the glyph ! 670: * directory entry for character index. The pointer to the new glyph directory ! 671: * entry is figured out from the current values of first and last. Each entry ! 672: * in the directory is 15 bytes long, and all we do is copy index's entry ! 673: * over to the new character's entry. All that really has to be fixed up ! 674: * is the bitmap pointer, and this guy is figured out in writerast() when ! 675: * we're creating the new raster file. ! 676: * ! 677: */ ! 678: ! 679: ! 680: if ( ++last > MAX_INDEX ) ! 681: error(FATAL, "too many characters in current raster file"); ! 682: ! 683: height = getvalue(G_HEIGHT, index); ! 684: width = getvalue(G_WIDTH, index); ! 685: gptr1 = fam->rst + GLYPH_PTR(index); ! 686: gptr2 = glyphdir + (15 * (last - first)); ! 687: ! 688: strcpy(charinfo[last].name, name); ! 689: strcpy(charinfo[last].rastname, fam->name); ! 690: charinfo[last].index = index; ! 691: charinfo[last].mapsize = ((width + BYTE - 1) / BYTE) * height; ! 692: charinfo[last].map = fam->rst + getvalue(G_BPTR, index); ! 693: charinfo[last].glydir = gptr2; ! 694: charinfo[last].synonyms[0] = '\0'; ! 695: charinfo[last].chwidth = -1; ! 696: ! 697: for ( i = 0; i < 15; i++, gptr1++, gptr2++ ) ! 698: *gptr2 = *gptr1; ! 699: ! 700: if ( gotspecial == FALSE && dodesc == ON && name[1] != '\0' ) ! 701: specialchar(name); ! 702: ! 703: if ( spacechar[0] != '\0' && strcmp(name, spacechar) == 0 ) ! 704: spacewidth = last; ! 705: ! 706: } /* End of recordchar */ ! 707: ! 708: ! 709: /*****************************************************************************/ ! 710: ! 711: ! 712: getsynonym() ! 713: ! 714: ! 715: { ! 716: ! 717: ! 718: char chname[10]; /* character's name built up here */ ! 719: ! 720: ! 721: /* ! 722: * ! 723: * Called from using() when we've found a '"' in the index field. The ! 724: * character named next in the input file is a synonym for the one we ! 725: * just defined (ie. charinfo[last]). We'll add the name to the list of ! 726: * synonyms for the character and use that list when we build the ASCII ! 727: * font file. ! 728: * ! 729: */ ! 730: ! 731: ! 732: if ( last < first ) /* haven't defined anything yet */ ! 733: error(FATAL, "bad synonym request - no characters defined"); ! 734: ! 735: fscanf(fp_in, "%s", chname); ! 736: ! 737: strcat(strcat(charinfo[last].synonyms, " "), chname); ! 738: ! 739: if ( gotspecial == FALSE && dodesc == ON && chname[1] != '\0' ) ! 740: specialchar(chname); ! 741: ! 742: } /* End of getsynonym */ ! 743: ! 744: ! 745: /*****************************************************************************/ ! 746: ! 747: ! 748: specialchar(name) ! 749: ! 750: ! 751: char *name; /* keep track of special characters */ ! 752: ! 753: ! 754: { ! 755: ! 756: ! 757: int i; /* loop index */ ! 758: ! 759: ! 760: /* ! 761: * ! 762: * Called to record the special characters we find in the charset[] array. ! 763: * It's used later on when we build the DESC file. We also keep track of ! 764: * the ligatures defined on this font (if any), and we'll use this info ! 765: * when we build the new ASCII font file. ! 766: * ! 767: */ ! 768: ! 769: ! 770: for ( i = 0; i < charcount; i++ ) ! 771: if ( strcmp(name, charset[i].name) == 0 ) ! 772: break; ! 773: ! 774: if ( i >= charcount ) { ! 775: strcpy(charset[charcount++].name, name); ! 776: if ( strcmp(name, "fi") == 0 ) ! 777: strcat(ligatures, " fi"); ! 778: else if ( strcmp(name, "ff") == 0 ) ! 779: strcat(ligatures, " ff"); ! 780: else if ( strcmp(name, "fl") == 0 ) ! 781: strcat(ligatures, " fl"); ! 782: else if ( strcmp(name, "Fi") == 0 ) ! 783: strcat(ligatures, " ffi"); ! 784: else if ( strcmp(name, "Fl") == 0 ) ! 785: strcat(ligatures, " ffl"); ! 786: } /* End if */ ! 787: ! 788: } /* End of specialchar */ ! 789: ! 790: ! 791: /*****************************************************************************/ ! 792: ! 793: ! 794: writerast(name, size) ! 795: ! 796: ! 797: char *name; /* name of the font */ ! 798: int size; /* in this point size */ ! 799: ! 800: ! 801: { ! 802: ! 803: ! 804: int fd; /* new raster file */ ! 805: int presize; /* really preamble + file mark */ ! 806: int dirsize; /* size of glyph directory */ ! 807: int totsize; /* total size of preamble and direc */ ! 808: char *ptr; /* used to change new directory */ ! 809: int offset; /* adjust bitmap pointers */ ! 810: int i; /* loop index */ ! 811: ! 812: ! 813: /* ! 814: * ! 815: * All the raster file data for *name.size has been collected. This routine ! 816: * puts it all together and writes everything out to the new raster file. ! 817: * ! 818: */ ! 819: ! 820: ! 821: if ( fontoutput == OFF ) return; /* not doing output for this font */ ! 822: ! 823: fam = &fam_data[0]; ! 824: cur_fam = 0; ! 825: ! 826: sprintf(buff, "%s/rast%s/%s.%d", nrastdir, device, name, size); ! 827: if ( (fd = creat(buff, 0644)) == -1) ! 828: error(FATAL, "can't open %s", buff); ! 829: ! 830: presize = 8 + rst[P_LENGTH].size + getvalue(P_LENGTH); ! 831: dirsize = (last - first + 1) * 15; ! 832: totsize = presize + dirsize; ! 833: ! 834: writevalue(first, P_FIRSTGLY, fam->rst + rst[P_FIRSTGLY].offset); ! 835: writevalue(last, P_LASTGLY, fam->rst + rst[P_LASTGLY].offset); ! 836: writevalue(presize, P_GLYDIR, fam->rst + rst[P_GLYDIR].offset); ! 837: ! 838: write(fd, fam->rst, presize); ! 839: ! 840: for ( ptr = glyphdir + rst[G_BPTR].offset, offset = 0, i = first; i <= last; i++, ptr += 15 ) { ! 841: writevalue(totsize + offset, G_BPTR, ptr); ! 842: offset += charinfo[i].mapsize; ! 843: } /* End for */ ! 844: ! 845: write(fd, glyphdir, (last - first + 1) * 15); ! 846: ! 847: for ( i = first; i <= last; i++ ) ! 848: write(fd, charinfo[i].map, charinfo[i].mapsize); ! 849: ! 850: close(fd); ! 851: ! 852: } /* End of writerast */ ! 853: ! 854: ! 855: /*****************************************************************************/ ! 856: ! 857: ! 858: buildfont(font, size) ! 859: ! 860: ! 861: char *font; /* name of troff's font file */ ! 862: int size; /* have data for this point size */ ! 863: ! 864: ! 865: { ! 866: ! 867: ! 868: FILE *fp; /* new font file */ ! 869: int i; /* loop index */ ! 870: int chwidth; /* next character's font table width */ ! 871: char *ptr; /* the whole synonym string */ ! 872: char *syn; /* next synonym for current character */ ! 873: ! 874: char *strtok(); ! 875: ! 876: ! 877: /* ! 878: * ! 879: * Called to build the ascii font file for the current font. Things are ! 880: * only done if if the current size is equal to unitwidth. ! 881: * ! 882: */ ! 883: ! 884: ! 885: if ( fontoutput == OFF || dofont == OFF ) ! 886: return; ! 887: ! 888: sprintf(buff, "%s/dev%s/%s", fontdir, device, font); ! 889: if ( (fp = fopen(buff, "w")) == NULL ) ! 890: error(FATAL, "can't open font file %s", buff); ! 891: ! 892: if ( comment[0] != '\0' ) ! 893: fprintf(fp, "#%s\n", comment); ! 894: ! 895: fprintf(fp, "name %s\n", font); ! 896: fprintf(fp, "internalname %d\n", internalname++); ! 897: ! 898: if ( isspecial == TRUE ) ! 899: fprintf(fp, "special\n"); ! 900: ! 901: if ( ligatures[0] != '\0' ) ! 902: fprintf(fp, "ligatures %s 0\n", ligatures); ! 903: ! 904: fprintf(fp, "charset\n"); ! 905: ! 906: if ( isspecial == FALSE ) { ! 907: fprintf(fp, "\\| %d 0 0\n", (res * unitwidth)/(72 * 6)); ! 908: fprintf(fp, "\\^ %d 0 0\n", (res * unitwidth)/(72 * 12)); ! 909: } /* End if */ ! 910: ! 911: setascender(size); ! 912: ! 913: for ( i = first; i <= last; i++ ) { ! 914: if ( (chwidth = charinfo[i].chwidth) < 0 ) { ! 915: chwidth = readvalue(charinfo[i].glydir + rst[G_CHWIDTH].offset, rst[G_CHWIDTH].size, UNSIGNED); ! 916: chwidth = (PIXEL_WIDTH(chwidth, res) * unitwidth) / size; ! 917: } /* End if */ ! 918: fprintf(fp, "%s %d %d %d\n", charinfo[i].name, chwidth, getascender(i), i); ! 919: ptr = charinfo[i].synonyms; ! 920: while ( (syn = strtok(ptr, " ")) != NULL ) { ! 921: fprintf(fp, "%s \"\n", syn); ! 922: ptr = NULL; ! 923: } /* End while */ ! 924: } /* End for */ ! 925: ! 926: fclose(fp); ! 927: ! 928: } /* End of buildfont */ ! 929: ! 930: ! 931: /*****************************************************************************/ ! 932: ! 933: ! 934: builddesc() ! 935: ! 936: ! 937: { ! 938: ! 939: ! 940: FILE *fp; /* new desc file */ ! 941: int ch; /* for copying first part of fp_in */ ! 942: int i; /* for loop index for copying charset */ ! 943: ! 944: ! 945: /* ! 946: * ! 947: * Builds the new DESC file from the data contained in the first part of ! 948: * the ASCII control file *fp_in and the special characters saved in the ! 949: * charset[] array. ! 950: * ! 951: */ ! 952: ! 953: ! 954: if ( dodesc == OFF ) /* don't build new DESC file */ ! 955: return; ! 956: ! 957: sprintf(buff, "%s/dev%s/DESC", fontdir, device); ! 958: if ( (fp = fopen(buff, "w")) == NULL ) ! 959: error(FATAL, "can't open file %s", buff); ! 960: ! 961: fseek(fp_in, 0L, 0); /* back to start of control file */ ! 962: ! 963: while ( fscanf(fp_in, "%s", buff) != EOF ) ! 964: if ( strcmp(buff, "build") == 0 ) ! 965: break; ! 966: else if ( buff[0] == '#' || strcmp(buff, "device") == 0 ) ! 967: skipline(fp_in); ! 968: else { ! 969: fprintf(fp, "%s", buff); ! 970: while ( (ch = putc(getc(fp_in), fp)) != '\n' && ch != EOF ) ; ! 971: } /* End else */ ! 972: ! 973: fprintf(fp, "charset\n"); ! 974: fprintf(fp, "\\| \\^"); ! 975: ! 976: for ( i = 0; i < charcount; i++ ) ! 977: fprintf(fp, "%c%s", (i % 15 == 13) ? '\n' : ' ', charset[i].name); ! 978: putc('\n', fp); ! 979: ! 980: fclose(fp); ! 981: ! 982: } /* End of builddesc */ ! 983: ! 984: ! 985: /*****************************************************************************/ ! 986: ! 987: ! 988: rastdata() ! 989: ! 990: ! 991: { ! 992: ! 993: ! 994: FILE *fp; /* "RASTDATA" file */ ! 995: ! 996: ! 997: /* ! 998: * ! 999: * The post-processor and possibly others will need to know the resolution ! 1000: * and format of the raster files. It's looked for in file "RASTDATA", which ! 1001: * is defined in file init.h. Anyway this routine makes sure a reasonable ! 1002: * data file goes along with all the raster files we just built. ! 1003: * ! 1004: */ ! 1005: ! 1006: ! 1007: sprintf(buff, "%s/rast%s/%s", nrastdir, device, RASTDATA); ! 1008: if ( (fp = fopen(buff, "w")) == NULL ) ! 1009: error(FATAL, "can't write file %s", buff); ! 1010: ! 1011: fprintf(fp, "#\n# Format and resolution data\n#\n"); ! 1012: fprintf(fp, "format new\nresolution %d\n", res); ! 1013: ! 1014: fclose(fp); ! 1015: ! 1016: } /* End of rastdata */ ! 1017: ! 1018: ! 1019: /*****************************************************************************/ ! 1020: ! 1021: ! 1022: setascender(size) ! 1023: ! 1024: ! 1025: int size; /* for this size - usually unitwidth */ ! 1026: ! 1027: ! 1028: { ! 1029: ! 1030: ! 1031: int i; /* just a loop index */ ! 1032: ! 1033: ! 1034: /* ! 1035: * ! 1036: * Called to set reasonable values for the ascender/descender values above ! 1037: * and below. If *ascender != '\0' we'll look the character up in charinfo[] ! 1038: * and use it's height and yref to set values for above and below. If we ! 1039: * don't find the character or it hasn't been set we'll use size and res ! 1040: * to pick reasonable values. ! 1041: * ! 1042: */ ! 1043: ! 1044: ! 1045: for ( i = first; i <= last; i++ ) ! 1046: if ( strcmp(ascender, charinfo[i].name) == 0 ) ! 1047: break; ! 1048: ! 1049: if ( i > last ) ! 1050: above = (size * res) / (72.27 * 2); ! 1051: else above = readvalue(charinfo[i].glydir + rst[G_YREF].offset, rst[G_YREF].size, INTEGER); ! 1052: ! 1053: above = above + .30 * above + .5; ! 1054: below = .20 * above + .5; ! 1055: ! 1056: } /* End of setascender */ ! 1057: ! 1058: ! 1059: /*****************************************************************************/ ! 1060: ! 1061: ! 1062: getascender(n) ! 1063: ! 1064: ! 1065: int n; /* character's index in charinfo[] */ ! 1066: ! 1067: ! 1068: { ! 1069: ! 1070: ! 1071: int height; /* raster height of n's bitmap */ ! 1072: int yref; /* y reference point */ ! 1073: int value; /* ascender value for character n */ ! 1074: ! 1075: ! 1076: /* ! 1077: * ! 1078: * Figures out an appropriate value for the ascender/descender field in ! 1079: * troff's ASCII font files for character n. ! 1080: * ! 1081: */ ! 1082: ! 1083: ! 1084: value = 0; ! 1085: ! 1086: yref = readvalue(charinfo[n].glydir + rst[G_YREF].offset, rst[G_YREF].size, INTEGER); ! 1087: height = readvalue(charinfo[n].glydir + rst[G_HEIGHT].offset, rst[G_HEIGHT].size, UNSIGNED); ! 1088: ! 1089: if ( yref >= above ) ! 1090: value |= 02; ! 1091: ! 1092: if ( height - yref > below ) ! 1093: value |= 01; ! 1094: ! 1095: return(value); ! 1096: ! 1097: } /* End of getascender */ ! 1098: ! 1099: ! 1100: /*****************************************************************************/ ! 1101: ! 1102: ! 1103: skipline(fp) ! 1104: ! 1105: ! 1106: FILE *fp; /* skip rest of line in this file */ ! 1107: ! 1108: ! 1109: { ! 1110: ! 1111: ! 1112: int ch; /* next character from *fp_in */ ! 1113: ! 1114: ! 1115: /* ! 1116: * ! 1117: * Skips the rest of the current line in file *fp. ! 1118: * ! 1119: */ ! 1120: ! 1121: ! 1122: while ( (ch = getc(fp)) != '\n' && ch != EOF ) ; ! 1123: ! 1124: } /* End of skipline */ ! 1125: ! 1126: ! 1127: /*****************************************************************************/ ! 1128: ! 1129: ! 1130: writevalue(val, field, p) ! 1131: ! 1132: ! 1133: unsigned val; /* write this value out */ ! 1134: int field; /* as next rst[field].size bytes */ ! 1135: char *p; /* starting right here */ ! 1136: ! 1137: ! 1138: { ! 1139: ! 1140: ! 1141: int n; /* size in bytes of field */ ! 1142: int i; /* just a loop index */ ! 1143: ! 1144: ! 1145: /* ! 1146: * ! 1147: * Writes val out as the nextrst[field].sizebytes starting at address *p. ! 1148: * It's used to build entries in the preamble and glyph directory for the ! 1149: * new raster file we're currently working on. ! 1150: * ! 1151: */ ! 1152: ! 1153: ! 1154: n = rst[field].size; /* number of bytes to write out */ ! 1155: ! 1156: for ( i = 1; i <= n; i++, p++ ) ! 1157: *p = (val >> (n - i) * BYTE) & BMASK; ! 1158: ! 1159: } /* End of writevalue */ ! 1160: ! 1161: ! 1162: /*****************************************************************************/ ! 1163: ! 1164: ! 1165: unsigned readvalue(p, n, kind) ! 1166: ! 1167: ! 1168: register char *p; /* start here */ ! 1169: register int n; /* and get this many bytes */ ! 1170: int kind; /* type of field - INTEGER or UNSIGNED */ ! 1171: ! 1172: ! 1173: { ! 1174: ! 1175: ! 1176: register unsigned value; /* result after decoding the field */ ! 1177: ! 1178: ! 1179: /* ! 1180: * ! 1181: * Does essentially the same thing as getvalue() in rast.c except that we ! 1182: * supply different information as parameters. ! 1183: * ! 1184: */ ! 1185: ! 1186: ! 1187: value = (kind == INTEGER && (*p & 0200)) ? ~0 : 0; ! 1188: ! 1189: for ( ; n > 0; n--, p++ ) ! 1190: value = (value << BYTE) | (*p & BMASK); ! 1191: ! 1192: return(value); ! 1193: ! 1194: } /* End of readvalue */ ! 1195: ! 1196: ! 1197: /*****************************************************************************/ ! 1198: ! 1199: ! 1200: wantfont(name) ! 1201: ! 1202: ! 1203: char *name; /* do work for this font? */ ! 1204: ! 1205: ! 1206: { ! 1207: ! 1208: ! 1209: int i; /* loop index */ ! 1210: ! 1211: ! 1212: /* ! 1213: * ! 1214: * If we've just asked to process a few fonts (using -f option) fontcount ! 1215: * will be non-zero and pointers to the requested font names will be stored ! 1216: * in array fontlist[]. This routine returns ON if *name is one of the ! 1217: * requested fonts or if fontcount is 0. Otherwise OFF will be returned to ! 1218: * the caller, which should stop all output for *name. ! 1219: * ! 1220: */ ! 1221: ! 1222: ! 1223: if ( fontcount == 0 ) /* didn't ask for any fonts */ ! 1224: return(ON); ! 1225: ! 1226: for ( i = 0; i < fontcount; i++ ) ! 1227: if ( strcmp(name, fontlist[i]) == 0 ) ! 1228: return(ON); ! 1229: ! 1230: return(OFF); ! 1231: ! 1232: } /* End of wantfont */ ! 1233: ! 1234: ! 1235: /*****************************************************************************/ ! 1236: ! 1237:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.