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