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.
33 #include <unistd.h> /* getopt. */
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
;
58 typedef void (*read_char_proc
) ARGS((struct font
*, wide_ubyte
));
59 typedef long (*set_char_proc
) ARGS((wide_ubyte
));
64 #define GF_MAGIC (GF_PRE << 8) + GF_ID
66 #define BMUNIT unsigned BMTYPE
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))
80 BMUNIT bit_masks
[9] = {
82 0xf, 0x1f, 0x3f, 0x7f,
87 BMUNIT bit_masks
[17] = {
89 0xf, 0x1f, 0x3f, 0x7f,
90 0xff, 0x1ff, 0x3ff, 0x7ff,
91 0xfff, 0x1fff, 0x3fff, 0x7fff,
94 #else /* BMBYTES == 4 */
95 BMUNIT bit_masks
[33] = {
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,
109 typedef enum {false,true}bool;
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 */
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 */
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.
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.
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) */
164 struct bitmap bitmap2
; /* shrunken bitmap for character */
179 #define NEW_ROW_MAX 238
187 #define CHAR_LOC0 246
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
;
201 ubyte ch1
= one(GF_file
);
205 fprintf(stderr
, "Bad GF file: %d expected, %d received.", ch
, ch1
);
211 too_many_bits( ubyte ch
)
213 fprintf(stderr
,"Too many bits found when loading character %d", ch
);
220 * Read size bytes from the FILE fp, constructing them into a
221 * signed/unsigned integer.
226 num( FILE *fp
, int size
)
230 while (size
--) x
= (x
<< 8) | one(fp
);
235 snum( FILE *fp
, int size
)
239 x
= (signed char) getc(fp
);
241 while (--size
) x
= (x
<< 8) | one(fp
);
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))
262 xmalloc( unsigned size
)
264 void *mem
= malloc(size
);
268 fprintf(stderr
,"! Out of memory (allocating %u bytes).\n", size
);
275 alloc_bitmap( struct bitmap
*bitmap
)
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);
290 #ifndef WORDS_BIGENDIAN
291 #define word_swap(x) x
293 #define word_swap(x) \
294 ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
295 (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
299 read_GF_char(struct font
*fontp
, wide_ubyte ch
)
303 int min_m
, max_m
, min_n
, max_n
;
304 BMUNIT
*cp
, *basep
, *maxp
;
305 BMUNIT
**basep_cpp
= &basep
;
314 g
= &fontp
->glyph
[ch
];
315 GF_file
= fontp
->file
;
318 printf("Loading gf char %d", ch
);
321 switch (cmnd
= one(GF_file
)) {
326 fseek(GF_file
, (long) num(GF_file
,
327 WIDENINT cmnd
- XXX1
+ 1), 1);
330 (void) four(GF_file
);
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
);
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;
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 */
348 g
->bitmap
.h
= one(GF_file
) + 1;
352 fprintf(stderr
,"Bad BOC code: %d", cmnd
);
356 paint_switch
= White
;
359 printf(", size=%dlx%d, dvi_adv=%ld\n", g
->bitmap
.w
, g
->bitmap
.h
,
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
);
371 word_weight
= BMBITS
;
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 */
385 count
= num(GF_file
, WIDENINT cmnd
- PAINT1
+ 1);
388 if (cp
>= ADD(basep
, bytes_wide
)) too_many_bits(ch
);
394 num(GF_file
, WIDENINT cmnd
- SKIP0
) * bytes_wide
/ sizeof (BMUNIT
);
397 paint_switch
= White
;
403 fseek(GF_file
, (long) num(GF_file
,
404 WIDENINT cmnd
- XXX1
+ 1), 1);
407 (void) four(GF_file
);
412 fprintf(stderr
, "Bad command in GF file: %d", cmnd
);
417 bytes_wide
/ sizeof (BMUNIT
);
418 if (basep
>= maxp
|| cp
>= basep
) too_many_bits(ch
);
420 word_weight
= BMBITS
;
425 if (count
<= word_weight
) {
427 *cp
= word_swap (*cp
);
428 *cp
|= bit_masks
[count
] << (BMBITS
- word_weight
);
429 *cp
= word_swap (*cp
);
431 word_weight
-= count
;
436 *cp
= word_swap (*cp
);
437 *cp
|= bit_masks
[word_weight
] <<
438 (BMBITS
- word_weight
);
439 *cp
= word_swap (*cp
);
442 count
-= word_weight
;
443 word_weight
= BMBITS
;
445 paint_switch
= ! paint_switch
;
452 read_GF_index( struct font
*fontp
, wide_bool hushcs
)
459 fontp
->read_char
= read_GF_char
;
460 GF_file
= fontp
->file
;
462 printf("Reading GF pixel file %s\n", fontp
->filename
);
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);
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);
480 fseek(GF_file
, sfour(GF_file
), 0); /* move to postamble */
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
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
) {
512 ch
= one(GF_file
); /* character code */
513 g
= &fontp
->glyph
[ch
];
516 /* g->pxl_adv = sfour(GF_file); */
517 (void) four(GF_file
);
518 (void) four(GF_file
); /* skip dy */
521 /* g->pxl_adv = one(GF_file) << 16; */
525 fprintf(stderr
, "Non-char_loc command found in GF preamble: %d",
528 g
->dvi_adv
= (long int) fontp
->dimconv
* sfour(GF_file
);
529 addr
= four(GF_file
);
530 if (addr
!= -1) g
->addr
= addr
;
532 printf("Read GF glyph for character %d; dy = %ld, addr = %d\n",
533 ch
, g
->dvi_adv
, addr
);
542 "gf2pbm [options] FONT-NAME\n"
546 " -n NUM do glyph number NUM\n"
547 " -o FILE output to FILE\n"
549 " -s print bitmap size\n"
553 " 1 - no such glyph\n"
555 "Based on Paul Vojta's Xdvi, munged by Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
560 dump_bitmap (FILE *out
, struct bitmap
*bm
)
562 int bs
= (bm
->w
) / 8 + ((bm
->w
% 8) ? 1 : 0);
564 fprintf (out
, "P4\n");
565 fprintf (out
, "%d %d\n", bm
->w
, bm
->h
);
567 for (h
= 0 ; h
< bm
->h
; h
++)
570 for (c
= 0 ; c
< bs
; c
++)
572 ubyte todump
= bm
->bits
[h
*bm
->bytes_wide
+ c
];
577 outb
= (outb
<< 1) | (todump
& 0x1);
578 todump
= todump
>> 1;
586 main (int argc
, char * argv
[])
594 char *filename
=NULL
;
595 char * outfilename
= NULL
;
597 while ((c
= getopt (argc
, argv
, "bsdho:n:")) != -1)
613 sscanf (optarg
, "%d", &glyph_num
);
619 outfilename
= optarg
;
625 if (!do_bitmap
&& !print_size
)
628 filename
= argv
[optind
];
632 fprintf (stderr
, "No font-name found. Use -h for help\n");
636 in_file
= fopen (filename
, "r");
639 fprintf (stderr
, "could not open `%s'\n", filename
);
643 fontp
= (struct font
*)malloc (sizeof (struct font
));
644 bzero (fontp
, sizeof (struct font
));
646 fontp
->fontname
= filename
;
647 fontp
->file
= in_file
;
649 fontp
->timestamp
= 0;
650 fontp
->maxchar
= 255;
655 int magic
= two(fontp
->file
);
656 if(magic
!= GF_MAGIC
)
658 fprintf (stderr
, "Not a GF file\n");
663 read_GF_index (fontp
, false);
664 while (maxchar
> 0 && fontp
->glyph
[maxchar
].addr
== 0) --maxchar
;
666 realloc_font(fontp
, WIDENINT maxchar
);
668 if (fontp
->glyph
[glyph_num
].addr
== 0)
670 fprintf (stderr
, "No glyph number %d\n", glyph_num
);
674 fseek(fontp
->file
, fontp
->glyph
[glyph_num
].addr
, 0);
676 read_GF_char (fontp
, glyph_num
);
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
,
690 if (outfilename
&& !strcmp ("-", outfilename
))
693 out_file
= outfilename
? fopen (outfilename
, "w") : NULL
;
697 sprintf (s
, "%d.pbm", glyph_num
);
699 out_file
= fopen (s
, "w");
704 fprintf (stderr
, "Could not open output file `%s'\n", outfilename
);
708 dump_bitmap (out_file
, &fontp
->glyph
[glyph_num
].bitmap
);