1 /*========================================================================*\
2 
3 Copyright (c) 1990-2004  Paul Vojta
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to
7 deal in the Software without restriction, including without limitation the
8 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 sell copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
19 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
22 
23 \*========================================================================*/
24 
25 /*
26  *	GF font reading routines.
27  *	Public routines are read_GF_index and read_GF_char.
28  */
29 
30 #include "xdvi-config.h"
31 #include "xdvi.h"
32 #include "dvi-init.h"
33 #include "util.h"
34 
35 #define	PAINT_0		0
36 #define	PAINT1		64
37 #define	PAINT2		65
38 #define	PAINT3		66
39 #define	BOC		67
40 #define	BOC1		68
41 #define	EOC		69
42 #define	SKIP0		70
43 #define	SKIP1		71
44 #define	SKIP2		72
45 #define	SKIP3		73
46 #define	NEW_ROW_0	74
47 #define	NEW_ROW_MAX	238
48 #define	XXX1		239
49 #define	XXX2		240
50 #define	XXX3		241
51 #define	XXX4		242
52 #define	YYY		243
53 #define	NO_OP		244
54 #define	CHAR_LOC	245
55 #define	CHAR_LOC0	246
56 #define	PRE		247
57 #define	POST		248
58 #define	POST_POST	249
59 
60 #define	GF_ID_BYTE	131
61 #define	TRAILER		223	/* Trailing bytes at end of file */
62 
63 static FILE *GF_file;
64 
65 static void
expect(ubyte ch)66 expect(ubyte ch)
67 {
68     ubyte ch1 = get_byte(GF_file);
69 
70     if (ch1 != ch)
71 	XDVI_FATAL((stderr, "Bad GF file:  %d expected, %d received.", ch, ch1));
72 }
73 
74 static void
too_many_bits(ubyte ch)75 too_many_bits(ubyte ch)
76 {
77     XDVI_FATAL((stderr, "Too many bits found when loading character %d", ch));
78 }
79 
80 /*
81  *	Public routines
82  */
83 
84 
85 static void
read_GF_char(struct font * fontp,wide_ubyte ch)86 read_GF_char(struct font *fontp,
87 	     wide_ubyte ch)
88 {
89     struct glyph *g;
90     ubyte cmnd;
91     int min_m, max_m, min_n, max_n;
92     bmUnitT *cp, *basep, *maxp;
93     int bytes_wide;
94     Boolean paint_switch;
95 #define	White	False
96 #define	Black	True
97     Boolean new_row;
98     int count;
99     int word_weight;
100 
101     g = &fontp->glyph[ch];
102     GF_file = fontp->file;
103 
104     if (globals.debug & DBG_PK)
105 	printf("Loading gf char %d", ch);
106 
107     for (;;) {
108 	switch (cmnd = get_byte(GF_file)) {
109 	case XXX1:
110 	case XXX2:
111 	case XXX3:
112 	case XXX4:
113 	    fseek(GF_file, (long)get_bytes(GF_file, (int)(cmnd - XXX1 + 1)), SEEK_CUR);
114 	    continue;
115 	case YYY:
116 	    (void)get_bytes(GF_file, 4);
117 	    continue;
118 	case BOC:
119 	    (void)get_bytes(GF_file, 4);	/* skip character code */
120 	    (void)get_bytes(GF_file, 4);	/* skip pointer to prev char */
121 	    min_m = get_lbytes(GF_file, 4);
122 	    max_m = get_lbytes(GF_file, 4);
123 	    g->x = -min_m;
124 	    min_n = get_lbytes(GF_file, 4);
125 	    g->y = max_n = get_lbytes(GF_file, 4);
126 	    g->bitmap.w = max_m - min_m + 1;
127 	    g->bitmap.h = max_n - min_n + 1;
128 	    break;
129 	case BOC1:
130 	    (void)get_byte(GF_file);	/* skip character code */
131 	    g->bitmap.w = get_byte(GF_file);	/* max_m - min_m */
132 	    g->x = g->bitmap.w - get_byte(GF_file);	/* ditto - max_m */
133 	    ++g->bitmap.w;
134 	    g->bitmap.h = get_byte(GF_file) + 1;
135 	    g->y = get_byte(GF_file);
136 	    break;
137 	default:
138 	    XDVI_FATAL((stderr, "Bad BOC code:  %d", cmnd));
139 	}
140 	break;
141     }
142     paint_switch = White;
143 
144     if (globals.debug & DBG_PK)
145 	printf(", size=%dx%d, dvi_adv=%ld\n", g->bitmap.w, g->bitmap.h,
146 	       g->dvi_adv);
147 
148     alloc_bitmap(&g->bitmap);
149     cp = basep = (bmUnitT *) g->bitmap.bits;
150     /*
151      *	Read character data into *basep
152      */
153     bytes_wide = ROUNDUP((int)g->bitmap.w, BMBITS) * BMBYTES;
154     maxp = ADD(basep, g->bitmap.h * bytes_wide);
155     memset(g->bitmap.bits, 0, g->bitmap.h * bytes_wide);
156     new_row = False;
157     word_weight = BMBITS;
158     for (;;) {
159 	count = -1;
160 	cmnd = get_byte(GF_file);
161 	if (cmnd < 64)
162 	    count = cmnd;
163 	else if (cmnd >= NEW_ROW_0 && cmnd <= NEW_ROW_MAX) {
164 	    count = cmnd - NEW_ROW_0;
165 	    paint_switch = White;	/* it'll be complemented later */
166 	    new_row = True;
167 	}
168 	else
169 	    switch (cmnd) {
170 	    case PAINT1:
171 	    case PAINT2:
172 	    case PAINT3:
173 		count = get_bytes(GF_file, (int)(cmnd - PAINT1 + 1));
174 		break;
175 	    case EOC:
176 		if (cp >= ADD(basep, bytes_wide))
177 		    too_many_bits(ch);
178 		return;
179 	    case SKIP1:
180 	    case SKIP2:
181 	    case SKIP3:
182 		basep += get_bytes(GF_file, (int)(cmnd - SKIP0)) * bytes_wide / sizeof(bmUnitT);
183 		/* 		*((char **)&basep) += get_bytes(GF_file, WIDENINT cmnd - SKIP0) * bytes_wide; */
184 	    case SKIP0:
185 		new_row = True;
186 		paint_switch = White;
187 		break;
188 	    case XXX1:
189 	    case XXX2:
190 	    case XXX3:
191 	    case XXX4:
192 		fseek(GF_file, (long)get_bytes(GF_file, (int)(cmnd - XXX1 + 1)), SEEK_CUR);
193 		break;
194 	    case YYY:
195 		(void)get_bytes(GF_file, 4);
196 		break;
197 	    case NO_OP:
198 		break;
199 	    default:
200 		XDVI_FATAL((stderr, "Bad command in GF file:  %d", cmnd));
201 	    }	/* end switch */
202 	if (new_row) {
203 	    basep += bytes_wide / sizeof(bmUnitT);
204 	    /* 	    *((char **)&basep) += bytes_wide; */
205 	    if (basep >= maxp || cp >= basep)
206 		too_many_bits(ch);
207 	    cp = basep;
208 	    word_weight = BMBITS;
209 	    new_row = False;
210 	}
211 	if (count >= 0) {
212 	    while (count)
213 		if (count <= word_weight) {
214 #ifndef	WORDS_BIGENDIAN
215 		    if (paint_switch)
216 			*cp |= bit_masks[count] << (BMBITS - word_weight);
217 #endif
218 		    word_weight -= count;
219 #ifdef	WORDS_BIGENDIAN
220 		    if (paint_switch)
221 			*cp |= bit_masks[count] << word_weight;
222 #endif
223 		    break;
224 		}
225 		else {
226 		    if (paint_switch)
227 #ifndef	WORDS_BIGENDIAN
228 			*cp |= bit_masks[word_weight] << (BMBITS - word_weight);
229 #else
230 		    *cp |= bit_masks[word_weight];
231 #endif
232 		    cp++;
233 		    count -= word_weight;
234 		    word_weight = BMBITS;
235 		}
236 	    paint_switch = 1 - paint_switch;
237 	}
238     }	/* end for */
239 }
240 
241 
242 void
read_GF_index(struct font * fontp,wide_bool hushcs)243 read_GF_index(struct font *fontp, wide_bool hushcs)
244 {
245     int hppp, vppp;
246     ubyte ch, cmnd;
247     struct glyph *g;
248     long checksum;
249 
250     fontp->read_char = read_GF_char;
251     GF_file = fontp->file;
252     if (globals.debug & DBG_PK)
253 	printf("Reading GF pixel file %s\n", fontp->filename);
254     /*
255      *	Find postamble.
256      */
257     fseek(GF_file, (long)-4, SEEK_END);
258     while (get_bytes(GF_file, 4) != ((unsigned long)TRAILER << 24 | TRAILER << 16
259 				     | TRAILER << 8 | TRAILER))
260 	fseek(GF_file, (long)-5, SEEK_CUR);
261     fseek(GF_file, (long)-5, SEEK_CUR);
262     for (;;) {
263 	ch = get_byte(GF_file);
264 	if (ch != TRAILER)
265 	    break;
266 	fseek(GF_file, (long)-2, SEEK_CUR);
267     }
268     if (ch != GF_ID_BYTE)
269 	XDVI_FATAL((stderr, "Bad end of font file %s", fontp->fontname));
270     fseek(GF_file, (long)-6, SEEK_CUR);
271     expect(POST_POST);
272     fseek(GF_file, get_lbytes(GF_file, 4), SEEK_SET);	/* move to postamble */
273     /*
274      *	Read postamble.
275      */
276     expect(POST);
277     (void)get_bytes(GF_file, 4);	/* pointer to last eoc + 1 */
278     (void)get_bytes(GF_file, 4);	/* skip design size */
279     checksum = get_bytes(GF_file, 4);
280     if (checksum != fontp->checksum && checksum != 0 && fontp->checksum != 0
281 	&& !hushcs)
282 	XDVI_WARNING((stderr, "Checksum mismatch (dvi = %lu, gf = %lu) in font file %s",
283 		      fontp->checksum, checksum, fontp->filename));
284     hppp = get_lbytes(GF_file, 4);
285     vppp = get_lbytes(GF_file, 4);
286     if (hppp != vppp && (globals.debug & DBG_PK))
287 	printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
288     (void)get_bytes(GF_file, 4);	/* skip min_m */
289     (void)get_bytes(GF_file, 4);	/* skip max_m */
290     (void)get_bytes(GF_file, 4);	/* skip min_n */
291     (void)get_bytes(GF_file, 4);	/* skip max_n */
292     /*
293      *	Prepare glyph array.
294      */
295     fontp->glyph = xmalloc(256 * sizeof(struct glyph));
296     memset((char *)fontp->glyph, 0, 256 * sizeof(struct glyph));
297     /*
298      *	Read glyph directory.
299      */
300     while ((cmnd = get_byte(GF_file)) != POST_POST) {
301 	int addr;
302 
303 	ch = get_byte(GF_file);	/* character code */
304 	g = &fontp->glyph[ch];
305 	switch (cmnd) {
306 	case CHAR_LOC:
307 	    /* g->pxl_adv = get_lbytes(GF_file, 4); */
308 	    (void)get_bytes(GF_file, 4);
309 	    (void)get_bytes(GF_file, 4);	/* skip dy */
310 	    break;
311 	case CHAR_LOC0:
312 	    /* g->pxl_adv = get_byte(GF_file) << 16; */
313 	    (void)get_byte(GF_file);
314 	    break;
315 	default:
316 	    XDVI_FATAL((stderr, "Non-char_loc command found in GF preamble:  %d", cmnd));
317 	}
318 	g->dvi_adv = fontp->dimconv * get_lbytes(GF_file, 4);
319 	addr = get_bytes(GF_file, 4);
320 	if (addr != -1)
321 	    g->addr = addr;
322 	if (globals.debug & DBG_PK)
323 	    printf("Read GF glyph for character %d; dy = %ld, addr = %x\n",
324 		   ch, g->dvi_adv, addr);
325     }
326 }
327