Annotation of coherent/d/bin/nroff/fwt_TFM.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * fwt_TFM.c
                      3:  * 3/30/93
                      4:  * Build troff font width table from HP TFM file.
                      5:  * Reference: Hewlett Packard, "Tagged Font Metric Specification".
                      6:  * However, as of 6/7/91, steve has not seen the official spec,
                      7:  * so this code is based on the braindamaged source code for HP TFM reader.
                      8:  * Prints useful debugging output to stderr if compiled with DEBUG true.
                      9:  * INCOMPLETE.
                     10:  */
                     11: 
                     12: #include <stdio.h>
                     13: #include "fwtable.h"
                     14: 
                     15: /* Manifest constants. */
                     16: #define        INTEL_ORDER     0x4949
                     17: #define        MOTOROLA_ORDER  0x4D4D
                     18: #define        N_SYMBOL_SET    14              /* bytes per symbol set entry */
                     19: 
                     20: /* Tag values; this list does not include unused tags. */
                     21: #define        T_SYMBOL_SET    404
                     22: #define        T_POINT         406
                     23: #define        T_NOMINAL_PT    407
                     24: #define        T_DESIGN_UNITS  408
                     25: #define        T_TYPE_STRUCT   410
                     26: #define        T_STROKE_WT     411
                     27: #define        T_SPACING       412
                     28: #define        T_SLANT         413
                     29: #define        T_APPEAR_WIDTH  414
                     30: #define        T_TYPEFACE      417
                     31: #define        T_HORIZ_ESC     433
                     32: #define        T_SELECT_STR    442
                     33: 
                     34: /* Type. */
                     35: typedef        struct  rational {
                     36:        long    r_mul;          /* multiplier */
                     37:        long    r_div;          /* divisor */
                     38: } RATIONAL;
                     39: 
                     40: /* Data type lengths. */
                     41: #define        MAXTYPE 18              /* Max data type */
                     42: int type_size[MAXTYPE+1] = {
                     43:        0,                      /* 0  == unused         */
                     44:        1,                      /* 1  == BYTE           */
                     45:        1,                      /* 2  == ASCII          */
                     46:        2,                      /* 3  == SHORT          */
                     47:        4,                      /* 4  == LONG           */
                     48:        8,                      /* 5  == RATIONAL       */
                     49:        0,0,0,0,0,0,0,0,0,0,    /* 6 to 15 == unused    */
                     50:        1,                      /* 16 == SIGNEDBYTE     */
                     51:        2,                      /* 17 == SIGNEDSHORT    */
                     52:        4                       /* 18 == SIGNEDLONG     */
                     53: };
                     54: 
                     55: /* Global. */
                     56: int    appear_width;           /* Width.                       */
                     57: RATIONAL design_units;         /* Design units.                */
                     58: int    Intel_order;            /* Use Intel i8086 byte order.  */
                     59: RATIONAL nominal_point;                /* Nominal pointsize.           */
                     60: RATIONAL point;                        /* Point size.                  */
                     61: int    selector;               /* Selector.                    */
                     62: int    slant;                  /* Slant.                       */
                     63: int    spacing;                /* Spacing.                     */
                     64: int    stroke_weight;          /* Stroke weight.               */
                     65: short  *symbol_horiz;          /* Symbol map horizontal esc.   */
                     66: short  *symbol_set;            /* Symbol set indices.          */
                     67: int    symbol_set_size;        /* Symbol set size.             */
                     68: int    symset_val;             /* Encoded symbol set value.    */
                     69: char   *typeface;              /* Typeface name.               */
                     70: int    type_structure;         /* Type structure.              */
                     71: 
                     72: /*
                     73:  * Return the GCD of two longs.
                     74:  * Euclid's algorithm.
                     75:  */
                     76: long
                     77: gcd(m, n) long m, n;
                     78: {
                     79:        long r;
                     80: 
                     81:        while ((r = m % n) != 0) {
                     82:                m = n;
                     83:                n = r;
                     84:        }
                     85:        return n;
                     86: }
                     87: 
                     88: /*
                     89:  * Read and return a long, observing specified byte order.
                     90:  */
                     91: long
                     92: getlong()
                     93: {
                     94:        register int c;
                     95: 
                     96:        c = getword();
                     97:        if (Intel_order)
                     98:                return (((long)getword()) << 16) | c;
                     99:        else
                    100:                return (((long)c) << 16) | getword();
                    101: }
                    102: 
                    103: /*
                    104:  * Read a rational and store it through the supplied pointer.
                    105:  */
                    106: void
                    107: getrational(rp) RATIONAL *rp;
                    108: {
                    109:        rp->r_mul = getlong();
                    110:        rp->r_div = getlong();
                    111: }
                    112: 
                    113: /*
                    114:  * Read a NUL-terminated string into buf[] and return a pointer to it.
                    115:  * No overflow check, for shame...
                    116:  */
                    117: char *
                    118: getstring()
                    119: {
                    120:        register char *cp;
                    121: 
                    122:        for (cp = buf; *cp++ = getuchar(); )
                    123:                ;
                    124:        return buf;
                    125: }
                    126: 
                    127: /*
                    128:  * Read and return a short (2 bytes), observing specified byte order.
                    129:  */
                    130: int
                    131: getword()
                    132: {
                    133:        register int c;
                    134: 
                    135:        c = getuchar();
                    136:        if (Intel_order)
                    137:                return (getuchar() << 8) | c;
                    138:        else
                    139:                return (c << 8) | getuchar();
                    140: }
                    141: 
                    142: /*
                    143:  * Read TFM file.
                    144:  */
                    145: void
                    146: inputTFM()
                    147: {
                    148:        register int i, ntags;
                    149:        int tag, type;
                    150:        long size, length, curpos, offset;
                    151: 
                    152:        /* Read byte order word. */
                    153:        if ((i = getword()) == INTEL_ORDER)
                    154:                ++Intel_order;
                    155:        else if (i != MOTOROLA_ORDER)
                    156:                fatal("unknown byte order 0x%x in TFM header", i);
                    157: 
                    158:        /* Skip TFM version number. */
                    159:        getword();
                    160: 
                    161:        /* Read typeface offset, warn if not equal to current position. */
                    162:        if ((offset = getlong()) != 8L) {
                    163:                nonfatal("warning: TFM file contains multiple typefaces; using first");
                    164:                xseek(offset);
                    165:        }
                    166: 
                    167:        /* Read tag count and process tags. */
                    168:        ntags = getword();
                    169:        dbprintf((stderr, "ntags=%d\n", ntags));
                    170:        for (i = 1; i <= ntags; i++) {
                    171: 
                    172:                /* Read tag, type, size; compute length. */
                    173:                tag = getword();
                    174:                type = getword();
                    175:                size = getlong();
                    176:                length = size * type_size[type];
                    177:                dbprintf((stderr, "tag=%d type=%d size=%ld length=%ld\n", tag, type, size, length));
                    178: 
                    179:                /* Save current position, seek to data position if required. */
                    180:                curpos = xtell();
                    181:                if (length > 4) {
                    182:                        offset = getlong();
                    183:                        dbprintf((stderr, "length=%ld, data at offset %ld\n", length, offset));
                    184:                        xseek(offset);
                    185:                }
                    186:                
                    187:                /* Process the tag. */
                    188:                switch(tag) {
                    189: 
                    190:                case T_SYMBOL_SET:      read_symbol_set((int)size / N_SYMBOL_SET);
                    191:                                        break;
                    192:                case T_POINT:           getrational(&point);            break;
                    193:                case T_NOMINAL_PT:      getrational(&nominal_point);    break;
                    194:                case T_DESIGN_UNITS:    getrational(&design_units);     break;
                    195:                case T_TYPE_STRUCT:     type_structure = getuchar();    break;
                    196:                case T_STROKE_WT:       stroke_weight = getuchar();     break;
                    197:                case T_SPACING:         spacing = getword();            break;
                    198:                case T_SLANT:           slant = getword();              break;
                    199:                case T_APPEAR_WIDTH:    appear_width = PCL_width(getuchar());
                    200:                                        break;
                    201:                case T_TYPEFACE:        typeface = newstring(getstring());
                    202:                                        break;
                    203:                case T_HORIZ_ESC:       symbol_horiz = read_array((int)size);
                    204:                                        break;
                    205:                case T_SELECT_STR:      selector = atoi(getstring());   break;
                    206:                default:
                    207:                        dbprintf((stderr, "tag %d IGNORED\n", tag));
                    208:                        break;                  /* Ignore other tags. */
                    209:                }
                    210: 
                    211:                /* Restore position for next tag. */
                    212:                xseek(curpos+4);
                    213:        }
                    214: }
                    215: 
                    216: /*
                    217:  * Write font width table output from TFM.
                    218:  */
                    219: void
                    220: outputTFM()
                    221: {
                    222:        register int i, j, width, max, mul;
                    223:        long g, lmul, ldiv;
                    224: 
                    225:        /* Calculate maximum width of characters in character set. */
                    226:        for (max = i = 0; i < NWIDTH && i < symbol_set_size; i++) {
                    227:                j = symbol_set[i];
                    228:                width = (j == -1) ? 0 : symbol_horiz[j];
                    229:                dbprintf((stderr, "i=%d j=%d width=%d\n", i, j, width));
                    230:                if (width > max)
                    231:                        max = width;            
                    232:        }
                    233:        mul = (max / 256) + 1;
                    234:        dbprintf((stderr, "max=%d\n", max));
                    235:        dbprintf((stderr, "mul=%d\n", mul));
                    236:        dbprintf((stderr, "design_unit: %ld/%ld\n", design_units.r_mul, design_units.r_div));
                    237:        dbprintf((stderr, "nominal pt:  %ld/%ld\n", nominal_point.r_mul, nominal_point.r_div));
                    238:        dbprintf((stderr, "point:       %ld/%ld\n", point.r_mul, point.r_div));
                    239: 
                    240:        /* A little fuss to convert tag values to PCL values; thanks, HP. */
                    241:        if (vflag)
                    242:                fprintf(stderr, "%s %s\n", typeface, symset);
                    243:        fprintf(ofp, "%s %s", typeface, symset);        /* descriptor string */
                    244:        fputc('\0', ofp);               /* NUL-terminated */
                    245:        fputc('\0', ofp);               /* PS name */
                    246:        putshort(FLAG_PCL);             /* flags */
                    247:        putshort(0);                    /* fonttype */
                    248:        putshort(0);                    /* orientation */
                    249:        putshort(spacing == 0);         /* spacing */
                    250:        putshort(symset_val);           /* symbol set */
                    251:        if (spacing == 0)
                    252:                putshort(0);            /* pitch, proportional */
                    253:        else {
                    254:                /* UNTESTED, is this right? */
                    255:                i = (point.r_div * nominal_point.r_div * design_units.r_mul) /
                    256:                    (point.r_mul * nominal_point.r_mul * design_units.r_div * spacing);
                    257:                putshort(i);            /* pitch, fixed spacing */
                    258:        }
                    259:        i = 10 * nominal_point.r_mul / nominal_point.r_div;
                    260:        putshort(i);                    /* 10 * pointsize */
                    261:        i = ((type_structure/8) << 5) | (appear_width << 2) | (slant != 0);
                    262:        putshort(i);                    /* style */
                    263:        i = (stroke_weight == 0) ? -7 : (stroke_weight-1)/17 - 7;
                    264:        putshort(i);                    /* weight */
                    265:        putshort(selector);             /* face */
                    266: 
                    267:        /* Compute multiplier and divisor. */
                    268: #if    0
                    269:        /*
                    270:         * I think this is philosophically right,
                    271:         * but the factors get too big when point==100/7231;
                    272:         * just assume a point is 1/72" instead.
                    273:         */
                    274:        if (point.r_mul == 1 && point.r_div == 72) {
                    275:                lmul = design_units.r_div * mul;
                    276:                ldiv = design_units.r_mul;
                    277:        } else {
                    278:                lmul = design_units.r_div * point.r_mul * 72 * mul;
                    279:                ldiv = design_units.r_mul * point.r_div;
                    280:        }
                    281: #else
                    282:        lmul = design_units.r_div * mul;
                    283:        ldiv = design_units.r_mul;
                    284: #endif
                    285:        dbprintf((stderr, "lmul=%ld ldiv=%ld\n", lmul, ldiv));
                    286:        if ((g = gcd(lmul, ldiv)) != 1) {
                    287:                lmul /= g;
                    288:                ldiv /= g;
                    289:        }
                    290:        dbprintf((stderr, "g=%ld lmul=%ld ldiv=%ld\n", g, lmul, ldiv));
                    291:        putshort((int)lmul);            /* mul */
                    292:        putshort((int)ldiv);            /* div */
                    293: 
                    294:        /* Write width table. */
                    295:        for (i = 0; i < 256; i++) {
                    296:                j = (i < symbol_set_size) ? symbol_set[i] : -1;
                    297:                width = (j == -1) ? 0 : symbol_horiz[j];
                    298:                fputc(width/mul, ofp);
                    299:                dbprintf((stderr, "i=%d width=%d\n", i, width/mul));
                    300:        }
                    301: }
                    302: 
                    303: /*
                    304:  * Convert appearance width tag value to PCL value.
                    305:  * Cf. "LJ III Printer Developer's Guide", p. 6-37.
                    306:  */
                    307: int
                    308: PCL_width(n) int n;
                    309: {
                    310:        if (n <= 20)       return 4;
                    311:        else if (n <= 47)  return 3;
                    312:        else if (n <= 74)  return 2;
                    313:        else if (n <= 101) return 1;
                    314:        else if (n <= 182) return 0;
                    315:        else if (n <= 209) return 6;
                    316:        else               return 7;
                    317: }
                    318: 
                    319: /*
                    320:  * Allocate space for n integer words.
                    321:  * Read the array of integers and return a pointer to the array.
                    322:  */
                    323: int *
                    324: read_array(n) int n;
                    325: {
                    326:        register int i;
                    327:        register short *ip, *p;
                    328: 
                    329:        p = ip = alloc(n * sizeof(short));
                    330:        for (i = 0; i < n; i++, ip++) {
                    331:                *ip = getword();
                    332: #if    0
                    333:                dbprintf((stderr, "index=%d val=%d\n", i, *ip));
                    334: #endif
                    335:        }
                    336:        return p;
                    337: }
                    338: 
                    339: /*
                    340:  * Read the symbol set directory.
                    341:  */
                    342: void
                    343: read_symbol_set(n) int n;
                    344: {
                    345:        register int i, found;
                    346:        long curpos, offset, symset_seek, symsel_seek;
                    347:        char *s;
                    348: 
                    349:        dbprintf((stderr, "n_symbol_sets=%d\n", n));
                    350:        for (found = i = 0; i < n && !found; i++) {
                    351:                dbprintf((stderr, "symbol set %d: ", i));
                    352:                symset_seek = getlong();
                    353:                symsel_seek = getlong();
                    354:                offset = getlong();
                    355:                symbol_set_size = getword();
                    356:                curpos = xtell();
                    357:                xseek(symset_seek);
                    358:                s = getstring();                /* symbol set */
                    359:                xseek(curpos);
                    360:                dbprintf((stderr, "symset=%s ", s));
                    361:                dbprintf((stderr, "index offset=%ld ", offset));
                    362:                dbprintf((stderr, "index length=%d\n", symbol_set_size));
                    363:                if (symset == NULL) {
                    364:                        symset = newstring(s);  /* no -s option, take first */
                    365:                        ++found;
                    366:                } else if (strcmp(symset, s) == 0)
                    367:                        ++found;
                    368:        }
                    369:        if (!found)
                    370:                fatal("symbol set %s not found", symset);
                    371:        dbprintf((stderr, "found symset %s\n", symset));
                    372:        xseek(symsel_seek);
                    373:        s = getstring();                /* read symbol set selector */
                    374:        dbprintf((stderr, "selector=%s ", s));
                    375:        symset_val = atoi(s) * 32 + s[strlen(s)-1] - 64;
                    376:        dbprintf((stderr, "symset_val=%d\n", i));
                    377:        xseek(offset);
                    378:        symbol_set = read_array(symbol_set_size);
                    379: }
                    380: 
                    381: /*
                    382:  * Seek to given offset, die on error.
                    383:  */
                    384: void
                    385: xseek(offset) long offset;
                    386: {
                    387:        if (fseek(ifp, offset, SEEK_SET) == -1L)
                    388:                fatal("fseek failed");
                    389: }
                    390: 
                    391: /*
                    392:  * Return current seek position, die on error.
                    393:  */
                    394: long
                    395: xtell()
                    396: {
                    397:        register long offset;
                    398: 
                    399:        if ((offset = ftell(ifp)) == -1L)
                    400:                fatal("ftell failed");
                    401:        return offset;
                    402: }
                    403: 
                    404: /* end of fwt_TFM.c */

unix.superglobalmegacorp.com

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