Python 2.6 compat - (Thanks to Petr Uzel <petr.uzel@suse.cz>)
[mftrace.git] / gf2pbm.c
blobfa31ea0d9c11bca37528b2c7202cf882e26d3c9b
1 /* -*-c-indentation-style:"bsd"-*- */
2 /*========================================================================*\
4 Copyright (c) 1990-1999 Paul Vojta
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to
8 deal in the Software without restriction, including without limitation the
9 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 sell copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 PAUL VOJTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 \*========================================================================*/
26 * GF font reading routines.
27 * Public routines are read_GF_index and read_GF_char.
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h> /* getopt. */
34 #include <strings.h>
36 #include "config.h"
38 #define ARGS(x) x
40 #define DBG_PK 0
42 #define WIDENINT (int)
43 typedef unsigned int wide_ubyte;
44 typedef int wide_bool;
45 typedef unsigned long Pixel;
46 typedef unsigned int Dimension;
49 #define one(fp) ((unsigned char) getc(fp))
50 #define sone(fp) ((long) one(fp))
51 #define two(fp) num (fp, 2)
52 #define stwo(fp) snum(fp, 2)
53 #define four(fp) num (fp, 4)
54 #define sfour(fp) snum(fp, 4)
55 typedef unsigned char ubyte;
57 struct font;
58 typedef void (*read_char_proc) ARGS((struct font *, wide_ubyte));
59 typedef long (*set_char_proc) ARGS((wide_ubyte));
61 #define BMTYPE int
62 #define GF_PRE 247
63 #define GF_ID 131
64 #define GF_MAGIC (GF_PRE << 8) + GF_ID
66 #define BMUNIT unsigned BMTYPE
69 (can't use sizeof.
71 #define BMBYTES 4
72 #define BMBITS (8 * BMBYTES)
73 extern BMUNIT bit_masks[BMBITS + 1];
74 #define ADD(a, b) ((BMUNIT *) (((char *) a) + b))
75 #define SUB(a, b) ((BMUNIT *) (((char *) a) - b))
79 #if (BMBYTES == 1)
80 BMUNIT bit_masks[9] = {
81 0x0, 0x1, 0x3, 0x7,
82 0xf, 0x1f, 0x3f, 0x7f,
83 0xff
85 #else
86 #if (BMBYTES == 2)
87 BMUNIT bit_masks[17] = {
88 0x0, 0x1, 0x3, 0x7,
89 0xf, 0x1f, 0x3f, 0x7f,
90 0xff, 0x1ff, 0x3ff, 0x7ff,
91 0xfff, 0x1fff, 0x3fff, 0x7fff,
92 0xffff
94 #else /* BMBYTES == 4 */
95 BMUNIT bit_masks[33] = {
96 0x0, 0x1, 0x3, 0x7,
97 0xf, 0x1f, 0x3f, 0x7f,
98 0xff, 0x1ff, 0x3ff, 0x7ff,
99 0xfff, 0x1fff, 0x3fff, 0x7fff,
100 0xffff, 0x1ffff, 0x3ffff, 0x7ffff,
101 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
102 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
103 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
104 0xffffffff
106 #endif
107 #endif
109 typedef enum {false,true}bool;
110 bool debug;
112 struct font {
113 char *fontname; /* name of font */
114 float fsize; /* size information (dots per inch) */
115 int magstepval; /* magstep number * two, or NOMAGSTP */
116 FILE *file; /* open font file or NULL */
117 char *filename; /* name of font file */
118 long checksum; /* checksum */
119 unsigned short timestamp; /* for LRU management of fonts */
120 ubyte flags; /* flags byte (see values below) */
121 ubyte maxchar; /* largest character code */
122 double dimconv; /* size conversion factor */
123 /* these fields are used by (loaded) raster fonts */
124 read_char_proc read_char; /* function to read bitmap */
125 struct glyph *glyph;
126 /* these fields are used by (loaded) virtual fonts */
127 struct font **vf_table; /* list of fonts used by this vf */
128 struct tn *vf_chain; /* ditto, if TeXnumber >= VFTABLELEN */
129 struct font *first_font; /* first font defined */
130 struct macro *macro;
131 /* I suppose the above could be put into a union, but we */
132 /* wouldn't save all that much space. */
138 * Bitmap structure for raster ops.
140 struct bitmap {
141 unsigned short w, h; /* width and height in pixels */
142 short bytes_wide; /* scan-line width in bytes */
143 char *bits; /* pointer to the bits */
147 * Per-character information.
148 * There is one of these for each character in a font (raster fonts only).
149 * All fields are filled in at font definition time,
150 * except for the bitmap, which is "faulted in"
151 * when the character is first referenced.
153 struct glyph {
154 long addr; /* address of bitmap in font file */
155 long dvi_adv; /* DVI units to move reference point */
156 short x, y; /* x and y offset in pixels */
157 struct bitmap bitmap; /* bitmap for character */
158 short x2, y2; /* x and y offset in pixels (shrunken bitmap) */
159 #ifdef GREY
160 XImage *image2;
161 char *pixmap2;
162 char *pixmap2_t;
163 #endif
164 struct bitmap bitmap2; /* shrunken bitmap for character */
167 #define PAINT_0 0
168 #define PAINT1 64
169 #define PAINT2 65
170 #define PAINT3 66
171 #define BOC 67
172 #define BOC1 68
173 #define EOC 69
174 #define SKIP0 70
175 #define SKIP1 71
176 #define SKIP2 72
177 #define SKIP3 73
178 #define NEW_ROW_0 74
179 #define NEW_ROW_MAX 238
180 #define XXX1 239
181 #define XXX2 240
182 #define XXX3 241
183 #define XXX4 242
184 #define YYY 243
185 #define NO_OP 244
186 #define CHAR_LOC 245
187 #define CHAR_LOC0 246
188 #define PRE 247
189 #define POST 248
190 #define POST_POST 249
192 #define GF_ID_BYTE 131
193 #define TRAILER 223 /* Trailing bytes at end of file */
195 static FILE *GF_file;
198 static void
199 expect( ubyte ch)
201 ubyte ch1 = one(GF_file);
203 if (ch1 != ch)
205 fprintf(stderr, "Bad GF file: %d expected, %d received.", ch, ch1);
206 exit (2);
210 static void
211 too_many_bits( ubyte ch)
213 fprintf(stderr,"Too many bits found when loading character %d", ch);
214 exit (2);
220 * Read size bytes from the FILE fp, constructing them into a
221 * signed/unsigned integer.
225 unsigned long
226 num( FILE *fp, int size)
228 long x = 0;
230 while (size--) x = (x << 8) | one(fp);
231 return x;
234 long
235 snum( FILE *fp, int size)
237 long x;
239 x = (signed char) getc(fp);
241 while (--size) x = (x << 8) | one(fp);
242 return x;
245 ubyte maxchar;
247 void
248 realloc_font(struct font *fontp, wide_ubyte newsize)
250 struct glyph *glyphp;
252 glyphp = fontp->glyph = (struct glyph*)realloc(fontp->glyph,
253 (unsigned int) (newsize + 1) * sizeof(struct glyph));
254 if (newsize > fontp->maxchar)
255 bzero((char *) (glyphp + fontp->maxchar + 1),
256 (int) (newsize - fontp->maxchar) * sizeof(struct glyph));
257 maxchar = fontp->maxchar = newsize;
260 #define ROUNDUP(x,y) (((x)+(y)-1)/(y))
261 void *
262 xmalloc( unsigned size)
264 void *mem = malloc(size);
266 if (mem == NULL)
268 fprintf(stderr,"! Out of memory (allocating %u bytes).\n", size);
269 exit (2);
271 return mem;
274 void
275 alloc_bitmap( struct bitmap *bitmap)
277 unsigned int size;
279 /* width must be multiple of 16 bits for raster_op */
280 bitmap->bytes_wide = ROUNDUP((int) bitmap->w, BMBITS) * BMBYTES;
281 size = bitmap->bytes_wide * bitmap->h;
282 bitmap->bits = (char*)xmalloc(size != 0 ? size : 1);
286 * Public routines
290 #ifndef WORDS_BIGENDIAN
291 #define word_swap(x) x
292 #else
293 #define word_swap(x) \
294 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
295 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
296 #endif
298 static void
299 read_GF_char(struct font *fontp, wide_ubyte ch)
301 struct glyph *g;
302 ubyte cmnd;
303 int min_m, max_m, min_n, max_n;
304 BMUNIT *cp, *basep, *maxp;
305 BMUNIT **basep_cpp = &basep;
306 int bytes_wide;
307 bool paint_switch;
308 #define White false
309 #define Black true
310 bool new_row;
311 int count;
312 int word_weight;
314 g = &fontp->glyph[ch];
315 GF_file = fontp->file;
317 if(debug & DBG_PK)
318 printf("Loading gf char %d", ch);
320 for (;;) {
321 switch (cmnd = one(GF_file)) {
322 case XXX1:
323 case XXX2:
324 case XXX3:
325 case XXX4:
326 fseek(GF_file, (long) num(GF_file,
327 WIDENINT cmnd - XXX1 + 1), 1);
328 continue;
329 case YYY:
330 (void) four(GF_file);
331 continue;
332 case BOC:
333 (void) four(GF_file); /* skip character code */
334 (void) four(GF_file); /* skip pointer to prev char */
335 min_m = sfour(GF_file);
336 max_m = sfour(GF_file);
337 g->x = -min_m;
338 min_n = sfour(GF_file);
339 g->y = max_n = sfour(GF_file);
340 g->bitmap.w = max_m - min_m + 1;
341 g->bitmap.h = max_n - min_n + 1;
342 break;
343 case BOC1:
344 (void) one(GF_file); /* skip character code */
345 g->bitmap.w = one(GF_file); /* max_m - min_m */
346 g->x = g->bitmap.w - one(GF_file); /* ditto - max_m */
347 ++g->bitmap.w;
348 g->bitmap.h = one(GF_file) + 1;
349 g->y = one(GF_file);
350 break;
351 default:
352 fprintf(stderr,"Bad BOC code: %d", cmnd);
354 break;
356 paint_switch = White;
358 if (debug)
359 printf(", size=%dlx%d, dvi_adv=%ld\n", g->bitmap.w, g->bitmap.h,
360 g->dvi_adv);
362 alloc_bitmap(&g->bitmap);
363 cp = basep = (BMUNIT *) g->bitmap.bits;
365 * Read character data into *basep
367 bytes_wide = ROUNDUP((int) g->bitmap.w, BMBITS) * BMBYTES;
368 maxp = ADD(basep, g->bitmap.h * bytes_wide);
369 bzero(g->bitmap.bits, g->bitmap.h * bytes_wide);
370 new_row = false;
371 word_weight = BMBITS;
372 for (;;) {
373 count = -1;
374 cmnd = one(GF_file);
375 if (cmnd < 64) count = cmnd;
376 else if (cmnd >= NEW_ROW_0 && cmnd <= NEW_ROW_MAX) {
377 count = cmnd - NEW_ROW_0;
378 paint_switch = White; /* it'll be complemented later */
379 new_row = true;
381 else switch (cmnd) {
382 case PAINT1:
383 case PAINT2:
384 case PAINT3:
385 count = num(GF_file, WIDENINT cmnd - PAINT1 + 1);
386 break;
387 case EOC:
388 if (cp >= ADD(basep, bytes_wide)) too_many_bits(ch);
389 return;
390 case SKIP1:
391 case SKIP2:
392 case SKIP3:
393 *(basep_cpp) +=
394 num(GF_file, WIDENINT cmnd - SKIP0) * bytes_wide / sizeof (BMUNIT);
395 case SKIP0:
396 new_row = true;
397 paint_switch = White;
398 break;
399 case XXX1:
400 case XXX2:
401 case XXX3:
402 case XXX4:
403 fseek(GF_file, (long) num(GF_file,
404 WIDENINT cmnd - XXX1 + 1), 1);
405 break;
406 case YYY:
407 (void) four(GF_file);
408 break;
409 case NO_OP:
410 break;
411 default:
412 fprintf(stderr, "Bad command in GF file: %d", cmnd);
413 } /* end switch */
414 if (new_row) {
416 *(basep_cpp) +=
417 bytes_wide / sizeof (BMUNIT);
418 if (basep >= maxp || cp >= basep) too_many_bits(ch);
419 cp = basep;
420 word_weight = BMBITS;
421 new_row = false;
423 if (count >= 0) {
424 while (count)
425 if (count <= word_weight) {
426 if (paint_switch) {
427 *cp = word_swap (*cp);
428 *cp |= bit_masks[count] << (BMBITS - word_weight);
429 *cp = word_swap (*cp);
431 word_weight -= count;
432 break;
434 else {
435 if (paint_switch) {
436 *cp = word_swap (*cp);
437 *cp |= bit_masks[word_weight] <<
438 (BMBITS - word_weight);
439 *cp = word_swap (*cp);
441 cp++;
442 count -= word_weight;
443 word_weight = BMBITS;
445 paint_switch = ! paint_switch;
447 } /* end for */
451 void
452 read_GF_index( struct font *fontp, wide_bool hushcs)
454 int hppp, vppp;
455 ubyte ch, cmnd;
456 struct glyph *g;
457 long checksum;
459 fontp->read_char = read_GF_char;
460 GF_file = fontp->file;
461 if (debug)
462 printf("Reading GF pixel file %s\n", fontp->filename);
464 * Find postamble.
466 fseek(GF_file, (long) -4, 2);
467 while (four(GF_file) != ((unsigned long) TRAILER << 24 | TRAILER << 16
468 | TRAILER << 8 | TRAILER))
469 fseek(GF_file, (long) -5, 1);
470 fseek(GF_file, (long) -5, 1);
471 for (;;) {
472 ch = one(GF_file);
473 if (ch != TRAILER) break;
474 fseek(GF_file, (long) -2, 1);
476 if (ch != GF_ID_BYTE)
477 fprintf(stderr, "Bad end of font file %s", fontp->fontname);
478 fseek(GF_file, (long) -6, 1);
479 expect(POST_POST);
480 fseek(GF_file, sfour(GF_file), 0); /* move to postamble */
482 * Read postamble.
484 expect(POST);
485 (void) four(GF_file); /* pointer to last eoc + 1 */
486 (void) four(GF_file); /* skip design size */
487 checksum = four(GF_file);
488 if (checksum != fontp->checksum && checksum != 0 && fontp->checksum != 0
489 && !hushcs)
490 fprintf(stderr,
491 "Checksum mismatch (dvi = %lu, gf = %lu) in font file %s\n",
492 fontp->checksum, checksum, fontp->filename);
493 hppp = sfour(GF_file);
494 vppp = sfour(GF_file);
495 if (hppp != vppp && (debug))
496 printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
497 (void) four(GF_file); /* skip min_m */
498 (void) four(GF_file); /* skip max_m */
499 (void) four(GF_file); /* skip min_n */
500 (void) four(GF_file); /* skip max_n */
502 * Prepare glyph array.
504 fontp->glyph = (struct glyph*)xmalloc(256 * sizeof(struct glyph));
505 bzero((char *) fontp->glyph, 256 * sizeof(struct glyph));
507 * Read glyph directory.
509 while ((cmnd = one(GF_file)) != POST_POST) {
510 int addr;
512 ch = one(GF_file); /* character code */
513 g = &fontp->glyph[ch];
514 switch (cmnd) {
515 case CHAR_LOC:
516 /* g->pxl_adv = sfour(GF_file); */
517 (void) four(GF_file);
518 (void) four(GF_file); /* skip dy */
519 break;
520 case CHAR_LOC0:
521 /* g->pxl_adv = one(GF_file) << 16; */
522 (void) one(GF_file);
523 break;
524 default:
525 fprintf(stderr, "Non-char_loc command found in GF preamble: %d",
526 cmnd);
528 g->dvi_adv = (long int) fontp->dimconv * sfour(GF_file);
529 addr = four(GF_file);
530 if (addr != -1) g->addr = addr;
531 if (debug)
532 printf("Read GF glyph for character %d; dy = %ld, addr = %d\n",
533 ch, g->dvi_adv, addr);
538 void
539 help ()
541 printf (
542 "gf2pbm [options] FONT-NAME\n"
543 "Options: \n"
544 " -b dump bitmap\n"
545 " -d debug\n"
546 " -n NUM do glyph number NUM\n"
547 " -o FILE output to FILE\n"
548 " -h this help\n"
549 " -s print bitmap size\n"
550 "\n"
551 "Return status:\n"
552 " 0 - success\n"
553 " 1 - no such glyph\n"
554 " 2 - error\n"
555 "Based on Paul Vojta's Xdvi, munged by Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
559 void
560 dump_bitmap (FILE *out, struct bitmap *bm)
562 int bs = (bm->w) / 8 + ((bm->w % 8) ? 1 : 0);
563 int h =0;
564 fprintf (out, "P4\n");
565 fprintf (out, "%d %d\n", bm->w, bm->h);
567 for (h = 0 ; h < bm->h; h++)
569 int c;
570 for (c = 0 ; c < bs; c++)
572 ubyte todump = bm->bits[h *bm->bytes_wide + c];
573 ubyte outb = 0;
574 int i = 8;
575 while (i --)
577 outb = (outb << 1) | (todump & 0x1);
578 todump = todump >> 1;
580 fputc(outb, out);
586 main (int argc, char * argv [])
588 int print_size = 0;
589 int do_bitmap = 0;
590 FILE * in_file= 0;
591 struct font * fontp;
593 int glyph_num = 65;
594 char *filename =NULL;
595 char * outfilename = NULL;
596 int c;
597 while ((c = getopt (argc, argv, "bsdho:n:")) != -1)
599 switch (c)
601 case 'b':
602 do_bitmap = true;
603 break;
605 case 'd':
606 debug = true;
607 break;
608 case 'h':
609 help ();
610 exit (0);
611 break;
612 case 'n':
613 sscanf (optarg, "%d", &glyph_num);
614 break;
615 case 's':
616 print_size = true;
617 break;
618 case 'o':
619 outfilename = optarg;
620 break;
625 if (!do_bitmap && !print_size)
626 do_bitmap = true;
628 filename = argv[optind];
630 if (!filename)
632 fprintf (stderr, "No font-name found. Use -h for help\n");
633 exit (2);
636 in_file = fopen (filename, "r");
637 if (!in_file)
639 fprintf (stderr, "could not open `%s'\n", filename);
640 exit (2);
643 fontp = (struct font*)malloc (sizeof (struct font));
644 bzero (fontp, sizeof (struct font));
646 fontp->fontname = filename;
647 fontp->file = in_file;
648 fontp->fsize = 0;
649 fontp->timestamp = 0;
650 fontp->maxchar = 255;
651 maxchar = 255;
655 int magic = two(fontp->file);
656 if(magic != GF_MAGIC)
658 fprintf (stderr, "Not a GF file\n");
659 exit (2);
663 read_GF_index (fontp, false);
664 while (maxchar > 0 && fontp->glyph[maxchar].addr == 0) --maxchar;
665 if (maxchar < 255)
666 realloc_font(fontp, WIDENINT maxchar);
668 if (fontp->glyph[glyph_num].addr == 0)
670 fprintf (stderr, "No glyph number %d\n", glyph_num);
671 return 1;
674 fseek(fontp->file, fontp->glyph[glyph_num].addr, 0);
676 read_GF_char (fontp, glyph_num);
678 if (print_size)
680 struct glyph* gp = fontp->glyph + glyph_num;
681 fprintf (stdout, "size: %dx%d, offset: (%d,%d)\n",
682 gp->bitmap.w, gp->bitmap.h,
683 gp->x, gp->y);
687 if (do_bitmap)
689 FILE * out_file = 0;
690 if (outfilename && !strcmp ("-", outfilename))
691 out_file = stdout;
693 out_file = outfilename ? fopen (outfilename, "w") : NULL;
694 if(!out_file)
696 static char s[100];
697 sprintf (s, "%d.pbm", glyph_num);
698 outfilename = s;
699 out_file = fopen (s, "w");
702 if (!out_file)
704 fprintf (stderr, "Could not open output file `%s'\n", outfilename);
705 exit (2);
708 dump_bitmap (out_file, &fontp->glyph[glyph_num].bitmap);
709 fclose (out_file);
711 return 0;