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

1.1       root        1: 
                      2: /*
                      3:  *
                      4:  * A few routines that read and process raster files supplied by Imagen.
                      5:  *
                      6:  * Impress, at least at the time these routines were written, only allowed
                      7:  * us to use families 0 to 95. That imposes a limit on the total number of
                      8:  * raster files that any one job can use, unless we do some kind of memory
                      9:  * management, and that in turn restricts the number of entries in array
                     10:  * fam_data[] to 96. Unless this limit is changed MAXFAMILY should never be
                     11:  * defined to be greater than 95.
                     12:  *
                     13:  */
                     14: 
                     15: 
                     16: #include <stdio.h>
                     17: #include <sys/types.h>
                     18: #include <sys/stat.h>
                     19: 
                     20: #include "ext.h"                       /* external variable definitions */
                     21: #include "gen.h"                       /* definitions used by everyone */
                     22: #include "rast.h"                      /* raster file definitions */
                     23: #include "impcodes.h"                  /* Impress 2.0 opcodes */
                     24: 
                     25: 
                     26: Rst            rst[] = RST_INIT;       /* describes raster file structure */
                     27: 
                     28: Rastdata       fam_data[MAXFAMILY+1];  /* data about raster files we've read */
                     29: 
                     30: int            fam_num = 0;            /* use this as next family number */
                     31: int            next_fam = 0;           /* next free spot in fam_data[] */
                     32: int            cur_fam = 0;            /* family number we're using right now */
                     33: int            last_fam = MAXFAMILY+1; /* last one we told printer about */
                     34: Rastdata       *fam = NULL;            /* &fam_data[cur_fam] */
                     35: 
                     36: int            rast_res = RAST_RES;    /* raster table resolution */
                     37: 
                     38: 
                     39: /*****************************************************************************/
                     40: 
                     41: 
                     42: getfamdata(f, s)
                     43: 
                     44: 
                     45:     char       *f;                     /* find data for this font */
                     46:     int                s;                      /* in this point size */
                     47: 
                     48: 
                     49: {
                     50: 
                     51: 
                     52:     int                i;                      /* check fam_data[i] next */
                     53: 
                     54: 
                     55: /*
                     56:  *
                     57:  * Looks for the family data for font *f and size s in the fam_data[]
                     58:  * data structure. Returns the index where it was found, or next_fam
                     59:  * if not found.
                     60:  *
                     61:  */
                     62: 
                     63: 
                     64:     for ( i = 0; i < next_fam; i++ )
                     65:        if ( fam_data[i].size == s  &&  strcmp(f, fam_data[i].name) == 0 )
                     66:            break;
                     67: 
                     68:     return(i);
                     69: 
                     70: }   /* End of getfamdata */
                     71: 
                     72: 
                     73: /*****************************************************************************/
                     74: 
                     75: 
                     76: getrastdata(f, s)
                     77: 
                     78: 
                     79:     char       *f;                     /* use this font's raster file */
                     80:     int                s;                      /* in this point size */
                     81: 
                     82: 
                     83: {
                     84: 
                     85: 
                     86:     int                i;                      /* loop index for setting families */
                     87: 
                     88: 
                     89: /*
                     90:  *
                     91:  * Called to find the raster file info for font f, size s in fam_data[].
                     92:  * If it's not there it will be read in from the appropriate file in
                     93:  * *rastdir and all the required info will be added to location
                     94:  * next_fam in fam_data[].
                     95:  *
                     96:  * I'm assuming that each raster file contains at most 128 glyphs. If
                     97:  * that's not the case we'll need to change the way things are done
                     98:  * because Impress only allows 128 members in each family. Brian took
                     99:  * account of of larger raster files in di10.c and it wouldn't be all
                    100:  * that difficult to do it here too, but I don't think it's necessary.
                    101:  *
                    102:  */
                    103: 
                    104: 
                    105:     cur_fam = getfamdata(f, s);                /* use this family next */
                    106:     fam = &fam_data[cur_fam];          /* its entry in fam_data[] */
                    107: 
                    108:     if ( cur_fam >= next_fam )  {      /* didn't find it */
                    109:        if ( next_fam > MAXFAMILY )     /* only use families 0 to 95 */
                    110:            error(FATAL, "job uses too many raster files");
                    111: 
                    112:        strncpy(fam->name, f, L_FNAME); /* initialze some of the fields */
                    113:        fam->name[L_FNAME-1] = '\0';
                    114:        fam->size = s;
                    115:        fam->rst = NULL;
                    116:        fam->advance = (int *) rastalloc((MAXMEMBER+1) * sizeof(int), FALSE);
                    117: 
                    118:        for ( i = 0; i < ROT_COUNT; i++ )  {
                    119:            fam->chused[i] = (unsigned char *) rastalloc((MAXMEMBER+BYTE)/BYTE, TRUE, 0);
                    120:            fam->fam[i] = -1;
                    121:        }   /* End for */
                    122: 
                    123:        next_fam++;                     /* can only use it once */
                    124:     }   /* End if */
                    125: 
                    126:     if ( fam->rst == NULL )            /* need to read the whole raster file */
                    127:        readrastfile(f, s);
                    128: 
                    129: }   /* End of getrastdata */
                    130: 
                    131: 
                    132: /*****************************************************************************/
                    133: 
                    134: 
                    135: readrastfile(f, s)
                    136: 
                    137: 
                    138:     char       *f;                     /* name of the raster file */
                    139:     int                s;                      /* in this point size */
                    140: 
                    141: 
                    142: {
                    143: 
                    144: 
                    145:     char       name[100];              /* raster file pathname built up here */
                    146:     int                fd;                     /* file descriptor for *name */
                    147:     struct stat buf;                   /* used to get raster file size */
                    148: 
                    149: 
                    150: /*
                    151:  *
                    152:  * Reads the raster file for font f in size s from directory *rastdir
                    153:  * and initializes some of the required fields in fam_data[cur_fam].
                    154:  *
                    155:  * First we try to open the appropriate raster file. Then we determine
                    156:  * its size in bytes and try to allocate enough memory for the whole file.
                    157:  * After we've successfully read it we close the file and then initialize
                    158:  * the rest of the fields in fam_data[cur_fam].
                    159:  *
                    160:  * I've made allowances for two types of raster file naming conventions.
                    161:  * The most common is the one that troff's post-processor will be using.
                    162:  * The raster file names all begin with the string "font." and end with
                    163:  * the suffix size. For example the raster table for the Roman font in size
                    164:  * 10 would be called R.10. The other convention is the one you'll find
                    165:  * in all the raster files supplied directly from Imagen (as of 9/15 anyway).
                    166:  * In this case the file names all begin with the prefix string "*font.r"
                    167:  * and again end with the size. For example the raster file for font cmti
                    168:  * in size 12 would be cmti.r12. Since this routine is used by programs that
                    169:  * expect both conventions I've written it to try the two different raster
                    170:  * file names before giving up.
                    171:  *
                    172:  */
                    173: 
                    174: 
                    175:     sprintf(name, "%s/%s.%d", rastdir, f, s);
                    176:     if ( (fd = open(name, 0)) == -1 )  {
                    177:        sprintf(name, "%s/%s.r%d", rastdir, f, s);
                    178:        if ( (fd = open(name, 0)) == -1 )
                    179:            error(FATAL, "can't open raster file for font %s, size %d", f, s);
                    180:     }  /* End if */
                    181: 
                    182:     if ( fstat(fd, &buf) == -1 )
                    183:        error(FATAL, "can't get file size for %s", name);
                    184: 
                    185:     fam->rst = rastalloc(buf.st_size, FALSE);
                    186: 
                    187:     if ( read(fd, fam->rst, buf.st_size) != buf.st_size )
                    188:        error(FATAL, "can't read raster file %s", name);
                    189: 
                    190:     close(fd);                         /* all done with it - for now anyway */
                    191: 
                    192:     fam->glyphdir = getvalue(P_GLYDIR);
                    193:     fam->first = getvalue(P_FIRSTGLY);
                    194:     fam->last = getvalue(P_LASTGLY);
                    195: 
                    196:     if ( (fam->mag = getvalue(P_MAG)) <= 0 )
                    197:        fam->mag = 1000;
                    198: 
                    199: }   /* End of readrastfile */
                    200: 
                    201: 
                    202: /*****************************************************************************/
                    203: 
                    204: 
                    205: freerast(count)
                    206: 
                    207: 
                    208:     int                count;                  /* max number of calls to free() */
                    209: 
                    210: 
                    211: {
                    212: 
                    213: 
                    214:     int                called;                 /* number of calls made so far */
                    215:     int                i;                      /* loop index */
                    216: 
                    217: 
                    218: /*
                    219:  *
                    220:  * Tries to free all the memory used to store raster file data for
                    221:  * at most count entires in array fam_data[]. The actual number of
                    222:  * calls to free() is returned to the caller. A return value of 0
                    223:  * obviously means there's no more memory to release. We don't want to
                    224:  * free the memory used to keep track of the characters we've downloaded
                    225:  * because we may want to use this raster file later on and we'll need to
                    226:  * know which glyphs have been downloaded.
                    227:  *
                    228:  * Although I don't expect to use this routine often, some of the
                    229:  * raster files are huge and there will undoubtedly be a few jobs
                    230:  * that won't be able to keep all the required raster data in memory
                    231:  * at the same time.
                    232:  *
                    233:  */
                    234: 
                    235: 
                    236:     for ( called = 0, i = 0; i < next_fam  &&  called < count; i++ )
                    237:        if ( fam_data[i].rst != NULL )  {
                    238:            free(fam_data[i].rst);
                    239:            fam_data[i].rst = NULL;
                    240:            called++;
                    241:        }   /* End if */
                    242: 
                    243:     return(called);
                    244: 
                    245: }   /* End of freerast */
                    246: 
                    247: 
                    248: /*****************************************************************************/
                    249: 
                    250: 
                    251: resetrast()
                    252: 
                    253: 
                    254: {
                    255: 
                    256: 
                    257:     int                i, j;                   /* loop indices - family and angle */
                    258: 
                    259: 
                    260: /*
                    261:  *
                    262:  * Called when we want to clear the fam_data[] array, free all the memory
                    263:  * associated with each raster file, and reset all the variables used to
                    264:  * access the raster file info. Not used when we're generating Impress
                    265:  * commands used to print files, but it may be useful when we build and
                    266:  * edit raster files and troff's ASCII font files - maybe it shouldn't
                    267:  * be in this file.
                    268:  *
                    269:  */
                    270: 
                    271: 
                    272:     for ( i = 0; i < next_fam; i++ )  {
                    273:        free(fam_data[i].rst);
                    274:        free(fam_data[i].advance);
                    275:        fam_data[i].name[0] = '\0';
                    276:        fam_data[i].size = 0;
                    277:        for ( j = 0; j < ROT_COUNT; j++ )
                    278:            free(fam_data[i].chused[j]);
                    279:     }  /* End for */
                    280: 
                    281:     next_fam = 0;
                    282:     cur_fam = 0;
                    283:     last_fam = -1;
                    284:     fam = NULL;
                    285: 
                    286: }   /* End of resetrast */
                    287: 
                    288: 
                    289: /*****************************************************************************/
                    290: 
                    291: 
                    292: char *rastalloc(size, init, val)
                    293: 
                    294: 
                    295:     unsigned   size;                   /* allocate this many bytes */
                    296:     int                init;                   /* if TRUE initialize bytes */
                    297:     int                val;                    /* to these values */
                    298: 
                    299: 
                    300: {
                    301: 
                    302: 
                    303:     char       *ptr;                   /* block of memory we just got */
                    304:     int                i;                      /* loop index for initialization */
                    305: 
                    306: 
                    307: /*
                    308:  *
                    309:  * Tries to allocate a block of memory that's large enough to be used for
                    310:  * storage of size bytes. If init is TRUE the memory will be initialized
                    311:  * to val. It's assumed that the memory is going to be used to store
                    312:  * a raster file or other related data. We'll keep trying to get enough
                    313:  * memory as long as some is being used for other raster files.
                    314:  *
                    315:  */
                    316: 
                    317: 
                    318:     while ( (ptr = (char *) malloc(size)) == NULL )
                    319:        if ( freerast(1) == 0 )
                    320:            error(FATAL, "can't allocate memory for raster file");
                    321: 
                    322:     if ( init == TRUE )                        /* set all bytes to val */
                    323:        for ( i = 0; i < size; i++ )
                    324:            *(ptr + i) = val;
                    325: 
                    326:     return(ptr);
                    327: 
                    328: }   /* End of rastalloc */
                    329: 
                    330: 
                    331: /*****************************************************************************/
                    332: 
                    333: 
                    334: download(c, advance, angle, fp)
                    335: 
                    336: 
                    337:     int                c;                      /* download this glyph? */
                    338:     int                advance;                /* using this as the advance width */
                    339:     int                angle;                  /* glyph rotation - just 2 bits */
                    340:     FILE       *fp;                    /* Impress commands written here */
                    341: 
                    342: 
                    343: {
                    344: 
                    345: 
                    346:     Glyph      glyph;                  /* all of c's important data */
                    347:     int                map_size;               /* bytes needed to store the bitmap */
                    348:     int                i;                      /* loop index for downloading glyph */
                    349: 
                    350: 
                    351: /*
                    352:  *
                    353:  * Downloads glyph number c, using the raster file fam->rst and advance
                    354:  * as the character advance. All the Impress commands are written to FILE
                    355:  * *fp. If advance is greater than or equal to zero we'll assume the caller
                    356:  * wants to use the value as the character advance for the glyph, otherwise
                    357:  * we'll get the value from the raster file. Returns the member number in
                    358:  * the current family that corresponds to glyph c.
                    359:  *
                    360:  * I've added glyph rotation capabilities to this routine. The parameter
                    361:  * angle selects the absolute orientation of the glyph. Each angle needs
                    362:  * to be handled as a separate family. That means we'll want separate
                    363:  * chused bitmaps and family numbers for each orientation. I've added
                    364:  * the necessary fields to Rastdata. The fam[] field is new and really
                    365:  * needed so we don't waste our limited family numbers on orientations
                    366:  * that will never be used in the document. The Impress family is no
                    367:  * longer the font's index in fam_data[].
                    368:  *
                    369:  * Does much of the stuff handled by xychar() in di10.c except for the
                    370:  * positioning of the reference point and printing the member. I've tried
                    371:  * to make things a little more general so I'm assuming that whoever calls
                    372:  * it has done the appropriate positioning and will take care of printing
                    373:  * the glyph.
                    374:  *
                    375:  */
                    376: 
                    377: 
                    378:     if ( c < fam->first  ||  c > fam->last )
                    379:        error(FATAL, "glyph %d out of range for font %s", c, fam->name);
                    380: 
                    381:     if ( fam->fam[angle] != last_fam )  {      /* using a new family now */
                    382:        if ( fam->fam[angle] == -1 )  {
                    383:            fam->fam[angle] = fam_num;
                    384:            if ( (fam_num += 1 + fam->last/128) > MAXFAMILY )
                    385:                error(FATAL, "job uses too many families");
                    386:        }   /* End if */
                    387:        putc(ASF, fp);
                    388:        putc(last_fam = fam->fam[angle] + c/128, fp);
                    389:     }  /* End if */
                    390: 
                    391:     if ( ! checkbit(fam->chused[angle], c) )  {        /* first use of this glyph */
                    392:        setbit(fam->chused[angle], c);          /* don't download it again */
                    393: 
                    394:        fam->advance[c] = (advance < 0 ) ? PIXEL_WIDTH(getvalue(G_CHWIDTH, c), rast_res) : advance;
                    395: 
                    396:        glyph.xref = getvalue(G_XREF, c);       /* we'll need these soon */
                    397:        glyph.yref = getvalue(G_YREF, c);
                    398:        glyph.width = getvalue(G_WIDTH, c);
                    399:        glyph.height = getvalue(G_HEIGHT, c);
                    400:        glyph.advance = fam->advance[c];
                    401:        glyph.bptr = fam->rst + getvalue(G_BPTR, c);
                    402: 
                    403:        if ( angle != ROT_0 )
                    404:            rotate(&glyph, angle);
                    405: 
                    406:        if ( (map_size = glyph.height * ((glyph.width + BYTE - 1) / BYTE)) > 0 )  {
                    407:            putc(ABGLY, fp);            /* define the glyph */
                    408:            putint((angle << 14) | (last_fam << 7) | c % 128, fp);
                    409:            putint(glyph.advance, fp);
                    410:            putint(glyph.width, fp);
                    411:            putint(glyph.xref, fp);
                    412:            putint(glyph.height, fp);
                    413:            putint(glyph.yref, fp);
                    414: 
                    415:            for ( i = map_size; i--; )  /* followed by its bitmap */
                    416:                putc(*glyph.bptr++, fp);
                    417:        } else error(NON_FATAL, "Bad glyph - font %s, glyph %d", fam->name, c);
                    418:     }  /* End if */
                    419: 
                    420:     return(c % 128);
                    421: 
                    422: }   /* End of download */
                    423: 
                    424: 
                    425: /*****************************************************************************/
                    426: 
                    427: 
                    428: unsigned getvalue(field, ch)
                    429: 
                    430: 
                    431:     int                        field;          /* position in rst[] */
                    432:     int                        ch;             /* character number - for glyphs */
                    433: 
                    434: 
                    435: {
                    436: 
                    437: 
                    438:     register int       n;              /* number of bytes in the field */
                    439:     register char      *p;             /* start of the field */
                    440:     register unsigned  value;          /* result after decoding field */
                    441: 
                    442: 
                    443: /*
                    444:  *
                    445:  * Called to figure out the value field in the current family's raster file.
                    446:  * Right now things don't work for strings, but they're not really important.
                    447:  *
                    448:  * You'll see quite a few calls to this routine without the parameter ch.
                    449:  * It's only used when we're accessing the glyph directory so I've omitted
                    450:  * passing a value when we're looking at the preamble.
                    451:  *
                    452:  */
                    453: 
                    454: 
                    455:     n = rst[field].size;               /* number of bytes we want to grab */
                    456: 
                    457:     p = fam->rst + rst[field].offset;  /* right except for glyph directory */
                    458: 
                    459:     if ( rst[field].glyphdir == TRUE ) /* it's really part of the directory */
                    460:        p += GLYPH_PTR(ch);
                    461: 
                    462:     value = (rst[field].type == INTEGER && (*p & 0200)) ? ~0 : 0;
                    463: 
                    464:     for ( ; n > 0; n--, p++ )
                    465:        value = (value << BYTE) | (*p & BMASK);
                    466: 
                    467:     return(value);
                    468: 
                    469: }   /* End of getvalue */
                    470: 
                    471: 
                    472: /*****************************************************************************/
                    473: 
                    474: 
                    475: checkbit(p, n)
                    476: 
                    477: 
                    478:     char       *p;                     /* start of the bitmap */
                    479:     int                n;                      /* see if this bit is set */
                    480: 
                    481: 
                    482: {
                    483: 
                    484: 
                    485: /*
                    486:  *
                    487:  * Returns the value (0 or 1) set in the n-th bit in the bitmap that
                    488:  * starts at address p. Primarily used to keep track of which glyphs
                    489:  * have already been downloaded, but it's also needed in the routine
                    490:  * that dumps bitmaps out to files. It probably should be defined as
                    491:  * a macro.
                    492:  *
                    493:  */
                    494: 
                    495: 
                    496:     return(((p[n / BYTE] >> ((BYTE - 1) - n % BYTE)) & 01));
                    497: 
                    498: }   /* End of checkbit */
                    499: 
                    500: 
                    501: /*****************************************************************************/
                    502: 
                    503: 
                    504: setbit(p, n)
                    505: 
                    506: 
                    507:     char       *p;                     /* start of the bitmap - again */
                    508:     int                n;                      /* bit that we want to set in p[] */
                    509: 
                    510: 
                    511: {
                    512: 
                    513: 
                    514: /*
                    515:  *
                    516:  * Turns on the n-th bit in the bitmap that starts at address p. This
                    517:  * routine is really only used to keep track of the glyphs that have
                    518:  * already been downloaded. Again it could easily be defined as a macro.
                    519:  *
                    520:  */
                    521: 
                    522: 
                    523:     p[n / BYTE] |= 01 << ((BYTE - 1) - n % BYTE);
                    524: 
                    525: }   /* End of setbit */
                    526: 
                    527: 
                    528: /*****************************************************************************/
                    529: 
                    530: 
                    531: dump_glyph(n, fp)
                    532: 
                    533: 
                    534:     int                n;                      /* glyph number we want to display */
                    535:     FILE       *fp;                    /* everything's written here */
                    536: 
                    537: 
                    538: {
                    539: 
                    540: 
                    541:     int                height;                 /* pixel height of the bitmap */
                    542:     int                width;                  /* width of the rows in pixels */
                    543:     int                xref;                   /* x coordinate of reference point */
                    544:     int                yref;                   /* same but for y coordinate */
                    545:     int                chwidth;                /* width of the character */
                    546:     int                rwid;                   /* number of bytes per bitmap row */
                    547:     int                i, j;                   /* loop indices for the bitmap */
                    548:     char       *bptr;                  /* start of the glyph's bitmap */
                    549: 
                    550: 
                    551: /*
                    552:  *
                    553:  * Really just a debugging routine that's used to dump the bitmap and
                    554:  * other glyph data for character n out to FILE *fp.
                    555:  *
                    556:  */
                    557: 
                    558: 
                    559:     height = getvalue(G_HEIGHT, n);
                    560:     width = getvalue(G_WIDTH, n);
                    561:     xref = getvalue(G_XREF, n);
                    562:     yref = getvalue(G_YREF, n);
                    563:     chwidth = getvalue(G_CHWIDTH, n);
                    564:     bptr = fam->rst + getvalue(G_BPTR, n);
                    565: 
                    566:     rwid = (width + BYTE - 1) / BYTE;
                    567: 
                    568:     fprintf(fp, "GLYPH NUMBER %d  Character Width = %d\n", n, PIXEL_WIDTH(chwidth, rast_res));
                    569:     fprintf(fp, " Raster Data: height = %d, width = %d, xref = %d, yref = %d, chwidth = %d\n",height, width, xref, yref, chwidth);
                    570: 
                    571:     for ( j = 0; j < height; j++ )  {
                    572:        for ( i = 0; i < width; i++ )
                    573:            if ( checkbit(bptr, j * rwid * BYTE + i) )
                    574:                putc('X', fp);
                    575:            else putc('.', fp);
                    576:        putc('\n', fp);
                    577:     }   /* End for */
                    578: 
                    579: }   /* End of dump_glyph */
                    580: 
                    581: 
                    582: /*****************************************************************************/
                    583: 
                    584: 

unix.superglobalmegacorp.com

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