home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Mftobdf / mftobdf.c < prev    next >
C/C++ Source or Header  |  1990-07-10  |  16KB  |  705 lines

  1. /*
  2.  * Copyright 1989 Dirk Grunwald
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without fee,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of Dirk Grunwald or M.I.T.
  9.  * not be used in advertising or publicity pertaining to distribution of
  10.  * the software without specific, written prior permission.  Dirk
  11.  * Grunwald and M.I.T. makes no representations about the suitability of
  12.  * this software for any purpose.  It is provided "as is" without express
  13.  * or implied warranty.
  14.  * 
  15.  * DIRK GRUNWALD AND M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  16.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17.  * FITNESS, IN NO EVENT SHALL M.I.T.  BE LIABLE FOR ANY SPECIAL, INDIRECT
  18.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  19.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  20.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  21.  * OR PERFORMANCE OF THIS SOFTWARE.
  22.  * 
  23.  * Author:
  24.  *     Dr. Dirk Grunwald
  25.  *     Dept. of Computer Science
  26.  *     Campus Box 430
  27.  *     Univ. of Colorado, Boulder
  28.  *     Boulder, CO 80309
  29.  * 
  30.  *     grunwald@colorado.edu
  31.  *     
  32.  */ 
  33.  
  34. #include <assert.h>
  35. #include <stdio.h>
  36. #include <ctype.h>
  37.  
  38. #include "libtex/types.h"
  39. #include "libtex/font.h"
  40.  
  41. #include "libtex/conv.h"
  42. #include "libtex/dvistate.h"
  43. #include "libtex/dviclass.h"
  44. #include "libtex/dvicodes.h"
  45. #include "libtex/postamble.h"
  46. #include "libtex/search.h"
  47. #include "libtex/fio.h"
  48.  
  49. /* X11 related files */
  50.  
  51. int    DviBlackness = -1;
  52. int    DviDpi = 300;
  53.  
  54. int    DviMag = 1000;
  55. int    DviDsz = 1000;
  56. char    *ProgName;
  57. int    ShowSnf = 0;
  58. int    UserMag = 1000;
  59.  
  60. long Numerator = 25400000;
  61. long Denomonator = 473628272;
  62.  
  63. int Debug = 0;
  64.  
  65. Conv Conversion;
  66. float DviFontTfmScale;
  67.  
  68. #define    GF_SHRUNK    GF_USR0
  69. #define    GLYPH_SHRUNK(g) ((g) -> g_flags & GF_SHRUNK)
  70. #define SHRUNK_GLYPH_BYTES_WIDE(g) ((((g) -> g_width + 15) >> 4) * 2)
  71. #define DEFAULT_BLACKNESS 3
  72.  
  73. #define TWOTO16    0x10000
  74. #define TWOTO24 16777216
  75. #define PTPI 72.27
  76.  
  77. main(argc, argv)
  78. int argc;
  79. char **argv;
  80. {
  81.   char *name = 0;
  82.   char *dev = "canon";
  83.   char *fname = 0;
  84.   int arg;
  85.   extern void processFont();
  86.   
  87.   struct font *theFont;
  88.   
  89.   ProgName = argv[0];
  90.   
  91.   for (arg = 1; arg < argc; arg++) {
  92.     char *str = argv[arg];
  93.     if ( strcmp(str, "-scaled") == 0 ) {
  94.       arg++;
  95.       DviMag = atoi( argv[arg] );
  96.     }
  97.     else  if ( strcmp(str, "-dpi") == 0 ) {
  98.       arg++;
  99.       DviDpi = atoi( argv[arg] );
  100.     }
  101.     else  if ( strcmp(str, "-D") == 0 ) {
  102.       Debug = 1;
  103.     }
  104.     else  if ( strcmp(str, "-Debug") == 0 ) {
  105.       Debug = 1;
  106.     }
  107.     else  if ( strcmp(str, "-size") == 0 ) {
  108.       arg++;
  109.       DviDsz = atoi( argv[arg] );
  110.     }
  111.     else  if ( strcmp(str, "-dev") == 0 ) {
  112.       arg++;
  113.       dev = argv[arg];
  114.     }
  115.     else  if ( strcmp(str, "-show") == 0 ) {
  116.       ShowSnf = !ShowSnf;
  117.     }
  118.     else  if ( strcmp(str, "-mag") == 0 ) {
  119.       arg++;
  120.       UserMag = atoi(argv[arg]);
  121.     }
  122.     else  if ( strcmp(str, "-b") == 0 ) {
  123.       arg++;
  124.       DviBlackness = atoi(argv[arg]);
  125.     }
  126.     else if ( str[0] != '-' ) {
  127.       name = argv[arg];
  128.       
  129.       if ( name == 0 ) {
  130.     fprintf(stderr,"%s: you must specify a font name\n", ProgName);
  131.     exit(1);
  132.       }
  133.       else {
  134.     int len;
  135.     int thisMag;
  136.     char *rindex();
  137.     char *nameWithOutPrefix;
  138.     
  139.     if ( nameWithOutPrefix = rindex(name, '/') ) {
  140.       name = nameWithOutPrefix+1;
  141.     }
  142.     
  143.     if ( Debug ) {
  144.       fprintf(stderr,"try to open %s with UserMag = %d\n",
  145.           name, UserMag);
  146.     }
  147.     
  148.     len = strlen(name);
  149.     
  150.     /* determine if they've specificd a font file or a font name */
  151.     
  152.     if (strcmp(name + len - 2,"pk") == 0
  153.         || strcmp(name + len - 2,"gf") == 0) {
  154.       
  155.       char *p = name + len;
  156.       
  157.       while (p > name && *p != '.') p--;
  158.       
  159.       if ( *p == '.' ) {
  160.         long value = atoi(p+1);
  161.         int sDpi;
  162.         
  163.         *p = 0;    /* end name*/
  164.         thisMag = ((value * DviMag * 1000) / DviDpi) / 1000;
  165.         sDpi = DviDpi * 1000;
  166.         sDpi /= 1000;
  167.         
  168.         if ( Debug || value < (sDpi * 0.25) ||  value > (sDpi * 5) ) {
  169.           fprintf(stderr, "%s: You have an odd sounding font number\n",
  170.               ProgName);
  171.           fprintf(stderr, "%s: I see a %d-dpi from mag %d file magnified %d\n",
  172.               ProgName, DviDpi, UserMag,thisMag);
  173.         }
  174.       }
  175.     }
  176.     else {
  177.       thisMag = DviMag;
  178.     }
  179.     
  180.     /* We read the font in at mag and then step it down to user mag, so
  181.        assume here that usermag is 1000 */
  182.     
  183.     SetConversion(DviDpi, 1000, Numerator, Denomonator, 1000);
  184.     
  185.     if ( Debug ) {
  186.       fprintf(stderr,"try to open %s at mag %d\n",
  187.           name, thisMag);
  188.     }
  189.     
  190.     theFont = GetFont(name, thisMag, DviDsz, dev, &fname);
  191.     if ( theFont == 0 ) {
  192.       fprintf(stderr,"Unable to locate ``%s''\n", name);
  193.       continue;
  194.     }
  195.     
  196.     if ( Debug && fname != 0 ) {
  197.       fprintf(stderr,"%s: returned name is %s\n", ProgName, fname);
  198.       fprintf(stderr,"%s: which lives in %s\n",
  199.           ProgName, theFont -> f_path);
  200.     }
  201.     
  202.     DviFontTfmScale = ((double)theFont -> f_design_size);
  203.     DviFontTfmScale *= 1000;
  204.     DviFontTfmScale /= (double) TWOTO24;
  205.     
  206.     processFont( theFont, name, thisMag );
  207.       }
  208.     }
  209.     else {
  210.       fprintf(stderr,"%s: don't grok ``%s''\n", ProgName, argv[arg]);
  211.       exit(1);
  212.     }
  213.   }
  214.   exit(0);
  215. }
  216.  
  217. /*
  218.  *    The following routine is used to shrink a glyph by some
  219.  *    shrink factor (in the width & height dimension).
  220.  *
  221.  *    These shrunken glyphs are more appropriate for previewers.
  222.  *
  223.  *    To do this, we simple scan the original raster, counting the
  224.  *    number of pixels within a given area. If the number of on pixels is
  225.  *    at least twice the total number of pixels, we turn the pixel in
  226.  *    the shrunken glyph ON, else OFF.
  227.  *
  228.  *    We use a lookup table to hasten the process of counting pixels.
  229.  *
  230.  *    The method used should be independent of byte-order (I think).
  231.  *
  232.  *    You need to define two types. One should be 32-bits long, and
  233.  *    the other 16 bits long.
  234.  */
  235.  
  236. typedef unsigned char BITS_8;
  237. typedef unsigned short BITS_16;
  238. typedef unsigned long BITS_32;
  239.  
  240. #define LOOKUP_BYTES    256
  241. #define    LOOKUP_BITS    8
  242. #define LOOKUP_MASK    0xff
  243.  
  244. static char dviLookUpTable[LOOKUP_BYTES];
  245. static char tableNotInitialized = 1;
  246.  
  247. struct glyph *
  248. dviShrinkGlyph(gly, font, rotation,shrinkH, shrinkW, blackness, killOld)
  249. struct glyph *gly;
  250. struct font *font;
  251. int rotation;
  252. int shrinkH;
  253. int shrinkW;
  254. int blackness;
  255. int killOld;
  256. {
  257.     int shrunkHeight;
  258.     int shrunkWidth;
  259.     int glyphWide;
  260.     int glyphHigh;
  261.     int glyphAdvance;
  262.     int shrunkAdvance;
  263.  
  264.     int bytesWide;
  265.     int shrunkBytesWide;
  266.  
  267.     struct glyph *ngly;
  268.  
  269.     BITS_16 *shrunkRaster;
  270.     int rasterSize;
  271.  
  272.     long width;
  273.     double ddvimag;
  274.     long dvimag;
  275.  
  276.     int x,y;
  277.     BITS_8 *cp;
  278.     BITS_8 *ptr;
  279.  
  280.     BITS_32 shrinkMask;
  281.  
  282.     int sampleSize;
  283.  
  284.     if (gly == 0 || !HASRASTER(gly) || (gly -> g_width < 0) ) {
  285.     return(0);
  286.     }
  287.  
  288.     if (gly -> g_raster == 0) {
  289.     gly-> g_raster = RASTER(gly, font, rotation);
  290.     }
  291.  
  292. /*
  293.  *    Initialize the lookup table of the number of bits in a given byte
  294.  */
  295.  
  296.     if (tableNotInitialized) {
  297.     register int i;
  298.     register int j;
  299.     register int k;
  300.     register int acc;
  301.     for (i = 0; i < LOOKUP_BYTES; i++) {
  302.         j = i;
  303.         acc = 0;
  304.         for (k = 0; j != 0 && k < LOOKUP_BITS ; k++) {
  305.         acc += (j & 1);
  306.         j >>= 1;
  307.         }
  308.         dviLookUpTable[i] = acc;
  309.     }
  310.     tableNotInitialized = 0;
  311.     }
  312.  
  313.     glyphHigh = gly -> g_height;
  314.     glyphWide = gly -> g_width;
  315.  
  316. /*
  317.  *    The following computes the ``escapement'' or the TFMwidth in
  318.  *    pixels. This converted to the DWIDTH in the bdf files.
  319.  *
  320.  *    This is a screwy point with Toreks library. He changes
  321.  *    the values of the design_size
  322.  *
  323.  */
  324.     ddvimag = font -> f_design_size / 16;
  325.     ddvimag *= font -> f_scaled;
  326.     ddvimag /= 1000;
  327.     dvimag = ROUND(ddvimag);
  328.     width = ScaleOneWidth( gly -> g_rawtfmwidth, dvimag);
  329.     gly -> g_pixwidth = fromSP( width );
  330.     glyphAdvance = (gly -> g_pixwidth);
  331.  
  332.     shrunkHeight = (glyphHigh + shrinkH - 1) / shrinkH;
  333.     shrunkWidth =  (glyphWide + shrinkW - 1) / shrinkW;
  334.     shrunkAdvance =  (glyphAdvance + shrinkW - 1) / shrinkW;
  335.  
  336.     bytesWide = (gly -> g_width + 7) >> 3;
  337.  
  338.     shrunkBytesWide = ((shrunkWidth + 7) >> 3);
  339.  
  340.     rasterSize = (shrunkHeight + 1) * shrunkBytesWide;
  341.     shrunkRaster = (BITS_16 *) malloc(rasterSize);
  342.     bzero(shrunkRaster, rasterSize);
  343.     ptr = (BITS_8 *) shrunkRaster;
  344.     
  345.     if (shrunkRaster == NULL) {
  346.     fprintf(stderr, "Out of memory!\n");
  347.     exit(1);
  348.     }
  349.  
  350.     if (Debug) {
  351.       fprintf(stderr, "%5d %10d %10d %10d %10d %10d %10d\n",
  352.           gly -> g_index,
  353.           gly -> g_width, gly -> g_height,
  354.           gly -> g_xorigin, gly -> g_yorigin,
  355.           shrunkWidth, shrunkHeight);
  356.     }
  357.  
  358.     for (y = 0; y < glyphHigh; y+= shrinkH) {
  359.     cp = (BITS_8 *) ptr;
  360.     shrinkMask = 0x80;
  361.     for (x = 0; x < glyphWide; x += shrinkW) {
  362.         int i;
  363.         int samples;
  364.         BITS_8 *baseP;
  365.         int upper;
  366.         register int thisShrinkW;
  367.  
  368.         baseP = (BITS_8 *) gly -> g_raster + (y * bytesWide);
  369.  
  370. /*
  371.  *    Set the upper limit on the height iteration so we dont count
  372.  *    off the end of the raster
  373.  */
  374.  
  375.         upper = y + shrinkH;
  376.         if (upper > glyphHigh) {
  377.         upper = glyphHigh;
  378.         }
  379.  
  380.         if (x + shrinkW > glyphWide) {
  381.         thisShrinkW = glyphWide - x;
  382.         } else {
  383.         thisShrinkW = shrinkW;
  384.         }
  385.  
  386.         samples = 0;
  387.         sampleSize = thisShrinkW * shrinkH;
  388.  
  389.         for (i = y; i < upper; i++) {
  390.         register int acc;
  391.         register BITS_8 *p;
  392.         register BITS_8 *ep;
  393. /*
  394.  *    Determine how many bytes our shrink window crosses (we might
  395.  *    overlap on byte-edges)
  396.  */
  397.  
  398.         p = baseP + (x >> 3);
  399.         ep = baseP + ( (x + thisShrinkW - 1) >> 3);
  400.         baseP += bytesWide;
  401.  
  402. /*
  403.  *    stuff everything in the accumulator
  404.  */
  405.  
  406.         acc = 0;
  407.         while (p <= ep) {
  408.             acc = ((acc << 8) & 0xff) | *p;
  409.             p++;
  410.         }
  411.  
  412. /*
  413.  *    clean off the right hand-side of extra bits, then clean off
  414.  *    the left hand side of extra bits, and then count them.
  415.  */
  416.  
  417.         acc = acc >> ( 7 - ((x + thisShrinkW - 1) & 0x7));
  418.         acc &= ~(-1 << thisShrinkW);
  419.         while (acc != 0) {
  420.             samples += dviLookUpTable[ acc & LOOKUP_MASK ];
  421.             acc >>= LOOKUP_BITS;
  422.         }
  423.         }
  424. /*
  425.  *    If at least 1/blackness of the bits are on, treat this entire sample as
  426.  *    being on.
  427.  */
  428.  
  429.         if ((samples * blackness) >= sampleSize) {
  430.         *ptr |= shrinkMask;
  431.         } else {
  432.         *ptr &= ~ shrinkMask;
  433.         }
  434.         shrinkMask >>= 1;
  435.         if (shrinkMask == 0) {
  436.         shrinkMask = 0x80;
  437.         ptr ++;
  438.         }
  439.     }
  440.     ptr = (BITS_8 *) (cp + shrunkBytesWide);
  441.     }
  442.  
  443. /*
  444.  *    Build a new glyph from the shrunken raster
  445.  */
  446.  
  447.     if (ShowSnf) {
  448.       printf("Old glyph:\n");
  449.       seeGlyph(gly -> g_raster, glyphHigh, bytesWide);
  450.       printf("New glyph:\n");
  451.       seeGlyph(shrunkRaster, shrunkHeight, shrunkBytesWide);
  452.     }
  453.  
  454.     ngly = (struct glyph *) malloc(sizeof(struct glyph));
  455.     bzero(ngly, sizeof(struct glyph));
  456.  
  457.     ngly -> g_raster = (char * ) shrunkRaster;
  458.     ngly -> g_un.g_integer = shrunkBytesWide;
  459.     ngly -> g_width = shrunkWidth;
  460.     ngly -> g_pixwidth = shrunkAdvance;
  461.     ngly -> g_height = shrunkHeight;
  462.  
  463.     ngly -> g_xorigin = gly -> g_xorigin / shrinkH;
  464.     ngly -> g_yorigin = gly -> g_yorigin / shrinkW;
  465.  
  466.     ngly -> g_flags |= GF_SHRUNK;    /* yes, its been shrunk */
  467.  
  468.     if ( killOld && gly -> g_raster ) {
  469.       free ( gly -> g_raster );
  470.       gly -> g_raster = 0;
  471.     }
  472.  
  473.     return(ngly);
  474. }
  475.  
  476. seeGlyph(c, h, w)
  477. char *c;
  478. int h;
  479. int w;
  480. {
  481.     int i,j;
  482.  
  483.     for (i = 0; i < h; i++ ) {
  484.     for (j = 0; j < w; j++) {
  485.         int k;
  486.         register int ch;
  487.         register int m;
  488.         char str[9];
  489.  
  490.         ch = *(c++);
  491.         m = 0x80;
  492.         for (k = 0; k < 8; k++) {
  493.         str[k] = ( (ch & m) ? '#' : '-' );
  494.         m >>= 1;
  495.         }
  496.         str[8] = 0;
  497.         printf("%s", str);
  498.     }
  499.     printf("\n");
  500.     }
  501. }
  502.  
  503. printhex(f,n)
  504. FILE *f;
  505. int n;
  506. {
  507.   fputc("0123456789abcdef"[(n >> 4) & 0xf], f);
  508.   fputc("0123456789abcdef"[n & 0xf], f);
  509. }
  510.  
  511. /*    SNF related junk */
  512.  
  513. void
  514. processFont(f, name, mag)
  515. struct font *f;
  516. char *name;
  517. int mag;
  518. {
  519.   struct glyph *g;
  520.   int c;
  521.   int blackness;
  522.  
  523.   int maxOverlap;
  524.   int nnonexistchars;
  525.  
  526. #define MAX_CHARACTER    127
  527.  
  528.   int glyphBytes[ MAX_CHARACTER + 1];
  529.   struct glyph *shrunkGlyphs[ MAX_CHARACTER + 1];
  530.  
  531.   int totalGlyphs;
  532.   int pointSize;
  533.   int shrink;
  534.  
  535.   int min_width = TWOTO16;
  536.   int max_width = -TWOTO16;
  537.  
  538.   int min_height = TWOTO16;
  539.   int max_height = -TWOTO16;
  540.  
  541.   int min_xorigin = TWOTO16;
  542.   int max_xorigin = -TWOTO16;
  543.  
  544.   int min_yorigin = TWOTO16;
  545.   int max_yorigin = -TWOTO16;
  546.  
  547. #define MIN(x,y) ((x < y) ? (x) : (y))
  548. #define MAX(x,y) ((x < y) ? (y) : (x))
  549.  
  550. #ifdef __STDC__
  551. #define MINMAX(x,y) { min_##x = MIN(min_##x,y); max_##x = MAX(max_##x,y); }
  552. #else
  553. #define MINMAX(x,y) { min_/**/x = MIN(min_/**/x,y); max_/**/x = MAX(max_/**/x,y); }
  554. #endif
  555.  
  556.   char newFileName[256];
  557.   char newName[256];
  558.   FILE *fontOut;
  559.   int i;
  560.  
  561.   double suffMag = (double) mag / (double) DviDsz;
  562.   int scaled = ROUND( (suffMag * 1000) );
  563.   double dsuff = ((double) DviDpi * UserMag * mag)
  564.     / ((double) 1000.0 * 1000.0) ;
  565.   int suff = ROUND(dsuff);
  566.  
  567.   if ( f -> f_design_size == 0 ) {
  568.     return;
  569.   }
  570.     
  571.   shrink = ROUND(1000.0 / UserMag);
  572.   if (shrink < 1 ) {
  573.     shrink = 1;
  574.   }
  575.   else if ( shrink > 10 ) {
  576.     shrink = 10;
  577.   }
  578.   
  579.   blackness = DviBlackness;
  580.   blackness = (blackness < 1) ? DEFAULT_BLACKNESS : blackness;
  581.  
  582.   sprintf(newName, "%s.%d", name, suff);
  583.   sprintf(newFileName, "%s.bdf", newName);
  584.  
  585.   fontOut = fopen(newFileName,"w");
  586.  
  587.   if (! fontOut  ) {
  588.     perror("fopen");
  589.     exit(1);
  590.   } else {
  591.     fprintf(stderr,"Write file %s\n", newFileName);
  592.   }
  593.  
  594.   totalGlyphs = 0;
  595.  
  596.   if ( Debug ) {
  597.     fprintf(stderr,"Font runs from %d to %d\n", f -> f_lowch, f -> f_highch);
  598.     fprintf(stderr, "%5s %10s %10s %10s %10s %10s %10s\n",
  599.         "Glyph", "Width", "Height", "Xorigin", "Yorigin",
  600.         "SWidth", "SHeight");
  601.   }
  602.  
  603.   for( c = f -> f_lowch; c < f -> f_highch; c++ ) {
  604.     g = GLYPH(f,c);
  605.     shrunkGlyphs[c] = 0;
  606.  
  607.     if (GVALID(g) && HASRASTER(g)) {
  608.     struct glyph *s;
  609.  
  610.     s = dviShrinkGlyph( g, f, ROT_NORM, shrink, shrink, blackness, 1);
  611.     shrunkGlyphs[c] = s;
  612.  
  613.     if (s == 0 )
  614.       continue;
  615.  
  616.     totalGlyphs++;
  617.  
  618.     MINMAX(width, s->g_width);
  619.     MINMAX(height, s->g_height);
  620.     MINMAX(xorigin, s->g_xorigin);
  621.     MINMAX(yorigin, s->g_yorigin);
  622.  
  623.     }
  624.   }
  625.  
  626.   fprintf(fontOut, "STARTFONT 2.1\n");
  627.   fprintf(fontOut,
  628.       "COMMENT This font image translated from Metafont\n");
  629.   fprintf(fontOut, "COMMENT Input file was ``%s''\n", name);
  630.   fprintf(fontOut, "COMMENT DPI was ``%d'', usermag ``%d'', blackness ``%d''\n",
  631.       DviDpi, UserMag, blackness);
  632.   fprintf(fontOut, "COMMENT shrink was %d\n", shrink);
  633.  
  634.   fprintf(fontOut, "FONT %s\n", newName);
  635.  
  636.   pointSize = (f -> f_design_size) / (TWOTO16 * 16);
  637.   fprintf(fontOut, "SIZE %d %d %d\n", pointSize, suff, suff);
  638.  
  639.   fprintf(fontOut, "FONTBOUNDINGBOX %d %d %d %d\n",
  640.       max_width + 1, max_height,
  641.       -max_xorigin, max_yorigin - max_height + 1);
  642.  
  643.   /* These follow the X conventions */
  644.  
  645.   fprintf(fontOut,"STARTPROPERTIES 3\n");
  646.   fprintf(fontOut,"FONT_ASCENT %d\n",
  647.       max_yorigin + 1);
  648.   fprintf(fontOut,"FONT_DESCENT %d\n",
  649.       max_height - max_yorigin + 1);
  650.   fprintf(fontOut,"COPYRIGHT \"Public Domain\"\n");
  651.   fprintf(fontOut,"ENDPROPERTIES\n");
  652.   fprintf(fontOut,"CHARS %d\n", totalGlyphs);
  653.  
  654.   for( c = f -> f_lowch; c < f -> f_highch; c++ ) {
  655.     if ( shrunkGlyphs[c] != 0 ) {
  656.       int column;
  657.       int width;
  658.       float swidth;
  659.       int bytes;
  660.       int byte;
  661.       char *p;
  662.       struct glyph *s = shrunkGlyphs[c];
  663.  
  664.       if ( s -> g_raster == 0 ) {
  665.     continue;    /* to next one */
  666.       }
  667.  
  668.       fprintf(fontOut, "STARTCHAR C%03d\n",c);
  669.       fprintf(fontOut, "ENCODING %d\n",c);
  670.  
  671.       width = s -> g_pixwidth;
  672.  
  673.       swidth = (double) ( width * 72000 ) / (double) ( pointSize * DviDpi );
  674.       fprintf(fontOut, "SWIDTH %d %d\n", (int) swidth, 0);
  675.       fprintf(fontOut, "DWIDTH %d %d\n", width, 0);
  676.  
  677.       fprintf(fontOut, "BBX %d %d %d %d\n",
  678.           s -> g_width,    /* width, height of bounding box */
  679.           s -> g_height,
  680.           -s -> g_xorigin,    /* offset of origin w.r.t. lower left corner*/
  681.           s -> g_yorigin - s -> g_height + 1);
  682.       fprintf(fontOut, "BITMAP\n");
  683.  
  684.       column = 0;
  685.       width = s -> g_un.g_integer;
  686.       bytes = width * s -> g_height;
  687.       for( p = s -> g_raster, byte = 0; byte < bytes; byte++, p++, column++ ) {
  688.     if (column >= width) {
  689.       fprintf(fontOut,"\n");
  690.       column = 0;
  691.     }
  692.     printhex(fontOut,*p);
  693.       }
  694.       if (column == width) {
  695.     fprintf(fontOut,"\n");
  696.       }
  697.       fprintf(fontOut, "ENDCHAR\n");
  698.  
  699.       free( s -> g_raster);
  700.     }
  701.   }
  702.   fprintf(fontOut, "ENDFONT\n");
  703.   fclose( fontOut );
  704. }
  705.