pk.c (8827B)
1 /*========================================================================*\ 2 3 Copyright (c) 1990-1999 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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 NOTE: 23 xdvi is based on prior work, as noted in the modification history 24 in xdvi.c. 25 26 \*========================================================================*/ 27 28 /* 29 * PK font reading routines. 30 * Public routines are read_PK_index and read_PK_char. 31 */ 32 33 #include <err.h> 34 35 #include "font.h" /* struct font, struct glyph */ 36 #include "xdvi.h" 37 #include "util.h" /* xmalloc() */ 38 39 #define PK_ID 89 40 #define PK_CMD_START 240 41 #define PK_X1 240 42 #define PK_X2 241 43 #define PK_X3 242 44 #define PK_X4 243 45 #define PK_Y 244 46 #define PK_POST 245 47 #define PK_NOOP 246 48 #define PK_PRE 247 49 50 static int PK_flag_byte; 51 static unsigned PK_input_byte; 52 static int PK_bitpos; 53 static int PK_dyn_f; 54 static int PK_repeat_count; 55 56 static int 57 PK_get_nyb(FILE *fp) 58 { 59 unsigned temp; 60 if (PK_bitpos < 0) { 61 PK_input_byte = one(fp); 62 PK_bitpos = 4; 63 } 64 temp = PK_input_byte >> PK_bitpos; 65 PK_bitpos -= 4; 66 return (temp & 0xf); 67 } 68 69 70 static int 71 PK_packed_num(FILE *fp) 72 { 73 int i,j; 74 75 if ((i = PK_get_nyb(fp)) == 0) { 76 do { 77 j = PK_get_nyb(fp); 78 ++i; 79 } 80 while (j == 0); 81 while (i > 0) { 82 j = (j << 4) | PK_get_nyb(fp); 83 --i; 84 } 85 return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f); 86 } 87 else { 88 if (i <= PK_dyn_f) return i; 89 if (i < 14) 90 return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp) 91 + PK_dyn_f + 1); 92 if (i == 14) PK_repeat_count = PK_packed_num(fp); 93 else PK_repeat_count = 1; 94 return PK_packed_num(fp); 95 } 96 } 97 98 99 static void 100 PK_skip_specials(struct font *fontp) 101 { 102 int i, j; 103 FILE *fp = fontp->file; 104 105 do { 106 PK_flag_byte = one(fp); 107 if (PK_flag_byte < PK_CMD_START) 108 continue; 109 switch (PK_flag_byte) { 110 case PK_X1 : 111 case PK_X2 : 112 case PK_X3 : 113 case PK_X4 : 114 i = 0; 115 for (j = PK_CMD_START; j <= PK_flag_byte; ++j) 116 i = (i << 8) | one(fp); 117 while (i--) (void) one(fp); 118 break; 119 case PK_Y : 120 (void) four(fp); 121 break; 122 case PK_POST : 123 case PK_NOOP : 124 break; 125 default : 126 errx(1, "Unexpected %d in PK file '%s'", PK_flag_byte, 127 fontp->filename); 128 break; 129 } 130 } 131 while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START); 132 } 133 134 /* 135 * Public routines 136 */ 137 138 static void 139 read_PK_char(struct font *fontp, unsigned char ch) 140 { 141 int i, j; 142 int n; 143 int row_bit_pos; 144 Boolean paint_switch; 145 BMUNIT *cp; 146 struct glyph *g; 147 FILE *fp = fontp->file; 148 long fpwidth; 149 BMUNIT word; 150 int word_weight, bytes_wide; 151 int rows_left, h_bit, count; 152 153 g = &fontp->glyph[ch]; 154 PK_flag_byte = g->x2; 155 PK_dyn_f = PK_flag_byte >> 4; 156 paint_switch = ((PK_flag_byte & 8) != 0); 157 PK_flag_byte &= 0x7; 158 if (PK_flag_byte == 7) n = 4; 159 else if (PK_flag_byte > 3) n = 2; 160 else n = 1; 161 162 if (debug & DBG_PK) printf("loading pk char %d, char type %d ", ch, n); 163 164 /* 165 * now read rest of character preamble 166 */ 167 if (n != 4) fpwidth = num(fp, 3); 168 else { 169 fpwidth = sfour(fp); 170 (void) four(fp); /* horizontal escapement */ 171 } 172 (void) num(fp, n); /* vertical escapement */ 173 { 174 unsigned long w, h; 175 176 w = num(fp, n); 177 h = num(fp, n); 178 if (w > 0x7fff || h > 0x7fff) 179 errx(1, "Character %d too large in file '%s'", ch, fontp->fontname); 180 g->bitmap.w = w; 181 g->bitmap.h = h; 182 } 183 g->x = snum(fp, n); 184 g->y = snum(fp, n); 185 186 g->dvi_adv = fontp->dimconv * fpwidth; 187 188 if (debug & DBG_PK) { 189 if (g->bitmap.w != 0) 190 printf(", size=%dx%d, dvi_adv=%ld", g->bitmap.w, g->bitmap.h, 191 g->dvi_adv); 192 putchar('\n'); 193 } 194 195 alloc_bitmap(&g->bitmap); 196 cp = (BMUNIT *) g->bitmap.bits; 197 198 /* 199 * read character data into *cp 200 */ 201 bytes_wide = ROUNDUP((int) g->bitmap.w, BMBITS) * BMBYTES; 202 PK_bitpos = -1; 203 if (PK_dyn_f == 14) { /* get raster by bits */ 204 bzero(g->bitmap.bits, (int) g->bitmap.h * bytes_wide); 205 for (i = 0; i < (int) g->bitmap.h; i++) { /* get all rows */ 206 cp = ADD(g->bitmap.bits, i * bytes_wide); 207 #ifndef WORDS_BIGENDIAN 208 row_bit_pos = -1; 209 #else 210 row_bit_pos = BMBITS; 211 #endif 212 for (j = 0; j < (int) g->bitmap.w; j++) { /* get one row */ 213 if (--PK_bitpos < 0) { 214 word = one(fp); 215 PK_bitpos = 7; 216 } 217 #ifndef WORDS_BIGENDIAN 218 if (++row_bit_pos >= BMBITS) { 219 cp++; 220 row_bit_pos = 0; 221 } 222 #else 223 if (--row_bit_pos < 0) { 224 cp++; 225 row_bit_pos = BMBITS - 1; 226 } 227 #endif 228 if (word & (1 << PK_bitpos)) *cp |= 1 << row_bit_pos; 229 } 230 } 231 } 232 else { /* get packed raster */ 233 rows_left = g->bitmap.h; 234 h_bit = g->bitmap.w; 235 PK_repeat_count = 0; 236 word_weight = BMBITS; 237 word = 0; 238 while (rows_left > 0) { 239 count = PK_packed_num(fp); 240 while (count > 0) { 241 if (count < word_weight && count < h_bit) { 242 #ifndef WORDS_BIGENDIAN 243 if (paint_switch) 244 word |= bit_masks[count] << (BMBITS - word_weight); 245 #endif 246 h_bit -= count; 247 word_weight -= count; 248 #ifdef WORDS_BIGENDIAN 249 if (paint_switch) 250 word |= bit_masks[count] << word_weight; 251 #endif 252 count = 0; 253 } 254 else if (count >= h_bit && h_bit <= word_weight) { 255 if (paint_switch) 256 word |= bit_masks[h_bit] << 257 #ifndef WORDS_BIGENDIAN 258 (BMBITS - word_weight); 259 #else 260 (word_weight - h_bit); 261 #endif 262 *cp++ = word; 263 /* "output" row(s) */ 264 for (i = PK_repeat_count * bytes_wide / BMBYTES; 265 i > 0; --i) { 266 *cp = *SUB(cp, bytes_wide); 267 ++cp; 268 } 269 rows_left -= PK_repeat_count + 1; 270 PK_repeat_count = 0; 271 word = 0; 272 word_weight = BMBITS; 273 count -= h_bit; 274 h_bit = g->bitmap.w; 275 } 276 else { 277 if (paint_switch) 278 #ifndef WORDS_BIGENDIAN 279 word |= bit_masks[word_weight] << 280 (BMBITS - word_weight); 281 #else 282 word |= bit_masks[word_weight]; 283 #endif 284 *cp++ = word; 285 word = 0; 286 count -= word_weight; 287 h_bit -= word_weight; 288 word_weight = BMBITS; 289 } 290 } 291 paint_switch = 1 - paint_switch; 292 } 293 if (cp != ((BMUNIT *) (g->bitmap.bits + bytes_wide * g->bitmap.h))) 294 errx(1, "Wrong number of bits stored: char. %d, font '%s'", 295 ch, fontp->fontname); 296 if (rows_left != 0 || h_bit != g->bitmap.w) 297 errx(1, "Bad pk file '%s', too many bits", fontp->fontname); 298 } 299 } 300 301 void 302 read_PK_index(struct font *fontp, Boolean hushcs) 303 { 304 int hppp, vppp; 305 long checksum; 306 307 fontp->read_char = read_PK_char; 308 if (debug & DBG_PK) 309 printf("Reading PK pixel file %s\n", fontp->filename); 310 311 fseek(fontp->file, (long) one(fontp->file), 1); /* skip comment */ 312 313 (void) four(fontp->file); /* skip design size */ 314 checksum = four(fontp->file); 315 if (checksum != fontp->checksum && checksum != 0 && fontp->checksum != 0 316 && !hushcs) 317 warnx("Checksum mismatch (dvi = %lu, pk = %lu) in font file '%s'", 318 fontp->checksum, checksum, fontp->filename); 319 hppp = sfour(fontp->file); 320 vppp = sfour(fontp->file); 321 if (hppp != vppp && (debug & DBG_PK)) 322 printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp); 323 /* 324 * Prepare glyph array. 325 */ 326 fontp->glyph = xmalloc(256 * sizeof(struct glyph)); 327 bzero((char *) fontp->glyph, 256 * sizeof(struct glyph)); 328 /* 329 * Read glyph directory (really a whole pass over the file). 330 */ 331 for (;;) { 332 int bytes_left, flag_low_bits; 333 unsigned int ch; 334 335 PK_skip_specials(fontp); 336 if (PK_flag_byte == PK_POST) break; 337 flag_low_bits = PK_flag_byte & 0x7; 338 if (flag_low_bits == 7) { 339 bytes_left = four(fontp->file); 340 ch = four(fontp->file); 341 } else if (flag_low_bits > 3) { 342 bytes_left = ((flag_low_bits - 4) << 16) + two(fontp->file); 343 ch = one(fontp->file); 344 } else { 345 bytes_left = (flag_low_bits << 8) + one(fontp->file); 346 ch = one(fontp->file); 347 } 348 fontp->glyph[ch].addr = ftell(fontp->file); 349 fontp->glyph[ch].x2 = PK_flag_byte; 350 fseek(fontp->file, (long) bytes_left, 1); 351 if (debug & DBG_PK) 352 printf("Scanning pk char %u, at %ld.\n", ch, 353 fontp->glyph[ch].addr); 354 } 355 }