Annotation of coherent/d/bin/nroff/fwt_TFM.c, revision 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.