diff options
Diffstat (limited to 'dviware/beebe/src/charpk.h')
-rw-r--r-- | dviware/beebe/src/charpk.h | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/dviware/beebe/src/charpk.h b/dviware/beebe/src/charpk.h new file mode 100644 index 0000000000..21a35f5aed --- /dev/null +++ b/dviware/beebe/src/charpk.h @@ -0,0 +1,344 @@ +/* -*-C-*- charpk.h */ +/*-->charpk*/ +/**********************************************************************/ +/******************************* charpk *******************************/ +/**********************************************************************/ + +/* This file departs from all others in the DVIxxx family in that it +declares some private functions and globals which are required nowhere +else. Only charpk() is called from outside. */ + +BYTE get_bit(); /* return next bit from file */ +BYTE get_nybble(); /* return next 4-bit nybble from file */ +UNSIGN16 pk_packed_num(); /* get packed number from file */ + +BYTE bit_weight; /* weight of current bit in next_byte */ +BYTE dyn_f; /* dynamic packing flag */ +UNSIGN16 repeat_count; /* how many times to repeat next row */ +BYTE next_byte; /* current input byte */ +BYTE word_weight; /* weight of current bit in *pword */ + +/**********************************************************************/ + +int +charpk(c,outfcn) /* return 0 on success, and EOF on failure */ +BYTE c; /* current character value */ +void (*outfcn)(); /* (possibly NULL) function to output current row */ +{ + INT16 count; /* how many bits of current color left */ + UNSIGN16 c_width; /* character width in dots */ + UNSIGN16 c_height; /* character height in dots */ + BOOLEAN do_output; /* FALSE if outfcn is NULL */ + register BYTE flag_byte; /* current file flag byte */ + UNSIGN16 h_bit; /* horizontal position in row */ + register UNSIGN16 i; /* loop index */ + register UNSIGN16 k; /* loop index */ + long offset; /* offset into font file */ + long p; /* pointer into font file */ + UNSIGN32 packet_length; /* packet length */ + UNSIGN32* pword; /* pointer into img_row[] */ + INT16 rows_left; /* how many rows left */ + struct char_entry *tcharptr;/* temporary char_entry pointer */ + BYTE turn_on; /* initial black/white flag */ + + /******************************************************************* + This function is called to process a single character description in + the PK font file. The character packet is pointed to by + fontptr->ch[c].fontrp, and was set by readpk(), which moved past any + special commands that precede the packet. + + The PK raster description is encoded in a complex form, but is + guaranteed to step across raster rows from left to right, and down + from the top row to bottom row, such that in references to + image[n][m], m never decreases in a row, and n never increases in a + character. This means that we only require enough memory space to + hold one row, provided that outfcn(c,yoff) is called each time a row + is completed. This is an important economization for + high-resolution output devices -- e.g. a 10pt character at 2400 + dots/inch would require about 8Kb for the entire image, but fewer + than 25 bytes for a single row. A 72pt character (such as in the + aminch font) would need about 430Kb for the image, but only about + 200 bytes for a row. + + The code follows PKtoPX quite closely, particular the latter's + sections 37-43 for preamble processing, and sections 44-51 for + raster decoding. + + Access to bit m in the current row is controlled through the macros + SETBIT(m) and TESTBIT(m) so we need not be concerned about the + details of bit masking. Too bad C does not have a bit data type! + + The row image is recorded in such a way that bits min_m .. max_m are + mapped onto bits 0 .. (max_m - min_m) in img_row[], so that + outfcn(c,yoff) should be relieved of any shifting operations. + + outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or if + it is NULL. + *******************************************************************/ + + if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c)) + { + (void)warning( + "charpk(): Character value out of range for PK font file"); + return(EOF); + } + tcharptr = &(fontptr->ch[c]); + + if (!VISIBLE(tcharptr)) + return(0); /* empty character raster -- nothing to output */ + + c_width = (UNSIGN16)tcharptr->wp; /* local copies of these to save */ + c_height = (UNSIGN16)tcharptr->hp; /* pointer dereferencing in loops */ + + p = (long)tcharptr->fontrp; /* font file raster pointer */ + if (p < 0L) + { + (void)warning( + "charpk(): Requested character not found in PK font file"); + return(EOF); + } + if (FSEEK(fontfp,p,0)) + { + (void)warning( + "charpk(): FSEEK() failure for PK font file character raster"); + return(EOF); + } + + /* Since readpk() has already done error checking on the file, and + recorded the character metrics, we need not repeat that work, and + concentrate instead on getting to the encoded raster description + which follows the character packet. */ + + img_words = (UNSIGN16)(c_width + 31) >> 5; + flag_byte = (BYTE)nosignex(fontfp,(BYTE)1); /* get packet flag byte */ + dyn_f = flag_byte >> 4; /* dyn_f is high 4 bits from flag_byte */ + turn_on = (BYTE)(flag_byte & 0x08); /* turn_on is 8-bit from flag_byte */ + flag_byte &= 0x07; /* final flag_byte is low 3 bits */ + do_output = (BOOLEAN)(outfcn != (void(*)())NULL); + + switch(flag_byte) /* flag_byte is in 0..7 */ + { + case 0: + case 1: + case 2: + case 3: /* short character preamble */ + packet_length = (UNSIGN32)flag_byte; + packet_length <<= 8; + packet_length += (UNSIGN32)nosignex(fontfp,(BYTE)1); + packet_length -= 8L; + offset = 9L; + break; + + case 4: + case 5: + case 6: /* extended short character preamble */ + packet_length = (UNSIGN32)(flag_byte & 0x03); + packet_length <<= 16; + packet_length += (UNSIGN32)nosignex(fontfp,(BYTE)2); + packet_length -= 13L; + offset = 14L; + break; + + case 7: /* long character preamble */ + packet_length = (UNSIGN32)nosignex(fontfp,(BYTE)4); + packet_length -= 28L; + offset = 32L; + break; + + } /* end switch */ + + if (FSEEK(fontfp,offset,1)) /* position to start of raster data */ + { + (void)warning( + "charpk(): FSEEK() failure for PK font file character raster"); + return(EOF); + } + + bit_weight = 0; + + if (dyn_f == (BYTE)14) /* <PKtoPX: Get raster by bits> */ + { /* uncompressed character image */ + for (i = 0; i < c_height; ++i) + { + pword = img_row; + if (do_output) + (void)clrrow(); + word_weight = (BYTE)31; + for (k = 0; k < c_width; ++k) + { + if (get_bit()) + *pword |= power[word_weight]; + if (word_weight) + --word_weight; + else + { + ++pword; + word_weight = (BYTE)31; + } + } /* end for (k) */ + if (do_output) + (void)(*outfcn)(c,i); + } /* end for (i) */ + } + else /* <PKtoPX: Create normally packed raster> */ + { /* run-length encoded character image */ + rows_left = (INT16)c_height; + h_bit = c_width; + repeat_count = 0; + word_weight = (BYTE)32; + pword = img_row; + if (do_output) + (void)clrrow(); /* clear img_row[] */ + while (rows_left > 0) + { + count = (INT16)pk_packed_num(); + while (count > 0) + { + if ( (count < (INT16)word_weight) && (count < (INT16)h_bit) ) + { + if (turn_on) + { + *pword |= gpower[word_weight]; + *pword &= ~gpower[word_weight - count]; + } + h_bit -= (UNSIGN16)count; + word_weight -= (BYTE)count; + count = 0; + } + else if ( (count >= (INT16)h_bit) && + (h_bit <= (UNSIGN16)word_weight) ) + { + if (turn_on) + { + *pword |= gpower[word_weight]; + *pword &= ~gpower[word_weight - h_bit]; + } + if (do_output) + { + for (i = 0; i <= repeat_count; (--rows_left, ++i)) + (void)(*outfcn)(c,(UNSIGN16)(c_height-rows_left)); + } + else + rows_left -= (INT16)(repeat_count + 1); + repeat_count = 0; + pword = img_row; + if (do_output) + (void)clrrow(); + word_weight = (BYTE)32; + count -= (INT16)h_bit; + h_bit = c_width; + } + else + { + if (turn_on) + *pword |= gpower[word_weight]; + pword++; + count -= (INT16)word_weight; + h_bit -= (UNSIGN16)word_weight; + word_weight = (BYTE)32; + } + } /* end while (count > 0) */ + turn_on = (BYTE)(!turn_on); + } /* end while (rows_left > 0) */ + if ((rows_left > 0) || (h_bit != c_width)) + { + (void)warning( + "charpk(): Bad PK font file--more bits than required"); + return(EOF); + } + } /* end if (run-length encoded image) */ + + return(0); +} + +/*-->get_bit*/ +/**********************************************************************/ +/****************************** get_bit *******************************/ +/**********************************************************************/ + +BYTE +get_bit() /* return 0, or non-zero (not necessarily 1) */ +{ + register BYTE temp; + + bit_weight >>= 1; + if (bit_weight == 0) /* then must get new byte from font file */ + { + next_byte = (BYTE)nosignex(fontfp,(BYTE)1); + bit_weight = (BYTE)128; + } + temp = next_byte & bit_weight; + next_byte &= ~bit_weight; /* clear the just-read bit */ + + return (temp); +} + + +/*-->get_nybble*/ +/**********************************************************************/ +/***************************** get_nybble *****************************/ +/**********************************************************************/ + +BYTE +get_nybble() +{ + register BYTE temp; + + if (bit_weight == 0) /* get high nybble */ + { + next_byte = (BYTE)nosignex(fontfp,(BYTE)1); + temp = next_byte >> 4; + next_byte &= 0x0f; + bit_weight = (BYTE)1; + } + else /* get low nybble */ + { + temp = next_byte; /* this has only 4 bits in it */ + bit_weight = (BYTE)0; + } + return(temp); +} + +/*-->pk_packed_num*/ +/**********************************************************************/ +/*************************** pk_packed_num ****************************/ +/**********************************************************************/ + +UNSIGN16 +pk_packed_num() /* return a (non-negative) packed number from the font file */ +{ /* this function is recursive to one level only */ + INT16 i,j; + + i = (INT16)get_nybble(); + if (i == 0) + { + do + { + j = (INT16)get_nybble(); + ++i; + } while (j == 0); + while (i > 0) + { + j <<= 4; + j += (INT16)get_nybble(); + --i; + } + return((UNSIGN16)(j - 15 + ((13 - dyn_f) << 4) + dyn_f)); + } + else if (i <= (INT16)dyn_f) + return((UNSIGN16)i); + else if (i < 14) + return((UNSIGN16)(((i - dyn_f - 1) << 4) + get_nybble() + dyn_f + 1)); + else if (i == 14) + { + repeat_count = pk_packed_num(); + return(pk_packed_num()); + } + else + { + repeat_count = 1; + return(pk_packed_num()); + } +} + + |