Annotation of researchv10no/cmd/dimpress/buildrast.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.