home *** CD-ROM | disk | FTP | other *** search
- /* -*-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());
- }
- }
-
-
-