home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume2 / ditdvi / tfm2desc.c < prev   
Encoding:
C/C++ Source or Header  |  1991-08-07  |  6.2 KB  |  281 lines

  1. #include    <stdio.h>
  2.  
  3. /*
  4. **    Get character widths out of tfm files. See man page.
  5. */
  6.  
  7. /* where the TeX tfm files live */
  8. #ifndef        TEXFONT
  9. #define        TEXFONT        "/usr/lib/tex/fonts/"
  10. #endif
  11.  
  12. #define        FIX        (1<<20)
  13. #define        UNKNOWN        (-1)
  14. #define        PPI        72
  15.  
  16. #ifndef        RESOLUTION
  17. #define        RESOLUTION    (PPI*8)
  18. #endif
  19.  
  20. #define        HEADERSIZE    24
  21.  
  22. int        designsize    = 0;
  23. int        spacewidth    = -1;
  24.  
  25. usage()
  26. {
  27.     (void)fprintf(stderr, "Usage: tfm2desc [-d<ds>] [-s<sw>] fontmap [m|s]\n");
  28.     exit(1);
  29. }
  30.  
  31. main(argc,argv)
  32.     int        argc;
  33.     char        *argv[];
  34. {
  35.     register int    c;
  36.     register char    type = ' ';
  37.     char        tfmname[256];
  38.     char        extname[10];
  39.     FILE        *tfmfile;
  40.     extern int    optind;
  41.     extern char    *optarg;
  42.     int        getopt(), atoi();
  43.  
  44.     while ((c = getopt(argc, argv, "d:s:")) != EOF)
  45.     {
  46.         switch (c)
  47.         {
  48.         case 'd':
  49.             designsize = atoi(optarg);
  50.             if (designsize <= 0)
  51.                 (void)fprintf(stderr, "Bad designsize: %d, will use designsize in tfm file\n", designsize);
  52.             break;
  53.         case 's':
  54.             spacewidth = atoi(optarg);
  55.             break;
  56.         default:
  57.             exit(1);
  58.             break;
  59.         }
  60.     }
  61.  
  62.     argc -= optind;
  63.     argv += optind;
  64.  
  65.     if (argc < 1)
  66.         usage();
  67.     if (freopen(argv[0], "r", stdin) == NULL)
  68.     {
  69.         perror(argv[0]);
  70.         exit(1);
  71.     }
  72.     (void)sprintf(tfmname, "%s%s.tfm", TEXFONT, argv[0]);
  73.     if ((tfmfile = fopen(tfmname, "r")) == NULL)
  74.     {
  75.         perror(argv[0]);
  76.         exit(1);
  77.     }
  78.     (void)fgets(extname, sizeof(extname), stdin);
  79.     if (extname[1] == '\n')
  80.         extname[1] = '\0';
  81.     if (extname[2] == '\n')
  82.         extname[2] = '\0';
  83.     if (argc >= 2)
  84.         type = argv[1][0];
  85.     convert(extname, argv[0], tfmfile, type);
  86.     exit(0);
  87. }
  88.  
  89. #define    get1(buffer, offset)    (buffer[offset])
  90.  
  91. int get2(buffer, offset)
  92.     unsigned char    *buffer;
  93.     int        offset;
  94. {
  95.     return ((buffer[offset] << 8) | buffer[offset + 1]);
  96. }
  97.  
  98. int get4(buffer, offset)
  99.     unsigned char    *buffer;
  100.     int    offset;
  101. {
  102.     register int    i, n;
  103.  
  104.     n = 0;
  105.     for (i = 0; i < 4; ++i)
  106.         n = (n << 8) | buffer[offset + i];
  107.     return (n);
  108. }
  109.  
  110. /*
  111. **    Convert from FIXES to pixels. The roundoff error of this
  112. **    routine is a max of (72*designsize)/2^20, which is negligible
  113. **    for ordinary pointsizes.
  114. */
  115. fixestopixels(fix, designsize)
  116.     int        fix;
  117.     int        designsize;
  118. {
  119.     register unsigned long    l;
  120.  
  121.     l = fix * RESOLUTION / PPI;
  122.     l = (l * designsize + FIX / 2) / FIX;
  123.     return (l);
  124. }
  125.  
  126. /*
  127. **    The main routine which converts a tfm file to a troff width table file
  128. */
  129. convert(extname, intname, tfmfile, type)
  130.     char        *extname, *intname;
  131.     FILE        *tfmfile;
  132.     char        type;
  133. {
  134.     register int    i, j, ch;
  135.     register unsigned char    *tfmbuf;
  136.     register int    aheight;
  137.     int        lh, bc, ec, nw, nh;
  138.     char        line[256];
  139.     char        name[3];
  140.     char        *malloc();
  141.  
  142. /*
  143. **    Read the whole tfm file in one gulp
  144. */
  145.     i = getc(tfmfile) & 0xff;
  146.     i = (i << 8) | (getc(tfmfile) & 0xff);
  147.     i *= 4;
  148.     if ((tfmbuf = (unsigned char *)malloc(i)) == NULL)
  149.     {
  150.         (void)fprintf(stderr, "Out of memory\n");
  151.         exit(1);
  152.     }
  153.     i -= 2;
  154.     if ((j = fread(tfmbuf + 2, sizeof(char), i, tfmfile)) != i)
  155.     {
  156.         (void)fprintf(stderr, "Short read on %s, want %d, got %d\n",
  157.             intname, i, j);
  158.         exit(1);
  159.     }
  160.  
  161.     (void)printf("name %s\ninternalname %s\n", extname, intname);
  162.     if (type == 's')
  163.         (void)printf("special\n");
  164.     else if (type != 's' && type != 'm')    /* not special or mono-spaced */
  165.         (void)printf("ligatures ff fi fl ffi ffl 0\n");
  166.     if (type != 's')
  167.     {
  168.         if ((aheight = getaheight(tfmbuf)) == UNKNOWN)
  169.         {
  170.             (void)fprintf(stderr, "No letter 'a' in %s.tfm\n", intname);
  171.             (void)fprintf(stderr, "\tSetting height to zero\n");
  172.             aheight = 0;
  173.         }
  174.     }
  175.  
  176.     if (spacewidth >= 0)
  177.         (void)printf("spacewidth %d\n", spacewidth);
  178.  
  179.     lh = get2(tfmbuf, 2) * 4;
  180.     bc = get2(tfmbuf, 4);
  181.     ec = get2(tfmbuf, 6);
  182.     nw = get2(tfmbuf, 8) * 4;
  183.     nh = get2(tfmbuf, 10) * 4;
  184.     if (designsize <= 0)
  185.         designsize = get4(tfmbuf, HEADERSIZE + 4) / FIX;
  186.  
  187.     (void)printf("charset\n");
  188.     ch = -1;
  189.     while (fgets(line, sizeof(line), stdin) != NULL)
  190.     {
  191.         register int    widthindex, heightanddepth, width;
  192.         int        height, depth, kerning;
  193.         int        temp;
  194.  
  195.         if (sscanf(line, "%o\t%2s\n", &temp, name) != 2)
  196.         {
  197.             (void)fprintf(stderr, "Bad spec file: %s", line);
  198.             exit(1);
  199.         }
  200.         /* space is a terminator */
  201.         if (name[0] == '\0')
  202.         {
  203.             name[0] = ' ';
  204.             name[1] = '\0';
  205.         }
  206.         if (temp >= 128)
  207.         {
  208.             specials(name, temp, spacewidth);
  209.             continue;
  210.         }
  211.         if (temp == ch)
  212.         {
  213.             (void)printf("%s\t\"\n", name);
  214.             continue;
  215.         }
  216.         ch = temp;
  217.         widthindex = get1(tfmbuf, HEADERSIZE + lh + (ch-bc)*4);
  218.         heightanddepth = get1(tfmbuf, HEADERSIZE + lh + (ch-bc)*4 + 1);
  219.         if (widthindex == 0)
  220.             continue;
  221.         width = get4(tfmbuf, HEADERSIZE + lh + (ec-bc+1)*4 + widthindex*4);
  222.         width = fixestopixels(width, designsize);
  223.         height = get4(tfmbuf, HEADERSIZE + lh + (ec-bc+1)*4 + nw +
  224.                 (heightanddepth>>4)*4);
  225.         height = fixestopixels(height, designsize);
  226.         depth = get4(tfmbuf, HEADERSIZE + lh + (ec-bc+1)*4 + nw + nh +
  227.             (heightanddepth & 0xf)*4);
  228.         depth = fixestopixels(depth, designsize);
  229.         kerning = 0;
  230.         if (height > aheight)
  231.             kerning |= 2;
  232.         if (depth > 0)
  233.             kerning |= 1;
  234.         if (width >= 256)
  235.             (void)fprintf(stderr, "Warning: width of %d for %s is too wide for ditroff to handle\n",
  236.                 width, name);
  237.         (void)printf("%s\t%d\t%d\t0%o\n", name, width, kerning, ch);
  238.     }
  239. }
  240.  
  241. /* Returns the height of the letter 'a' in the font passed as a parameter.
  242.  * The height is returned in pixels since troff likes to use pixels as its
  243.  * unit. If the letter 'a' is not found, UNKNOWN is returned.
  244.  */
  245. int getaheight(buffer)
  246.     unsigned char    *buffer;
  247. {
  248.     register int    lh, bc, ec, nw, designsize;
  249.     register int    widthindex, heightanddepth, height;
  250.  
  251.     lh = get2(buffer, 2) * 4;
  252.     bc = get2(buffer, 4);
  253.     ec = get2(buffer, 6);
  254.     nw = get2(buffer, 8) * 4;
  255.     if (bc > 'a' || ec < 'a')
  256.         return (UNKNOWN);
  257.     designsize = get4(buffer, HEADERSIZE + 4) / FIX;    /* Convert from FIXes */
  258.     widthindex = get1(buffer, HEADERSIZE + lh + ('a'-bc)*4);
  259.     heightanddepth = get1(buffer, HEADERSIZE + lh + ('a'-bc)*4 + 1);
  260.     if (widthindex == 0)
  261.         return (UNKNOWN);
  262.     height = get4(buffer, HEADERSIZE + lh + (ec-bc+1)*4 + nw +
  263.         (heightanddepth >> 4)*4);
  264.     return (fixestopixels(height, designsize));
  265. }
  266.  
  267. specials(name, ch, width)
  268.     char        *name;
  269.     int        ch, width;
  270. {
  271.     if (strcmp(name, "\\&") == 0)
  272.         width = 0;
  273.     /* assume em space is twice space width */
  274.     else if (strcmp(name, "\\^") == 0)
  275.         width = (width + 3) / 6;        /* 1/12 em space */
  276.     else if (strcmp(name, "\\|") == 0)
  277.         width = (width + 1) / 3;        /* 1/6 em space */
  278.     /* make ru same as spacewidth */
  279.     (void)printf("%s\t%d\t0\t0%o\n", name, width, ch);
  280. }
  281.