Annotation of researchv10no/cmd/dimpress/buildrast.c, revision 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.