2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 * Routines to import GF and PK format bitmap font files.
26 * GF is the "generic font" file format for bitmap fonts; GF files are
27 * typically produced by Metafont.
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).
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.
44 #include <sys/types.h>
49 #include <X11/Xutil.h>
50 #include <X11/Xatom.h>
51 #endif /* !BDF_NO_X11 */
56 #define MAX(h, i) ((h) > (i) ? (h) : (i))
59 #define MIN(l, o) ((l) < (o) ? (l) : (o))
62 * Symbolic names for the opcode bytes in GF files.
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 */
89 * Symbolic names for the opcode bytes in PK files.
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 */
101 * Structure used to track the state for various things when reading a font.
110 * Routine to compare two glyphs by encoding so they can be sorted.
113 by_encoding(const void *a, const void *b)
115 bdf_glyph_t *c1, *c2;
117 c1 = (bdf_glyph_t *) a;
118 c2 = (bdf_glyph_t *) b;
119 if (c1->encoding < c2->encoding)
121 else if (c1->encoding > c2->encoding)
127 * Routines for scanning numbers from GF and PK files.
130 _bdf_mf_get16(FILE *in)
132 return (getc(in) << 8) | (getc(in) & 0xff);
136 _bdf_mf_get32(FILE *in)
138 int hi = _bdf_mf_get16(in);
142 return (hi << 16) + _bdf_mf_get16(in);
146 printscaled(int s, unsigned char *buf)
156 sprintf((char *) buf, "%d", s >> 16);
157 buf += strlen((char *) buf);
158 s = 10 * ( s & 65535 ) + 5;
164 s = s + 32768 - (delta >> 1);
165 *buf++ = 0x30 + (s >> 16);
166 s = 10 * (s & 65535);
170 sprintf((char *) buf, " scaled)");
174 * Routine to scan the PK specials and add them as comments if necessary.
177 _bdf_pk_specials(FILE *in, bdf_font_t *font, bdf_options_t *opts,
178 unsigned char *glyphname)
182 unsigned int comment_size;
183 unsigned char *comment, bytes[4];
186 * Initialize the variable that keeps track of the storage allocated
187 * for the comments encountered.
192 while ((c = getc(in)) >= PK_xxx1 && c != GF_char_loc) {
194 * Anything between PK_reserved1 and 0xff are bad values. PK_pre is
195 * the font preamble which is not expected here.
197 if (c == PK_pre || (c >= PK_post && c <= 0xff))
201 * Anything between PK_xxx1 and PK_xxx4 are string specials which will
202 * be added with the comments if comments are being kept.
204 if (c >= PK_xxx1 && c <= PK_xxx4) {
206 * Determine the number of bytes that need to be read to determine
207 * the length of the string special.
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];
214 if (opts->keep_comments) {
216 * Make sure there is enough space for the string.
218 if (comment_size < num + 1) {
219 if (comment_size == 0)
220 comment = (unsigned char *) malloc(num + 1);
222 comment = (unsigned char *)
223 realloc((char *) comment, num + 1);
224 comment_size = num + 1;
227 * Read the comment and add it to the font.
229 fread((char *) comment, num, 1, in);
231 if (!strncmp((char *) comment, "title ", 6))
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.
237 strcpy((char *) glyphname, (char *) comment + 6);
242 _bdf_add_comment(font, (char *) comment, num);
245 * Skip the string special.
251 * PK_yyy is a numeric special. Add the number as a comment if
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);
261 comment = (unsigned char *)
262 realloc((char *) comment, 64);
265 sprintf((char *) comment, "%d", num);
266 printscaled(num, comment + strlen((char *) comment));
267 _bdf_add_comment(font, (char *) comment,
268 strlen((char *) comment));
274 * Free up the comment buffer if it was allocated.
276 if (comment_size > 0)
277 free((char *) comment);
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.
287 * Awkward little routine to collect packed bits from a PK file.
290 _bdf_pk_getbit(FILE *in, _bdf_mf_state_t *state)
293 if (state->mask == 0) {
297 return (state->c & state->mask);
301 * Another awkward little routine to get 4 bits at a time from a PK file.
304 _bdf_pk_getnybble(FILE *in, _bdf_mf_state_t *state)
308 if (state->top == 0) {
312 r = (state->c >> ((state->top - 1) << 2)) & 0x0f;
318 * Yet another awkward routine to read a packed number and a repeat count from
322 _bdf_pk_getpacked(FILE *in, int *rcount, int dyn, _bdf_mf_state_t *state)
326 if ((i = _bdf_pk_getnybble(in, state)) == 0) {
328 j = _bdf_pk_getnybble(in, state);
332 j = (j << 4) + _bdf_pk_getnybble(in, state);
333 return j - 15 + ((13 - dyn) << 4) + dyn;
340 return ((i - dyn - 1) << 4) + dyn + 1 + _bdf_pk_getnybble(in, state);
342 *rcount = (i == 14) ? _bdf_pk_getpacked(in, rcount, dyn, state) : 1;
343 return _bdf_pk_getpacked(in, rcount, dyn, state);
347 _bdf_load_pk_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
348 void *data, bdf_font_t **font)
350 int n, res, set, x, y, bpr, rcnt, ismono;
351 int num, plen, pend, row_size, awidth;
352 short rb, maxrb, minlb, maxlb;
357 bdf_callback_struct_t cb;
358 _bdf_mf_state_t state;
360 unsigned char *row, bytes[256], glyphname[256];
366 * Create a font to work with.
368 *font = f = (bdf_font_t *) malloc(sizeof(bdf_font_t));
369 (void) memset((char *) f, 0, sizeof(bdf_font_t));
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.
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);
384 * Initialize the horizontal and vertical offsets of the font to some
387 f->bbx.x_offset = f->bbx.y_offset = 32767;
395 rb = maxrb = maxlb = 0;
397 (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
400 * Load the initial comment.
402 fread((char *) bytes, 1, 1, in);
404 fread(bytes, n, 1, in);
408 * Add the comment to the font if indicated.
410 if (opts->keep_comments)
411 _bdf_add_comment(f, (char *) bytes, (unsigned int) n);
414 * Get the point size and scale it down
416 f->point_size = (int) (((float) _bdf_mf_get32(in)) /
417 ((float) (1 << 20)));
422 fread(bytes, 4, 1, in);
425 * Get the horizontal resolution.
427 f->resolution_x = (int)
428 (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
431 * Get the vertical resolution.
433 f->resolution_y = (int)
434 (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
437 * Determine the denominator used for scalable width calculations.
439 denom = ((double) f->point_size) * ((double) f->resolution_x);
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
447 (void) fstat(fileno(in), &st);
450 * Set the callback up.
453 cb.reason = BDF_LOAD_START;
455 cb.total = st.st_size;
456 (*callback)(&cb, data);
463 while ((res = _bdf_pk_specials(in, f, opts, glyphname)) != PK_post &&
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);
470 if ((res & 7) == 7) {
476 * Get the packet length and glyph encoding.
478 plen = _bdf_mf_get32(in);
479 g.encoding = _bdf_mf_get32(in);
481 pend = plen + ftell(in);
484 * Get the glyph metrics.
488 * Ignore the TFM width.
490 (void) _bdf_mf_get32(in);
493 * Get the device width (DWIDTH) from the horizontal escapement of
494 * the glyph and calculate the scalable width (SWIDTH) from it.
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);
502 * Ignore the vertical escapement.
504 (void) _bdf_mf_get32(in);
507 * Collect the remaining glyph metrics info and calculate the
508 * glyph ascent and descent from the height and vertical offset.
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) {
516 * Extended glyph info.
519 plen = (((res & 0x07) - 4) << 16) + _bdf_mf_get16(in);
521 plen = (((res & 0x0f) - 4) << 16) + _bdf_mf_get16(in);
524 * Load the encoding byte and the first byte of the TFM width.
526 fread(bytes, 2, 1, in);
527 g.encoding = (int) bytes[0];
529 pend = plen + ftell(in) - 1;
532 * Get the glyph metrics.
536 * Ignore the last two bytes of the TFM width.
538 (void) _bdf_mf_get16(in);
541 * Get the device width (DWIDTH) from the horizontal escapement of
542 * the glyph and calculate the scalable width (SWIDTH) from it.
544 g.dwidth = (unsigned short) _bdf_mf_get16(in);
545 dw = (double) g.dwidth;
546 g.swidth = (unsigned short) ((dw * 72000.0) / denom);
549 * Collect the remaining glyph metrics info and calculate the
550 * glyph ascent and descent from the height and vertical offset.
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;
557 g.bbx.x_offset = (short) num;
558 if ((num = _bdf_mf_get16(in)) > 32767)
559 g.bbx.y_offset = num - 65536;
561 g.bbx.y_offset = (short) num;
564 * Short glyph info. Read the next 10 bytes so they can be used
565 * as part of the glyph info calculations.
567 fread(bytes, 10, 1, in);
571 plen = ((res & 0x07) << 8) + bytes[num++];
573 plen = ((res & 0x0f) << 8) + bytes[num++];
575 g.encoding = (int) bytes[num++];
577 pend = plen + ftell(in) - 8;
580 * Skip the TFM width.
585 * Get the device width (DWIDTH) from the horizontal escapement of
586 * the glyph and calculate the scalable width (SWIDTH) from it.
588 g.dwidth = (unsigned short) bytes[num++];
589 dw = (double) g.dwidth;
590 g.swidth = (unsigned short) ((dw * 72000.0) / denom);
593 * Collect the remaining glyph metrics info and calculate the
594 * glyph ascent and descent from the height and vertical offset.
596 g.bbx.width = (unsigned short) bytes[num++];
597 g.bbx.height = (unsigned short) bytes[num++];
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
605 g.bbx.x_offset = (short) ((bytes[num] & 0x80) ?
606 256 - bytes[num] : bytes[num]);
608 g.bbx.y_offset = (short) ((bytes[num] & 0x80) ?
609 bytes[num] - 256 : bytes[num]);
614 * Adjust the vertical metrics of the glyph.
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;
621 * Check to see if the font needs to be marked as proportional.
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)) {
631 f->spacing = BDF_PROPORTIONAL;
635 * Now load the packed bits or the run length encoded image.
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);
643 * Reset the state values.
645 state.top = state.mask = state.c = 0;
646 if ((res & 0xf0) == 0xe0) {
650 if ((g.bbx.width & 7) == 0)
652 * The bits are on a boundary that is a multiple of 8, so the
653 * bitmap can be read all at once.
655 fread(g.bitmap, g.bbx.height * bpr, 1, in);
658 * The width is not a multiple of 8, so the bitmap should be
659 * read one bit at a time.
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));
670 * Get the run length encoded image.
674 * The glyph image is going to be run length encoded, so allocate
675 * a row to collect bits into.
677 if (row_size < bpr) {
679 row = (unsigned char *) malloc(bpr);
681 row = (unsigned char *) realloc((char *) row, bpr);
685 * Initialize the row buffer so we don't get any extra bits in the
688 (void) memset((char *) row, 0, row_size);
691 * Determine if the run length encoding starts with bits that are
692 * to be set or cleared.
695 for (rcnt = x = y = 0; y < g.bbx.height;) {
697 * Get the next number and a repeat count.
699 n = _bdf_pk_getpacked(in, &rcnt, (res >> 4) & 0x0f, &state);
701 for (; n > 0 && x < g.bbx.width; x++, n--) {
703 row[x >> 3] |= (0x80 >> (x & 7));
705 if (x == g.bbx.width) {
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
712 for (x = 0; rcnt >= 0; rcnt--, y++)
713 (void) memcpy((char *) (g.bitmap + (y * bpr)),
715 (void) memset((char *) row, 0, bpr);
720 * Invert the flag that indicates whether bits need
728 * Adjust the font bounding box.
730 f->bbx.ascent = MAX(g.bbx.ascent, f->bbx.ascent);
731 f->bbx.descent = MAX(g.bbx.descent, f->bbx.descent);
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);
739 * Increase the average width count to be used later.
741 awidth += g.bbx.width;
743 if ((g.encoding < 0 || g.encoding > 65535) && opts->keep_unencoded) {
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.
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));
753 f->unencoded = (bdf_glyph_t *)
754 realloc((char *) f->unencoded,
755 sizeof(bdf_glyph_t) * (f->unencoded_size + 1));
758 (void) memcpy((char *) (f->unencoded + f->unencoded_used),
759 (char *) &g, sizeof(bdf_glyph_t));
761 } else if (g.encoding >= 0 && g.encoding <= 65535) {
763 * Add the glyph to the encoded list.
765 if (f->glyphs_used == f->glyphs_size) {
767 * Expand by 128 glyphs at a time.
769 if (f->glyphs_used == 0)
770 f->glyphs = (bdf_glyph_t *)
771 malloc(sizeof(bdf_glyph_t) << 7);
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;
780 gp = f->glyphs + f->glyphs_used++;
781 (void) memcpy((char *) gp, (char *) &g, sizeof(bdf_glyph_t));;
784 * Free up the memory allocated for the temporary glyph so it
788 free((char *) g.bitmap);
792 * Make sure the temporary glyph is reinitialized.
794 (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
797 * Call the callback if indicated.
800 cb.reason = BDF_LOADING;
801 cb.total = st.st_size;
802 cb.current = ftell(in);
803 (*callback)(&cb, data);
808 * Sort all the glyphs by encoding.
810 qsort((char *) f->glyphs, f->glyphs_used, sizeof(bdf_glyph_t),
814 * Adjust the font bounding box from the values collected.
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;
822 * Set the default character as being undefined.
824 f->default_glyph = -1;
827 * Set the font ascent and descent.
829 f->font_ascent = f->bbx.ascent;
830 f->font_descent = f->bbx.descent;
833 * Now add the properties to the font.
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);
841 * Calculate and add the pixel size.
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);
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);
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);
860 prop.name = "FONT_ASCENT";
861 prop.format = BDF_INTEGER;
862 prop.value.int32 = f->font_ascent;
863 bdf_add_font_property(f, &prop);
865 prop.name = "FONT_DESCENT";
866 prop.format = BDF_INTEGER;
867 prop.value.int32 = f->font_descent;
868 bdf_add_font_property(f, &prop);
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);
876 * Default all PK fonts to proportional spacing.
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;
886 bdf_add_font_property(f, &prop);
889 * Free up the row buffer if it was allocated.
895 * Call the callback one last time if necessary.
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);
904 * Add a message indicating the font was converted.
906 _bdf_add_comment(f, "Font converted from PK to BDF.", 30);
907 _bdf_add_acmsg(f, "Font converted from PK to BDF.", 30);
913 _bdf_gf_specials(FILE *in, bdf_font_t *font, bdf_options_t *opts,
914 unsigned char glyphname[])
918 unsigned int comment_size;
919 unsigned char *comment, bytes[4];
922 * Initialize the variable that keeps track of the storage allocated
923 * for the comments encountered.
928 while ((c = getc(in)) >= GF_xxx1) {
930 * GF_xxx1 .. GF_xxx4 are string specials which will be added with the
931 * comments if comments are being kept.
933 if (c >= GF_xxx1 && c <= GF_xxx4) {
935 * Determine the number of bytes that need to be read to determine
936 * the length of the string special.
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];
943 if (opts->keep_comments) {
945 * Make sure there is enough space for the string.
947 if (comment_size < num + 1) {
948 if (comment_size == 0)
949 comment = (unsigned char *) malloc(num + 1);
951 comment = (unsigned char *)
952 realloc((char *) comment, num + 1);
953 comment_size = num + 1;
956 * Read the comment and add it to the font.
958 fread((char *) comment, num, 1, in);
960 if (!strncmp((char *) comment, "title ", 6))
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.
966 strcpy((char *) glyphname, (char *) comment + 6);
971 _bdf_add_comment(font, (char *) comment, num);
974 * Skip the string special.
981 * GF_yyy is a numeric special. Add the number as a comment if
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);
991 comment = (unsigned char *)
992 realloc((char *) comment, 64);
995 sprintf((char *) comment, "%d", num);
996 printscaled(num, comment + strlen((char *) comment));
997 _bdf_add_comment(font, (char *) comment,
998 strlen((char *) comment));
1007 * Free up the comment buffer if it was allocated.
1009 if (comment_size > 0)
1010 free((char *) comment);
1013 * Return the byte that caused the loop to terminate.
1019 _bdf_load_gf_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
1020 void *data, bdf_font_t **font)
1022 int n, res, set, x, y, bpr, ismono;
1024 short rb, maxrb, minlb, maxlb;
1028 bdf_property_t prop;
1029 bdf_callback_struct_t cb;
1031 unsigned char bytes[256], glyphname[256];
1036 * Create a font to work with.
1038 *font = f = (bdf_font_t *) malloc(sizeof(bdf_font_t));
1039 (void) memset((char *) f, 0, sizeof(bdf_font_t));
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.
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);
1054 * Initialize the horizontal and vertical offsets of the font to some
1057 f->bbx.x_offset = f->bbx.y_offset = 32767;
1060 * Initialize things.
1064 rb = maxrb = maxlb = 0;
1066 (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
1069 * Load the initial comment.
1071 fread((char *) bytes, 1, 1, in);
1073 fread(bytes, n, 1, in);
1077 * Add the comment to the font if indicated.
1079 if (opts->keep_comments)
1080 _bdf_add_comment(f, (char *) bytes, (unsigned int) n);
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
1088 (void) fstat(fileno(in), &st);
1091 * Set the callback up.
1093 if (callback != 0) {
1094 cb.reason = BDF_LOAD_START;
1096 cb.total = st.st_size;
1097 (*callback)(&cb, data);
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);
1108 if (res == GF_boc) {
1109 /* 32-bit character code */
1110 if ((g.encoding = _bdf_mf_get32(in) & 0xff) < 0)
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));
1117 (unsigned short) (_bdf_mf_get32(in) + g.bbx.x_offset);
1118 g.bbx.y_offset = (short) _bdf_mf_get32(in);
1120 (unsigned short) (_bdf_mf_get32(in) - g.bbx.y_offset);
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;
1132 g.bbx.ascent = g.bbx.height + g.bbx.y_offset;
1133 g.bbx.descent = -g.bbx.y_offset;
1137 * Check to see if the font needs to be marked as proportional.
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)) {
1147 f->spacing = BDF_PROPORTIONAL;
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);
1159 while ((res = getc(in)) < GF_xxx1) {
1162 if (res < GF_paint3) {
1168 res = _bdf_mf_get16(in);
1171 res = (_bdf_mf_get16(in) << 8) | (getc(in) & 0xff);
1174 for (; res > 0; x++, res--) {
1176 g.bitmap[(y * bpr) + (x >> 3)] |= (0x80 >> (x & 7));
1179 } else if (GF_skip0 <= res && res <= GF_skip3) {
1185 res = _bdf_mf_get16(in);
1188 res = (_bdf_mf_get16(in) << 8) | (getc(in) & 0xff);
1196 } else if (GF_newrow_0 <= res && res <= GF_newrow_164) {
1198 x = res - GF_newrow_0;
1204 * Adjust the font bounding box.
1206 f->bbx.ascent = MAX(g.bbx.ascent, f->bbx.ascent);
1207 f->bbx.descent = MAX(g.bbx.descent, f->bbx.descent);
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);
1215 * Increase the average width count to be used later.
1217 awidth += g.bbx.width;
1219 if ((g.encoding < 0 || g.encoding > 65535) && opts->keep_unencoded) {
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.
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));
1229 f->unencoded = (bdf_glyph_t *)
1230 realloc((char *) f->unencoded,
1231 sizeof(bdf_glyph_t) * (f->unencoded_size + 1));
1232 f->unencoded_size++;
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) {
1239 * Add the glyph to the encoded list.
1241 if (f->glyphs_used == f->glyphs_size) {
1243 * Expand by 128 glyphs at a time.
1245 if (f->glyphs_used == 0)
1246 f->glyphs = (bdf_glyph_t *)
1247 malloc(sizeof(bdf_glyph_t) << 7);
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;
1256 gp = f->glyphs + f->glyphs_used++;
1257 (void) memcpy((char *) gp, (char *) &g, sizeof(bdf_glyph_t));;
1260 * Free up the memory allocated for the temporary glyph so it
1264 free((char *) g.bitmap);
1268 * Make sure the temporary glyph is reinitialized.
1270 (void) memset((char *) &g, 0, sizeof(bdf_glyph_t));
1273 * We're done with this glyph; forget we've seen its name
1278 * Call the callback if indicated.
1280 if (callback != 0) {
1281 cb.reason = BDF_LOADING;
1282 cb.total = st.st_size;
1283 cb.current = ftell(in);
1284 (*callback)(&cb, data);
1292 * Sort all the glyphs by encoding.
1294 qsort((char *) f->glyphs, f->glyphs_used, sizeof(bdf_glyph_t),
1298 * Adjust the font bounding box from the values collected.
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;
1306 * Set the default character as being undefined.
1308 f->default_glyph = -1;
1311 * Set the font ascent and descent.
1313 f->font_ascent = f->bbx.ascent;
1314 f->font_descent = f->bbx.descent;
1317 * Collect the remaining font info from the postamble.
1319 (void) _bdf_mf_get32(in);
1322 * Get the point size and scale it down
1324 f->point_size = (int) (((float) _bdf_mf_get32(in)) /
1325 ((float) (1 << 20)));
1328 * Skip the checksum.
1333 * Get the horizontal resolution.
1335 f->resolution_x = (int)
1336 (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
1339 * Get the vertical resolution.
1341 f->resolution_y = (int)
1342 (((((float) _bdf_mf_get32(in)) * 72.27) / ((float) (1 << 16))) + 0.5);
1345 * Skip the overall font rows and columns because they have already
1351 * Determine the denominator used for scalable width calculations.
1353 denom = ((double) f->point_size) *
1354 ((double) f->resolution_x);
1357 * Cycle through the glyph specific info and set the device and scalable
1360 while ((res = getc(in)) != GF_post_post) {
1362 * Get the encoding and locate it in the font.
1365 for (set = 0, gp = f->glyphs;
1366 set < f->glyphs_used && gp->encoding != num; gp++, set++) ;
1368 * If the glyph is not found for some reason, make the glyph pointer
1369 * point to the temporary glyph storage.
1371 if (set == f->glyphs_used)
1374 if (res == GF_char_loc) {
1376 * Get both horizontal and vertical escapement, only keeping
1377 * the horizontal for the device width.
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);
1391 * Skip the TFM width and the glyph file offset.
1396 * Call the callback if indicated.
1398 if (callback != 0) {
1399 cb.reason = BDF_LOADING;
1400 cb.total = st.st_size;
1401 cb.current = ftell(in);
1402 (*callback)(&cb, data);
1407 * Now add the properties to the font.
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);
1415 * Calculate and add the pixel size.
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);
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);
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);
1434 prop.name = "FONT_ASCENT";
1435 prop.format = BDF_INTEGER;
1436 prop.value.int32 = f->font_ascent;
1437 bdf_add_font_property(f, &prop);
1439 prop.name = "FONT_DESCENT";
1440 prop.format = BDF_INTEGER;
1441 prop.value.int32 = f->font_descent;
1442 bdf_add_font_property(f, &prop);
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);
1450 * Default all PK fonts to proportional spacing.
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;
1460 bdf_add_font_property(f, &prop);
1463 * Call the callback one last time if necessary.
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);
1472 * Add a message indicating the font was converted.
1474 _bdf_add_comment(f, "Font converted from GF to BDF.", 30);
1475 _bdf_add_acmsg(f, "Font converted from GF to BDF.", 30);
1481 bdf_load_mf_font(FILE *in, bdf_options_t *opts, bdf_callback_t callback,
1482 void *data, bdf_font_t **font)
1484 unsigned char mfmag[2];
1487 * Load the header to see if this is a GF or PK font.
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);