wdvi

network DVI viewer
Log | Files | Refs

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 }