]> git.kernelconcepts.de Git - gbdfed.git/blob - bdfpkgf.c
Fixup several compile faults due to changes in recent distributions,
[gbdfed.git] / bdfpkgf.c
1 /*
2  * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 /*
24  * Routines to import GF and PK format bitmap font files.
25  *
26  * GF is the "generic font" file format for bitmap fonts; GF files are
27  * typically produced by Metafont.
28  *
29  * PK is the "packed file" font file format which is the de facto standard
30  * bitmap font format in the TeX world. It contains most of the information
31  * that's in a GF file, but much more compactly. PK fonts are typically
32  * generated from GF fonts by gftopk(1), or by a converter like gsftopk(1).
33  *
34  * Documentation for these file formats can be found in the literate programs
35  * GFtoPK, PKtoGF, GFtoDVI and GFtype which are included in a typical TeX
36  * distribution's source.
37  *
38  */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46
47 #ifndef BDF_NO_X11
48 #include <X11/Xlib.h>
49 #include <X11/Xutil.h>
50 #include <X11/Xatom.h>
51 #endif /* !BDF_NO_X11 */
52
53 #include "bdfP.h"
54
55 #undef MAX
56 #define MAX(h, i) ((h) > (i) ? (h) : (i))
57
58 #undef MIN
59 #define MIN(l, o) ((l) < (o) ? (l) : (o))
60
61 /*
62  * Symbolic names for the opcode bytes in GF files.
63  */
64 #define GF_paint1        64 /* 0x40 */
65 #define GF_paint2        65 /* 0x41 */
66 #define GF_paint3        66 /* 0x42 */
67 #define GF_boc           67 /* 0x43 */
68 #define GF_boc1          68 /* 0x44 */
69 #define GF_eoc           69 /* 0x45 */
70 #define GF_skip0         70 /* 0x46 */
71 #define GF_skip1         71 /* 0x47 */
72 #define GF_skip2         72 /* 0x48 */
73 #define GF_skip3         73 /* 0x49 */
74 #define GF_newrow_0      74 /* 0x4A */
75 #define GF_newrow_164   238 /* 0xEE */
76 #define GF_xxx1         239 /* 0xEF */
77 #define GF_xxx2         240 /* 0xF0 */
78 #define GF_xxx3         241 /* 0xF1 */
79 #define GF_xxx4         242 /* 0xF2 */
80 #define GF_yyy          243 /* 0xF3 */
81 #define GF_no_op        244 /* 0xF4 */
82 #define GF_char_loc     245 /* 0xF5 */
83 #define GF_char_loc0    246 /* 0xF6 */
84 #define GF_pre          247 /* 0xF7 */
85 #define GF_post         248 /* 0xF8 */
86 #define GF_post_post    249 /* 0xF9 */
87
88 /*
89  * Symbolic names for the opcode bytes in PK files.
90  */
91
92 #define PK_id            89 /* 0x59 */
93 #define PK_xxx1         240 /* 0xF0 */
94 #define PK_xxx4         243 /* 0xF3 */
95 #define PK_yyy          244 /* 0xF4 */
96 #define PK_post         245 /* 0xF5 */
97 #define PK_reserved1    248 /* 0xF8 */
98 #define PK_pre          247 /* 0xF7 */
99
100 /*
101  * Structure used to track the state for various things when reading a font.
102  */
103 typedef struct {
104     int top;
105     int mask;
106     int c;
107 } _bdf_mf_state_t;
108
109 /*
110  * Routine to compare two glyphs by encoding so they can be sorted.
111  */
112 static int
113 by_encoding(const void *a, const void *b)
114 {
115     bdf_glyph_t *c1, *c2;
116
117     c1 = (bdf_glyph_t *) a;
118     c2 = (bdf_glyph_t *) b;
119     if (c1->encoding < c2->encoding)
120       return -1;
121     else if (c1->encoding > c2->encoding)
122       return 1;
123     return 0;
124 }
125
126 /*
127  * Routines for scanning numbers from GF and PK files.
128  */
129 static int
130 _bdf_mf_get16(FILE *in)
131 {
132     return (getc(in) << 8) | (getc(in) & 0xff);
133 }
134
135 static int
136 _bdf_mf_get32(FILE *in)
137 {
138     int hi = _bdf_mf_get16(in);
139
140     if (hi > 32767)
141       hi -= 65536;
142     return (hi << 16) + _bdf_mf_get16(in);
143 }
144
145 static void
146 printscaled(int s, unsigned char *buf)
147 {
148     int delta;
149
150     *buf++ = ' ';
151     *buf++ = '(';
152     if (s < 0) {
153         *buf++ = '-';
154         s = -s;
155     }
156     sprintf((char *) buf, "%d", s >> 16);
157     buf += strlen((char *) buf);
158     s = 10 * ( s & 65535 ) + 5;
159     if (s != 5) {
160         delta = 10;
161         *buf++ = '.';
162         do {
163             if (delta > 65536)
164               s = s + 32768 - (delta >> 1);
165             *buf++ = 0x30 + (s >> 16);
166             s = 10 * (s & 65535);
167             delta *= 10;
168         } while (s > delta);
169     }
170     sprintf((char *) buf, " scaled)");
171
172
173 /*
174  * Routine to scan the PK specials and add them as comments if necessary.
175  */
176 static int
177 _bdf_pk_specials(FILE *in, bdf_font_t *font, bdf_options_t *opts,
178                  unsigned char *glyphname)
179 {
180     int c;
181     int i, n, num;
182     unsigned int comment_size;
183     unsigned char *comment, bytes[4];
184
185     /*
186      * Initialize the variable that keeps track of the storage allocated
187      * for the comments encountered.
188      */
189     comment = 0;
190     comment_size = 0;
191
192     while ((c = getc(in)) >= PK_xxx1 && c != GF_char_loc) {
193         /*
194          * Anything between PK_reserved1 and 0xff are bad values.  PK_pre is
195          * the font preamble which is not expected here.
196          */
197         if (c == PK_pre || (c >= PK_post && c <= 0xff))
198           return -2;
199
200         /*
201          * Anything between PK_xxx1 and PK_xxx4 are string specials which will
202          * be added with the comments if comments are being kept.
203          */
204         if (c >= PK_xxx1 && c <= PK_xxx4) {
205             /*
206              * Determine the number of bytes that need to be read to determine
207              * the length of the string special.
208              */
209             n = (c - PK_xxx1) + 1;
210             fread((char *) bytes, n, 1, in);
211             for (i = 0, num = 0; i < n; i++)
212               num = (num << 8) | bytes[i];
213
214             if (opts->keep_comments) {
215                 /*
216                  * Make sure there is enough space for the string.
217                  */
218                 if (comment_size < num + 1) {
219                     if (comment_size == 0)
220                       comment = (unsigned char *) malloc(num + 1);
221                     else
222                       comment = (unsigned char *)
223                           realloc((char *) comment, num + 1);
224                     comment_size = num + 1;
225                 }
226                 /*
227                  * Read the comment and add it to the font.
228                  */
229                 fread((char *) comment, num, 1, in);
230                 comment[num] = 0;
231                 if (!strncmp((char *) comment, "title ", 6))
232                   /*
233                    * The comment is the glyph's name/title; save it so it can
234                    * be associated with the forthcoming glyph, rather than
235                    * with the font as a whole.
236                    */
237                   strcpy((char *) glyphname, (char *) comment + 6);
238                 else
239                   /*
240                    * A regular comment.
241                    */
242                   _bdf_add_comment(font, (char *) comment, num);
243             } else
244               /*
245                * Skip the string special.
246                */
247               fseek(in, num, 1L);
248         }
249
250         /*
251          * PK_yyy is a numeric special.  Add the number as a comment if
252          * specified.
253          */
254         if (c == PK_yyy) {
255             num = _bdf_mf_get32(in);
256             if (opts->keep_comments) {
257                 if (comment_size < 64) {
258                     if (comment_size == 0)
259                       comment = (unsigned char *) malloc(64);
260                     else
261                       comment = (unsigned char *)
262                           realloc((char *) comment, 64);
263                     comment_size = 64;
264                 }
265                 sprintf((char *) comment, "%d", num);
266                 printscaled(num, comment + strlen((char *) comment));
267                 _bdf_add_comment(font, (char *) comment,
268                                  strlen((char *) comment));
269             }
270         }
271     }
272
273     /*
274      * Free up the comment buffer if it was allocated.
275      */
276     if (comment_size > 0)
277       free((char *) comment);
278
279     /*
280      * Return the byte that caused the loop to terminate.  This will be the
281      * postamble marker GF_post or the start of the glyphs.
282      */
283     return c;
284 }
285
286 /*
287  * Awkward little routine to collect packed bits from a PK file.
288  */
289 static int
290 _bdf_pk_getbit(FILE *in, _bdf_mf_state_t *state)
291 {
292     state->mask >>= 1;
293     if (state->mask == 0) {
294         state->c = getc(in);
295         state->mask = 0x80;
296     }
297     return (state->c & state->mask);
298 }
299
300 /*
301  * Another awkward little routine to get 4 bits at a time from a PK file.
302  */
303 static int
304 _bdf_pk_getnybble(FILE *in, _bdf_mf_state_t *state)
305 {
306     int r;
307
308     if (state->top == 0) {
309         state->c = getc(in);
310         state->top = 2;
311     }
312     r = (state->c >> ((state->top - 1) << 2)) & 0x0f;
313     state->top--;
314     return r;
315 }
316
317 /*
318  * Yet another awkward routine to read a packed number and a repeat count from
319  * a PK file.
320  */
321 static int
322 _bdf_pk_getpacked(FILE *in, int *rcount, int dyn, _bdf_mf_state_t *state)
323 {
324     int i, j;
325
326     if ((i = _bdf_pk_getnybble(in, state)) == 0) {
327         do {
328             j = _bdf_pk_getnybble(in, state);
329             i++;
330         } while (!j);
331         for (;i > 0; i--)
332           j = (j << 4) + _bdf_pk_getnybble(in, state);
333         return j - 15 + ((13 - dyn) << 4) + dyn;
334     }
335
336     if (i <= dyn)
337       return i;
338
339     if (i < 14)
340       return ((i - dyn - 1) << 4) + dyn + 1 + _bdf_pk_getnybble(in, state);
341
342     *rcount = (i == 14) ? _bdf_pk_getpacked(in, rcount, dyn, state) : 1;
343     return _bdf_pk_getpacked(in, rcount, dyn, state);
344 }
345
346 static int
347 _bdf_load_pk_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
348                   void *data, bdf_font_t **font)
349 {
350     int n, res, set, x, y, bpr, rcnt, ismono;
351     int num, plen, pend, row_size, awidth;
352     short rb, maxrb, minlb, maxlb;
353     double denom, dw;
354     bdf_font_t *f;
355     bdf_glyph_t *gp, g;
356     bdf_property_t prop;
357     bdf_callback_struct_t cb;
358     _bdf_mf_state_t state;
359     struct stat st;
360     unsigned char *row, bytes[256], glyphname[256];
361
362     row = 0;
363     glyphname[0] = 0;
364
365     /*
366      * Create a font to work with.
367      */
368     *font = f = (bdf_font_t *) malloc(sizeof(bdf_font_t));
369     (void) memset((char *) f, 0, sizeof(bdf_font_t));
370
371     /*
372      * Set some defaults and allocate an initial amount of space.  Make the
373      * initial assumption that the font is monowidth but determine if it
374      * should be proportional when the glyphs are loaded.  Allocate space for
375      * at least 128 glyphs before loading the font.
376      */
377     f->bpp = 1;
378     f->spacing = BDF_MONOWIDTH;
379     f->glyphs_size = 128;
380     f->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) << 7);
381     (void) memset((char *) f->glyphs, 0, sizeof(bdf_glyph_t) << 7);
382
383     /*
384      * Initialize the horizontal and vertical offsets of the font to some
385      * large number.
386      */
387     f->bbx.x_offset = f->bbx.y_offset = 32767;
388
389     /*
390      * Initialize things.
391      */
392     ismono = 1;
393     row_size = 0;
394     awidth = 0;
395     rb = maxrb = maxlb = 0;
396     minlb = 32767;
397     (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
398
399     /*
400      * Load the initial comment.
401      */
402     fread((char *) bytes, 1, 1, in);
403     n = bytes[0];
404     fread(bytes, n, 1, in);
405     bytes[n] = 0;
406
407     /*
408      * Add the comment to the font if indicated.
409      */
410     if (opts->keep_comments)
411       _bdf_add_comment(f, (char *) bytes, (unsigned int) n);
412
413     /*
414      * Get the point size and scale it down 
415      */
416     f->point_size = (int) (((float) _bdf_mf_get32(in)) /
417                             ((float) (1 << 20)));
418
419     /*
420      * Skip the checksum.
421      */
422     fread(bytes, 4, 1, in);
423
424     /*
425      * Get the horizontal resolution.
426      */
427     f->resolution_x = (int)
428         (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
429
430     /*
431      * Get the vertical resolution.
432      */
433     f->resolution_y = (int)
434         (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
435
436     /*
437      * Determine the denominator used for scalable width calculations.
438      */
439     denom = ((double) f->point_size) * ((double) f->resolution_x);
440
441     /*
442      * Get the font info so we can set up the callback.  The callback will
443      * update after every glyph is loaded and is based on file size instead of
444      * number of glyphs.  This allows the font to be read all at once instead
445      * of twice.
446      */
447     (void) fstat(fileno(in), &st);
448
449     /*
450      * Set the callback up.
451      */
452     if (callback != 0) {
453         cb.reason = BDF_LOAD_START;
454         cb.current = 0;
455         cb.total = st.st_size;
456         (*callback)(&cb, data);
457     }
458
459     /*
460      * Load the glyphs.
461      */
462     gp = f->glyphs;
463     while ((res = _bdf_pk_specials(in, f, opts, glyphname)) != PK_post &&
464            res > 0) {
465         /* Set the glyph's name, if we've seen it */
466         if (strlen((char *) glyphname)) {
467             g.name = malloc(strlen((char *) glyphname)+1);
468             strcpy((char *) g.name, (char *) glyphname);
469         }
470         if ((res & 7) == 7) {
471             /*
472              * Long glyph info.
473              */
474
475             /*
476              * Get the packet length and glyph encoding.
477              */
478             plen = _bdf_mf_get32(in);
479             g.encoding = _bdf_mf_get32(in);
480
481             pend = plen + ftell(in);
482
483             /*
484              * Get the glyph metrics.
485              */
486
487             /*
488              * Ignore the TFM width.
489              */
490             (void) _bdf_mf_get32(in);
491
492             /*
493              * Get the device width (DWIDTH) from the horizontal escapement of
494              * the glyph and calculate the scalable width (SWIDTH) from it.
495              */
496             num = _bdf_mf_get32(in);
497             g.dwidth = num >> 16;
498             dw = (double) g.dwidth;
499             g.swidth = (unsigned short) ((dw * 72000.0) / denom);
500
501             /*
502              * Ignore the vertical escapement.
503              */
504             (void) _bdf_mf_get32(in);
505
506             /*
507              * Collect the remaining glyph metrics info and calculate the
508              * glyph ascent and descent from the height and vertical offset.
509              */
510             g.bbx.width = (unsigned short) _bdf_mf_get32(in);
511             g.bbx.height = (unsigned short) _bdf_mf_get32(in);
512             g.bbx.x_offset = (short) _bdf_mf_get32(in);
513             g.bbx.y_offset = (short) _bdf_mf_get32(in);
514         } else if (res & 0x04) {
515             /*
516              * Extended glyph info.
517              */
518             if (res & 0x08)
519               plen = (((res & 0x07) - 4) << 16) + _bdf_mf_get16(in);
520             else
521               plen = (((res & 0x0f) - 4) << 16) + _bdf_mf_get16(in);
522
523             /*
524              * Load the encoding byte and the first byte of the TFM width.
525              */
526             fread(bytes, 2, 1, in);
527             g.encoding = (int) bytes[0];
528
529             pend = plen + ftell(in) - 1;
530
531             /*
532              * Get the glyph metrics.
533              */
534
535             /*
536              * Ignore the last two bytes of the TFM width.
537              */
538             (void) _bdf_mf_get16(in);
539
540             /*
541              * Get the device width (DWIDTH) from the horizontal escapement of
542              * the glyph and calculate the scalable width (SWIDTH) from it.
543              */
544             g.dwidth = (unsigned short) _bdf_mf_get16(in);
545             dw = (double) g.dwidth;
546             g.swidth = (unsigned short) ((dw * 72000.0) / denom);
547
548             /*
549              * Collect the remaining glyph metrics info and calculate the
550              * glyph ascent and descent from the height and vertical offset.
551              */
552             g.bbx.width = (unsigned short) _bdf_mf_get16(in);
553             g.bbx.height = (unsigned short) _bdf_mf_get16(in);
554             if ((num = _bdf_mf_get16(in)) > 32767)
555               g.bbx.x_offset = num - 65536;
556             else
557               g.bbx.x_offset = (short) num;
558             if ((num = _bdf_mf_get16(in)) > 32767)
559               g.bbx.y_offset = num - 65536;
560             else
561               g.bbx.y_offset = (short) num;
562         } else {
563             /*
564              * Short glyph info.  Read the next 10 bytes so they can be used
565              * as part of the glyph info calculations.
566              */
567             fread(bytes, 10, 1, in);
568
569             num = 0;
570             if (res & 0x08)
571               plen = ((res & 0x07) << 8) + bytes[num++];
572             else
573               plen = ((res & 0x0f) << 8) + bytes[num++];
574
575             g.encoding = (int) bytes[num++];
576
577             pend = plen + ftell(in) - 8;
578
579             /*
580              * Skip the TFM width.
581              */
582             num += 3;
583
584             /*
585              * Get the device width (DWIDTH) from the horizontal escapement of
586              * the glyph and calculate the scalable width (SWIDTH) from it.
587              */
588             g.dwidth = (unsigned short) bytes[num++];
589             dw = (double) g.dwidth;
590             g.swidth = (unsigned short) ((dw * 72000.0) / denom);
591
592             /*
593              * Collect the remaining glyph metrics info and calculate the
594              * glyph ascent and descent from the height and vertical offset.
595              */
596             g.bbx.width = (unsigned short) bytes[num++];
597             g.bbx.height = (unsigned short) bytes[num++];
598             /*
599              * The hoff value we're now to interpret gives the horizontal
600              * offset of the reference point compared to the character's
601              * pixels.  i.e. a value of -2 means the pixels start at +2; see
602              * the discussion of the example character raster in the pktogf
603              * web.
604              */
605             g.bbx.x_offset = (short) ((bytes[num] & 0x80) ?
606                                       256 - bytes[num] : bytes[num]);
607             num++;
608             g.bbx.y_offset = (short) ((bytes[num] & 0x80) ?
609                                       bytes[num] - 256 : bytes[num]);
610             num++;
611         }
612
613         /*
614          * Adjust the vertical metrics of the glyph.
615          */
616         g.bbx.y_offset = (g.bbx.y_offset + 1) - g.bbx.height;
617         g.bbx.ascent = g.bbx.height + g.bbx.y_offset;
618         g.bbx.descent = -g.bbx.y_offset;
619
620         /*
621          * Check to see if the font needs to be marked as proportional.
622          */
623         if (f->glyphs_used > 0 && ismono &&
624             (f->glyphs[0].bbx.width != g.bbx.width ||
625              f->glyphs[0].bbx.height != g.bbx.height ||
626              f->glyphs[0].bbx.x_offset != g.bbx.x_offset ||
627              f->glyphs[0].bbx.y_offset != g.bbx.y_offset ||
628              f->glyphs[0].bbx.ascent != g.bbx.ascent ||
629              f->glyphs[0].bbx.descent != g.bbx.descent)) {
630             ismono = 0;
631             f->spacing = BDF_PROPORTIONAL;
632         }
633
634         /*
635          * Now load the packed bits or the run length encoded image.
636          */
637         bpr = (g.bbx.width + 7) >> 3;
638         g.bytes = bpr * g.bbx.height;
639         g.bitmap = (unsigned char *) malloc(g.bytes);
640         (void) memset((char *) g.bitmap, 0, g.bytes);
641
642         /*
643          * Reset the state values.
644          */
645         state.top = state.mask = state.c = 0;
646         if ((res & 0xf0) == 0xe0) {
647             /*
648              * Packed bit format.
649              */
650             if ((g.bbx.width & 7) == 0)
651               /*
652                * The bits are on a boundary that is a multiple of 8, so the
653                * bitmap can be read all at once.
654                */
655               fread(g.bitmap, g.bbx.height * bpr, 1, in);
656             else {
657                 /*
658                  * The width is not a multiple of 8, so the bitmap should be
659                  * read one bit at a time.
660                  */
661                 for (y = 0; y < g.bbx.height; y++) {
662                     for (x = 0; x < g.bbx.width; x++) {
663                         if (_bdf_pk_getbit(in, &state))
664                           g.bitmap[(y * bpr) + (x >> 3)] |= (0x80 >> (x & 7));
665                     }
666                 }
667             }
668         } else {
669             /*
670              * Get the run length encoded image.
671              */
672
673             /*
674              * The glyph image is going to be run length encoded, so allocate
675              * a row to collect bits into.
676              */
677             if (row_size < bpr) {
678                 if (row_size == 0)
679                   row = (unsigned char *) malloc(bpr);
680                 else
681                   row = (unsigned char *) realloc((char *) row, bpr);
682                 row_size = bpr;
683             }
684             /*
685              * Initialize the row buffer so we don't get any extra bits in the
686              * image by accident.
687              */
688             (void) memset((char *) row, 0, row_size);
689
690             /*
691              * Determine if the run length encoding starts with bits that are
692              * to be set or cleared.
693              */
694             set = res & 0x08;
695             for (rcnt = x = y = 0; y < g.bbx.height;) {
696                 /*
697                  * Get the next number and a repeat count.
698                  */
699                 n = _bdf_pk_getpacked(in, &rcnt, (res >> 4) & 0x0f, &state);
700                 while (n > 0) {
701                     for (; n > 0 && x < g.bbx.width; x++, n--) {
702                         if (set)
703                           row[x >> 3] |= (0x80 >> (x & 7));
704                     }
705                     if (x == g.bbx.width) {
706                         /*
707                          * Copy the row into the actual glyph bitmap as many
708                          * times as called for by the repeat count, reset x to
709                          * 0 so a new row can be started, and initialize the
710                          * row buffer again.
711                          */
712                         for (x = 0; rcnt >= 0; rcnt--, y++)
713                           (void) memcpy((char *) (g.bitmap + (y * bpr)),
714                                         (char *) row, bpr);
715                         (void) memset((char *) row, 0, bpr);
716                         rcnt = 0;
717                     }
718                 }
719                 /*
720                  * Invert the flag that indicates whether bits need
721                  * to be set or not.
722                  */
723                 set = !set;
724             }
725         }
726
727         /*
728          * Adjust the font bounding box.
729          */
730         f->bbx.ascent = MAX(g.bbx.ascent, f->bbx.ascent);
731         f->bbx.descent = MAX(g.bbx.descent, f->bbx.descent);
732
733         rb = g.bbx.width + g.bbx.x_offset;
734         maxrb = MAX(rb, maxrb);
735         minlb = MIN(g.bbx.x_offset, minlb);
736         maxlb = MAX(g.bbx.x_offset, maxlb);
737
738         /*
739          * Increase the average width count to be used later.
740          */
741         awidth += g.bbx.width;
742
743         if ((g.encoding < 0 || g.encoding > 65535) && opts->keep_unencoded) {
744             /*
745              * If the glyph is unencoded (encoding field < 0 or > 65535) and
746              * the unencoded glyphs should be kept, then add the glyph to the
747              * unencoded list of the font.
748              */
749             if (f->unencoded_used == f->unencoded_size) {
750                 if (f->unencoded_size == 0)
751                   f->unencoded = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t));
752                 else
753                   f->unencoded = (bdf_glyph_t *)
754                       realloc((char *) f->unencoded,
755                               sizeof(bdf_glyph_t) * (f->unencoded_size + 1));
756                 f->unencoded_size++;
757             }
758             (void) memcpy((char *) (f->unencoded + f->unencoded_used),
759                           (char *) &g, sizeof(bdf_glyph_t));
760             f->unencoded_used++;
761         } else if (g.encoding >= 0 && g.encoding <= 65535) {
762             /*
763              * Add the glyph to the encoded list.
764              */
765             if (f->glyphs_used == f->glyphs_size) {
766                 /*
767                  * Expand by 128 glyphs at a time.
768                  */
769                 if (f->glyphs_used == 0)
770                   f->glyphs = (bdf_glyph_t *)
771                       malloc(sizeof(bdf_glyph_t) << 7);
772                 else
773                   f->glyphs = (bdf_glyph_t *)
774                       realloc((char *) f->glyphs,
775                               sizeof(bdf_glyph_t) * (f->glyphs_used + 128));
776                 gp = f->glyphs + f->glyphs_used;
777                 (void) memset((char *) gp, 0, sizeof(bdf_glyph_t) << 7);
778                 f->glyphs_size += 128;
779             }
780             gp = f->glyphs + f->glyphs_used++;
781             (void) memcpy((char *) gp, (char *) &g, sizeof(bdf_glyph_t));;
782         } else {
783             /*
784              * Free up the memory allocated for the temporary glyph so it
785              * doesn't leak.
786              */
787             if (g.bytes > 0)
788               free((char *) g.bitmap);
789         }
790
791         /*
792          * Make sure the temporary glyph is reinitialized.
793          */
794         (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
795
796         /*
797          * Call the callback if indicated.
798          */
799         if (callback != 0) {
800             cb.reason = BDF_LOADING;
801             cb.total = st.st_size;
802             cb.current = ftell(in);
803             (*callback)(&cb, data);
804         }
805     }
806
807     /*
808      * Sort all the glyphs by encoding.
809      */
810     qsort((char *) f->glyphs, f->glyphs_used, sizeof(bdf_glyph_t),
811           by_encoding);
812
813     /*
814      * Adjust the font bounding box from the values collected.
815      */
816     f->bbx.width = maxrb - minlb;
817     f->bbx.height = f->bbx.ascent + f->bbx.descent;
818     f->bbx.x_offset = minlb;
819     f->bbx.y_offset = -f->bbx.descent;
820
821     /*
822      * Set the default character as being undefined.
823      */
824     f->default_glyph = -1;
825
826     /*
827      * Set the font ascent and descent.
828      */
829     f->font_ascent = f->bbx.ascent;
830     f->font_descent = f->bbx.descent;
831
832     /*
833      * Now add the properties to the font.
834      */
835     prop.name = "POINT_SIZE";
836     prop.format = BDF_INTEGER;
837     prop.value.int32 = f->point_size * 10;
838     bdf_add_font_property(f, &prop);
839
840     /*
841      * Calculate and add the pixel size.
842      */
843     denom = (double) f->resolution_y;
844     dw = (double) (f->point_size * 10);
845     prop.name = "PIXEL_SIZE";
846     prop.format = BDF_INTEGER;
847     prop.value.int32 = (int) (((denom * dw) / 722.7) + 0.5);
848     bdf_add_font_property(f, &prop);
849
850     prop.name = "RESOLUTION_X";
851     prop.format = BDF_CARDINAL;
852     prop.value.card32 = (unsigned int) f->resolution_x;
853     bdf_add_font_property(f, &prop);
854
855     prop.name = "RESOLUTION_Y";
856     prop.format = BDF_CARDINAL;
857     prop.value.card32 = (unsigned int) f->resolution_y;
858     bdf_add_font_property(f, &prop);
859
860     prop.name = "FONT_ASCENT";
861     prop.format = BDF_INTEGER;
862     prop.value.int32 = f->font_ascent;
863     bdf_add_font_property(f, &prop);
864
865     prop.name = "FONT_DESCENT";
866     prop.format = BDF_INTEGER;
867     prop.value.int32 = f->font_descent;
868     bdf_add_font_property(f, &prop);
869
870     prop.name = "AVERAGE_WIDTH";
871     prop.format = BDF_INTEGER;
872     prop.value.int32 = (awidth / (f->unencoded_used + f->glyphs_used)) * 10;
873     bdf_add_font_property(f, &prop);
874
875     /*
876      * Default all PK fonts to proportional spacing.
877      */
878     prop.name = "SPACING";
879     prop.format = BDF_ATOM;
880     prop.value.atom = "P";
881     switch (f->spacing) {
882       case BDF_PROPORTIONAL: prop.value.atom = "P"; break;
883       case BDF_MONOWIDTH: prop.value.atom = "M"; break;
884       case BDF_CHARCELL: prop.value.atom = "C"; break;
885     }
886     bdf_add_font_property(f, &prop);
887
888     /*
889      * Free up the row buffer if it was allocated.
890      */
891     if (row_size > 0)
892       free((char *) row);
893
894     /*
895      * Call the callback one last time if necessary.
896      */
897     if (callback != 0 && cb.current != cb.total) {
898         cb.reason = BDF_LOADING;
899         cb.total = cb.current = st.st_size;
900         (*callback)(&cb, data);
901     }
902
903     /*
904      * Add a message indicating the font was converted.
905      */
906     _bdf_add_comment(f, "Font converted from PK to BDF.", 30);
907     _bdf_add_acmsg(f, "Font converted from PK to BDF.", 30);
908
909     return BDF_OK;
910 }
911
912 static int
913 _bdf_gf_specials(FILE *in, bdf_font_t *font, bdf_options_t *opts,
914                  unsigned char glyphname[])
915 {
916     int c;
917     int i, n, num;
918     unsigned int comment_size;
919     unsigned char *comment, bytes[4];
920
921     /*
922      * Initialize the variable that keeps track of the storage allocated
923      * for the comments encountered.
924      */
925     comment = 0;
926     comment_size = 0;
927
928     while ((c = getc(in)) >= GF_xxx1) {
929         /*
930          * GF_xxx1 .. GF_xxx4 are string specials which will be added with the
931          * comments if comments are being kept.
932          */
933         if (c >= GF_xxx1 && c <= GF_xxx4) {
934             /*
935              * Determine the number of bytes that need to be read to determine
936              * the length of the string special.
937              */
938             n = (c - GF_xxx1) + 1;
939             fread((char *) bytes, n, 1, in);
940             for (i = 0, num = 0; i < n; i++)
941               num = (num << 8) | bytes[i];
942
943             if (opts->keep_comments) {
944                 /*
945                  * Make sure there is enough space for the string.
946                  */
947                 if (comment_size < num + 1) {
948                     if (comment_size == 0)
949                       comment = (unsigned char *) malloc(num + 1);
950                     else
951                       comment = (unsigned char *)
952                           realloc((char *) comment, num + 1);
953                     comment_size = num + 1;
954                 }
955                 /*
956                  * Read the comment and add it to the font.
957                  */
958                 fread((char *) comment, num, 1, in);
959                 comment[num] = 0;
960                 if (!strncmp((char *) comment, "title ", 6))
961                   /*
962                    * The comment is the glyph's name/title; save it so
963                    * it can be associated with the forthcoming glyph,
964                    * rather than with the font as a whole.
965                    */
966                   strcpy((char *) glyphname, (char *) comment + 6);
967                 else
968                   /*
969                    * A regular comment
970                    */
971                   _bdf_add_comment(font, (char *) comment, num);
972             } else
973               /*
974                * Skip the string special.
975                */
976               fseek(in, num, 1L);
977             c = GF_no_op;
978         }
979
980         /*
981          * GF_yyy is a numeric special.  Add the number as a comment if
982          * specified.
983          */
984         if (c == GF_yyy) {
985             num = _bdf_mf_get32(in);
986             if (opts->keep_comments) {
987                 if (comment_size < 64) {
988                     if (comment_size == 0)
989                       comment = (unsigned char *) malloc(64);
990                     else
991                       comment = (unsigned char *)
992                           realloc((char *) comment, 64);
993                     comment_size = 64;
994                 }
995                 sprintf((char *) comment, "%d", num);
996                 printscaled(num, comment + strlen((char *) comment));
997                 _bdf_add_comment(font, (char *) comment,
998                                  strlen((char *) comment));
999             }
1000             c = GF_no_op;
1001         }
1002         if (c != GF_no_op)
1003           break;
1004     }
1005
1006     /*
1007      * Free up the comment buffer if it was allocated.
1008      */
1009     if (comment_size > 0)
1010       free((char *) comment);
1011
1012     /*
1013      * Return the byte that caused the loop to terminate.
1014      */
1015     return c;
1016 }
1017
1018 static int
1019 _bdf_load_gf_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
1020                   void *data, bdf_font_t **font)
1021 {
1022     int n, res, set, x, y, bpr, ismono;
1023     int awidth, num;
1024     short rb, maxrb, minlb, maxlb;
1025     double denom, dw;
1026     bdf_font_t *f;
1027     bdf_glyph_t *gp, g;
1028     bdf_property_t prop;
1029     bdf_callback_struct_t cb;
1030     struct stat st;
1031     unsigned char bytes[256], glyphname[256];
1032
1033     glyphname[0] = 0;
1034
1035     /*
1036      * Create a font to work with.
1037      */
1038     *font = f = (bdf_font_t *) malloc(sizeof(bdf_font_t));
1039     (void) memset((char *) f, 0, sizeof(bdf_font_t));
1040
1041     /*
1042      * Set some defaults and allocate an initial amount of space.  Make the
1043      * initial assumption that the font is monowidth but determine if it
1044      * should be proportional when the glyphs are loaded.  Allocate space for
1045      * at least 128 glyphs before loading the font.
1046      */
1047     f->bpp = 1;
1048     f->spacing = BDF_MONOWIDTH;
1049     f->glyphs_size = 128;
1050     f->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) << 7);
1051     (void) memset((char *) f->glyphs, 0, sizeof(bdf_glyph_t) << 7);
1052
1053     /*
1054      * Initialize the horizontal and vertical offsets of the font to some
1055      * large number.
1056      */
1057     f->bbx.x_offset = f->bbx.y_offset = 32767;
1058
1059     /*
1060      * Initialize things.
1061      */
1062     ismono = 1;
1063     awidth = 0;
1064     rb = maxrb = maxlb = 0;
1065     minlb = 32767;
1066     (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
1067
1068     /*
1069      * Load the initial comment.
1070      */
1071     fread((char *) bytes, 1, 1, in);
1072     n = bytes[0];
1073     fread(bytes, n, 1, in);
1074     bytes[n] = 0;
1075
1076     /*
1077      * Add the comment to the font if indicated.
1078      */
1079     if (opts->keep_comments)
1080       _bdf_add_comment(f, (char *) bytes, (unsigned int) n);
1081
1082     /*
1083      * Get the font info so we can set up the callback.  The callback will
1084      * update after every glyph is loaded and is based on file size instead of
1085      * number of glyphs.  This allows the font to be read all at once instead
1086      * of twice.
1087      */
1088     (void) fstat(fileno(in), &st);
1089
1090     /*
1091      * Set the callback up.
1092      */
1093     if (callback != 0) {
1094         cb.reason = BDF_LOAD_START;
1095         cb.current = 0;
1096         cb.total = st.st_size;
1097         (*callback)(&cb, data);
1098     }
1099
1100     while ((res = _bdf_gf_specials(in, f, opts, glyphname)) != GF_post) {
1101         /* Set the glyph's name, if we've seen it */
1102         if (((res == GF_boc) || (res == GF_boc1)) &&
1103             strlen((char *) glyphname)) {
1104             g.name = malloc(strlen((char *) glyphname)+1);
1105             strcpy(g.name, (char *) glyphname);
1106         }
1107
1108         if (res == GF_boc) {
1109             /* 32-bit character code */
1110             if ((g.encoding = _bdf_mf_get32(in) & 0xff) < 0)
1111               g.encoding += 256;
1112             /* Skip navigation pointer that's not relevant for us */
1113             (void) _bdf_mf_get32(in);
1114             /* 4 times 32-bit loose bounding box parameters */
1115             g.bbx.x_offset = -((short) _bdf_mf_get32(in));
1116             g.bbx.width =
1117                 (unsigned short) (_bdf_mf_get32(in) + g.bbx.x_offset);
1118             g.bbx.y_offset = (short) _bdf_mf_get32(in);
1119             g.bbx.height =
1120                 (unsigned short) (_bdf_mf_get32(in) - g.bbx.y_offset);
1121             g.bbx.height++;
1122             g.bbx.ascent = g.bbx.height + g.bbx.y_offset;
1123             g.bbx.descent = -g.bbx.y_offset;
1124         } else if (res == GF_boc1) {
1125             g.encoding = getc(in);
1126             g.bbx.width = getc(in);
1127             g.bbx.x_offset = getc(in) - g.bbx.width;
1128             g.bbx.height = getc(in);
1129             g.bbx.y_offset = getc(in) - g.bbx.height;
1130             g.bbx.height++;
1131             g.bbx.width++;
1132             g.bbx.ascent = g.bbx.height + g.bbx.y_offset;
1133             g.bbx.descent = -g.bbx.y_offset;
1134         }
1135
1136         /*
1137          * Check to see if the font needs to be marked as proportional.
1138          */
1139         if (f->glyphs_used > 0 && ismono &&
1140             (f->glyphs[0].bbx.width != g.bbx.width ||
1141              f->glyphs[0].bbx.height != g.bbx.height ||
1142              f->glyphs[0].bbx.x_offset != g.bbx.x_offset ||
1143              f->glyphs[0].bbx.y_offset != g.bbx.y_offset ||
1144              f->glyphs[0].bbx.ascent != g.bbx.ascent ||
1145              f->glyphs[0].bbx.descent != g.bbx.descent)) {
1146             ismono = 0;
1147             f->spacing = BDF_PROPORTIONAL;
1148         }
1149
1150         bpr = (g.bbx.width + 7) >> 3;
1151         g.bytes = g.bbx.height * bpr;
1152         g.bitmap = (unsigned char *) malloc(g.bytes);
1153         (void) memset((char *) g.bitmap, 0, g.bytes);
1154
1155         /*
1156          * Get the glyph.
1157          */
1158         set = x = y = 0;
1159         while ((res = getc(in)) < GF_xxx1) {
1160             if (res == GF_eoc)
1161               break;
1162             if (res < GF_paint3) {
1163                 switch (res) {
1164                   case GF_paint1:
1165                     res = getc(in);
1166                     break;
1167                   case GF_paint2:
1168                     res = _bdf_mf_get16(in);
1169                     break;
1170                   case GF_paint3:
1171                     res = (_bdf_mf_get16(in) << 8) | (getc(in) & 0xff);
1172                     break;
1173                 }
1174                 for (; res > 0; x++, res--) {
1175                     if (set)
1176                       g.bitmap[(y * bpr) + (x >> 3)] |= (0x80 >> (x & 7));
1177                 }
1178                 set = !set;
1179             } else if (GF_skip0 <= res && res <= GF_skip3) {
1180                 switch (res) {
1181                   case GF_skip1:
1182                     res = getc(in);
1183                     break;
1184                   case GF_skip2:
1185                     res = _bdf_mf_get16(in);
1186                     break;
1187                   case GF_skip3:
1188                     res = (_bdf_mf_get16(in) << 8) | (getc(in) & 0xff);
1189                     break;
1190                   default:
1191                     res = 0;
1192                 }
1193                 x = 0;
1194                 y += res;
1195                 set = 0;
1196             } else if (GF_newrow_0 <= res && res <= GF_newrow_164) {
1197                 y++;
1198                 x = res - GF_newrow_0;
1199                 set = 1;
1200             }
1201         }
1202
1203         /*
1204          * Adjust the font bounding box.
1205          */
1206         f->bbx.ascent = MAX(g.bbx.ascent, f->bbx.ascent);
1207         f->bbx.descent = MAX(g.bbx.descent, f->bbx.descent);
1208
1209         rb = g.bbx.width + g.bbx.x_offset;
1210         maxrb = MAX(rb, maxrb);
1211         minlb = MIN(g.bbx.x_offset, minlb);
1212         maxlb = MAX(g.bbx.x_offset, maxlb);
1213
1214         /*
1215          * Increase the average width count to be used later.
1216          */
1217         awidth += g.bbx.width;
1218
1219         if ((g.encoding < 0 || g.encoding > 65535) && opts->keep_unencoded) {
1220             /*
1221              * If the glyph is unencoded (encoding field < 0 or > 65535) and
1222              * the unencoded glyphs should be kept, then add the glyph to the
1223              * unencoded list of the font.
1224              */
1225             if (f->unencoded_used == f->unencoded_size) {
1226                 if (f->unencoded_size == 0)
1227                   f->unencoded = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t));
1228                 else
1229                   f->unencoded = (bdf_glyph_t *)
1230                       realloc((char *) f->unencoded,
1231                               sizeof(bdf_glyph_t) * (f->unencoded_size + 1));
1232                 f->unencoded_size++;
1233             }
1234             (void) memcpy((char *) (f->unencoded + f->unencoded_used),
1235                           (char *) &g, sizeof(bdf_glyph_t));
1236             f->unencoded_used++;
1237         } else if (g.encoding >= 0 && g.encoding <= 65535) {
1238             /*
1239              * Add the glyph to the encoded list.
1240              */
1241             if (f->glyphs_used == f->glyphs_size) {
1242                 /*
1243                  * Expand by 128 glyphs at a time.
1244                  */
1245                 if (f->glyphs_used == 0)
1246                   f->glyphs = (bdf_glyph_t *)
1247                       malloc(sizeof(bdf_glyph_t) << 7);
1248                 else
1249                   f->glyphs = (bdf_glyph_t *)
1250                       realloc((char *) f->glyphs,
1251                               sizeof(bdf_glyph_t) * (f->glyphs_used + 128));
1252                 gp = f->glyphs + f->glyphs_used;
1253                 (void) memset((char *) gp, 0, sizeof(bdf_glyph_t) << 7);
1254                 f->glyphs_size += 128;
1255             }
1256             gp = f->glyphs + f->glyphs_used++;
1257             (void) memcpy((char *) gp, (char *) &g, sizeof(bdf_glyph_t));;
1258         } else {
1259             /*
1260              * Free up the memory allocated for the temporary glyph so it
1261              * doesn't leak.
1262              */
1263             if (g.bytes > 0)
1264               free((char *) g.bitmap);
1265         }
1266
1267         /*
1268          * Make sure the temporary glyph is reinitialized.
1269          */
1270         (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
1271
1272         /*
1273          * We're done with this glyph; forget we've seen its name
1274          */
1275         glyphname[0] = 0;
1276
1277         /*
1278          * Call the callback if indicated.
1279          */
1280         if (callback != 0) {
1281             cb.reason = BDF_LOADING;
1282             cb.total = st.st_size;
1283             cb.current = ftell(in);
1284             (*callback)(&cb, data);
1285         }
1286
1287         if (res == GF_post)
1288           break;
1289     }
1290
1291     /*
1292      * Sort all the glyphs by encoding.
1293      */
1294     qsort((char *) f->glyphs, f->glyphs_used, sizeof(bdf_glyph_t),
1295           by_encoding);
1296
1297     /*
1298      * Adjust the font bounding box from the values collected.
1299      */
1300     f->bbx.width = maxrb - minlb;
1301     f->bbx.height = f->bbx.ascent + f->bbx.descent;
1302     f->bbx.x_offset = minlb;
1303     f->bbx.y_offset = -f->bbx.descent;
1304
1305     /*
1306      * Set the default character as being undefined.
1307      */
1308     f->default_glyph = -1;
1309
1310     /*
1311      * Set the font ascent and descent.
1312      */
1313     f->font_ascent = f->bbx.ascent;
1314     f->font_descent = f->bbx.descent;
1315
1316     /*
1317      * Collect the remaining font info from the postamble.
1318      */
1319     (void) _bdf_mf_get32(in);
1320
1321     /*
1322      * Get the point size and scale it down 
1323      */
1324     f->point_size = (int) (((float) _bdf_mf_get32(in)) /
1325                             ((float) (1 << 20)));
1326
1327     /*
1328      * Skip the checksum.
1329      */
1330     fseek(in, 4, 1L);
1331
1332     /*
1333      * Get the horizontal resolution.
1334      */
1335     f->resolution_x = (int)
1336         (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
1337
1338     /*
1339      * Get the vertical resolution.
1340      */
1341     f->resolution_y = (int)
1342         (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
1343
1344     /*
1345      * Skip the overall font rows and columns because they have already
1346      * been determined.
1347      */
1348     fseek(in, 16, 1L);
1349
1350     /*
1351      * Determine the denominator used for scalable width calculations.
1352      */
1353     denom = ((double) f->point_size) *
1354         ((double) f->resolution_x);
1355
1356     /*
1357      * Cycle through the glyph specific info and set the device and scalable
1358      * widths.
1359      */
1360     while ((res = getc(in)) != GF_post_post) {
1361         /*
1362          * Get the encoding and locate it in the font.
1363          */
1364         num = getc(in);
1365         for (set = 0, gp = f->glyphs;
1366              set < f->glyphs_used && gp->encoding != num; gp++, set++) ;
1367         /*
1368          * If the glyph is not found for some reason, make the glyph pointer
1369          * point to the temporary glyph storage.
1370          */
1371         if (set == f->glyphs_used)
1372           gp = &g;
1373
1374         if (res == GF_char_loc) {
1375             /*
1376              * Get both horizontal and vertical escapement, only keeping
1377              * the horizontal for the device width.
1378              */
1379             num = _bdf_mf_get32(in);
1380             gp->dwidth = num >> 16;
1381             dw = (double) gp->dwidth;
1382             gp->swidth = (unsigned short) ((dw * 72000.0) / denom);
1383             (void) _bdf_mf_get32(in);
1384         } else if (res == GF_char_loc0) {
1385             gp->dwidth = (unsigned short) getc(in);
1386             dw = (double) gp->dwidth;
1387             gp->swidth = (unsigned short) ((dw * 72000.0) / denom);
1388         }
1389
1390         /*
1391          * Skip the TFM width and the glyph file offset.
1392          */
1393         fseek(in, 8, 1L);
1394
1395         /*
1396          * Call the callback if indicated.
1397          */
1398         if (callback != 0) {
1399             cb.reason = BDF_LOADING;
1400             cb.total = st.st_size;
1401             cb.current = ftell(in);
1402             (*callback)(&cb, data);
1403         }
1404     }
1405
1406     /*
1407      * Now add the properties to the font.
1408      */
1409     prop.name = "POINT_SIZE";
1410     prop.format = BDF_INTEGER;
1411     prop.value.int32 = f->point_size * 10;
1412     bdf_add_font_property(f, &prop);
1413
1414     /*
1415      * Calculate and add the pixel size.
1416      */
1417     denom = (double) f->resolution_y;
1418     dw = (double) (f->point_size * 10);
1419     prop.name = "PIXEL_SIZE";
1420     prop.format = BDF_INTEGER;
1421     prop.value.int32 = (int) (((denom * dw) / 722.7) + 0.5);
1422     bdf_add_font_property(f, &prop);
1423
1424     prop.name = "RESOLUTION_X";
1425     prop.format = BDF_CARDINAL;
1426     prop.value.card32 = (unsigned int) f->resolution_x;
1427     bdf_add_font_property(f, &prop);
1428
1429     prop.name = "RESOLUTION_Y";
1430     prop.format = BDF_CARDINAL;
1431     prop.value.card32 = (unsigned int) f->resolution_y;
1432     bdf_add_font_property(f, &prop);
1433
1434     prop.name = "FONT_ASCENT";
1435     prop.format = BDF_INTEGER;
1436     prop.value.int32 = f->font_ascent;
1437     bdf_add_font_property(f, &prop);
1438
1439     prop.name = "FONT_DESCENT";
1440     prop.format = BDF_INTEGER;
1441     prop.value.int32 = f->font_descent;
1442     bdf_add_font_property(f, &prop);
1443
1444     prop.name = "AVERAGE_WIDTH";
1445     prop.format = BDF_INTEGER;
1446     prop.value.int32 = (awidth / (f->unencoded_used + f->glyphs_used)) * 10;
1447     bdf_add_font_property(f, &prop);
1448
1449     /*
1450      * Default all PK fonts to proportional spacing.
1451      */
1452     prop.name = "SPACING";
1453     prop.format = BDF_ATOM;
1454     prop.value.atom = "P";
1455     switch (f->spacing) {
1456       case BDF_PROPORTIONAL: prop.value.atom = "P"; break;
1457       case BDF_MONOWIDTH: prop.value.atom = "M"; break;
1458       case BDF_CHARCELL: prop.value.atom = "C"; break;
1459     }
1460     bdf_add_font_property(f, &prop);
1461
1462     /*
1463      * Call the callback one last time if necessary.
1464      */
1465     if (callback != 0 && cb.current != cb.total) {
1466         cb.reason = BDF_LOADING;
1467         cb.total = cb.current = st.st_size;
1468         (*callback)(&cb, data);
1469     }
1470
1471     /*
1472      * Add a message indicating the font was converted.
1473      */
1474     _bdf_add_comment(f, "Font converted from GF to BDF.", 30);
1475     _bdf_add_acmsg(f, "Font converted from GF to BDF.", 30);
1476
1477     return BDF_OK;
1478 }
1479
1480 int
1481 bdf_load_mf_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
1482                  void *data, bdf_font_t **font)
1483 {
1484     unsigned char mfmag[2];
1485
1486     /*
1487      * Load the header to see if this is a GF or PK font.
1488      */
1489     fread((char *) mfmag, 2, 1, in);
1490     if (mfmag[0] != GF_pre || (mfmag[1] != PK_id && mfmag[1] != 0x83))
1491       return BDF_NOT_MF_FONT;
1492     return (mfmag[1] == PK_id) ?
1493         _bdf_load_pk_font(in, opts, callback, data, font) :
1494         _bdf_load_gf_font(in, opts, callback, data, font);
1495 }