diff options
Diffstat (limited to 'dviware/beebe/src/chargf.h')
-rw-r--r-- | dviware/beebe/src/chargf.h | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/dviware/beebe/src/chargf.h b/dviware/beebe/src/chargf.h new file mode 100644 index 0000000000..dae9f894f5 --- /dev/null +++ b/dviware/beebe/src/chargf.h @@ -0,0 +1,344 @@ +/* -*-C-*- chargf.h */ +/*-->chargf*/ +/**********************************************************************/ +/******************************* chargf *******************************/ +/**********************************************************************/ + +int +chargf(c,outfcn) /* return 0 on success, and EOF on failure */ +BYTE c; /* current character value */ +void (*outfcn)(); /* (possibly NULL) function to output current row */ +{ + UNSIGN16 d; /* step in m index */ + BOOLEAN do_output; /* FALSE if outfcn is NULL */ + register UNSIGN16 k; /* loop step */ + register INT16 m,n; /* column,row indices in image[n][m] */ + long p; /* pointer into font file */ + BYTE paint_switch; /* alternates between BLACK and WHITE */ + struct char_entry *tcharptr;/* temporary char_entry pointer */ + register BYTE the_byte; /* current command byte */ + UNSIGN32 the_word; /* temporary result holder */ + +/* NB: We only test for equality with BLACK. WHITE is any non-zero +bit pattern, so we cannot test for equality with it */ +#define BLACK ((BYTE)0) +#define WHITE ((BYTE)(!BLACK)) + + /******************************************************************* + This function is called to process a single character description in + the GF font file, and to set the character metrics hp, wp, xoffp, + and yoffp for it. The character description may start either at a + special (XXX) command, or at a beginning-of-character (BOC or BOC1) + command. It processes the character description up to, and + including, the end-of-character (EOC) command which terminates it. + + The GF 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. + + 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 + if it is NULL. + *******************************************************************/ + + if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c)) + { + (void)warning( + "chargf(): Character value out of range for GF font file"); + return(EOF); + } + tcharptr = &(fontptr->ch[c]); + + p = (long)tcharptr->fontrp; /* font file raster pointer */ + if (p < 0L) + { + (void)warning( + "chargf(): Requested character not found in GF font file"); + return(EOF); + } + if (FSEEK(fontfp,p,0)) + { + (void)warning( + "chargf(): FSEEK() failure for GF font file character raster"); + return(EOF); + } + + do_output = (BOOLEAN)(outfcn != (void(*)())NULL); + + (void)skgfspec(); /* skip any GF special commands */ + + the_byte = (BYTE)nosignex(fontfp,(BYTE)1); + if ((the_byte != GFBOC) && (the_byte != GFBOC1)) + { + (void)warning( + "chargf(): GF font file not positioned at BOC or BOC1 command"); + return(EOF); + } + + for (;;) /* loop with exit at EOC, or at BOC or BOC1 if no rasters */ + { + switch (the_byte) + { + case GFPAINT0: + paint_switch = (BYTE)(!paint_switch); + break; + + case GFPAINT1: + d = (UNSIGN16)nosignex(fontfp,(BYTE)1); + if (do_output && (paint_switch == BLACK)) + { + for (k = 0; k < d; (++m, ++k)) + SETBIT(m); + } + else + m += (INT16)d; + paint_switch = (BYTE)(!paint_switch); + break; + + case GFPAINT2: + d = (UNSIGN16)nosignex(fontfp,(BYTE)2); + if (do_output && (paint_switch == BLACK)) + { + for (k = 0; k < d; (++m, ++k)) + SETBIT(m); + } + else + m += (INT16)d; + paint_switch = (BYTE)(!paint_switch); + break; + + case GFPAINT3: /* METAFONT never needs this */ + d = (UNSIGN16)nosignex(fontfp,(BYTE)3); /* NOTE: truncation */ + if (do_output && (paint_switch == BLACK)) + { + for (k = 0; k < d; (++m, ++k)) + SETBIT(m); + } + else + m += (INT16)d; + paint_switch = (BYTE)(!paint_switch); + break; + + case GFBOC: /* beginning-of-character -- long form */ + the_word = (UNSIGN32)nosignex(fontfp,(BYTE)4); + p = (long)signex(fontfp,(BYTE)4); + if ((UNSIGN32)c != the_word) + { + if (p < 0L) + { + (void)warning( + "chargf(): Requested character not found in back chain in GF font file"); + return(EOF); + } + else + (void)FSEEK(fontfp,p,0); /* must follow back chain */ + break; + } + else + { + min_m = (INT16)signex(fontfp,(BYTE)4); + max_m = (INT16)signex(fontfp,(BYTE)4); + min_n = (INT16)signex(fontfp,(BYTE)4); + max_n = (INT16)signex(fontfp,(BYTE)4); + } + if ((min_m < MIN_M) || (MAX_M < max_m) || + (min_n < MIN_N) || (MAX_N < max_n)) + { + (void)warning( + "chargf(): GF font file character box too large for me"); + return(EOF); + } + m = min_m; + n = max_n; + paint_switch = WHITE; + img_words = (UNSIGN16)((max_m - min_m + 1 + 31) >> 5); + if (do_output) + (void)clrrow(); + tcharptr->hp = (COORDINATE)(max_n - min_n + 1); + tcharptr->wp = (COORDINATE)(max_m - min_m + 1); + tcharptr->xoffp = -(COORDINATE)(min_m); + tcharptr->yoffp = (COORDINATE)(max_n); + if (!VISIBLE(tcharptr)) + return(0); /* empty character raster -- nothing to output */ + break; + + case GFBOC1: /* beginning-of-character -- short form */ + if (c != (BYTE)nosignex(fontfp,(BYTE)1)) + { + (void)warning( + "chargf(): Requested character not found in GF font file"); + return(EOF); + } + else + { + min_m = (INT16)nosignex(fontfp,(BYTE)1); + max_m = (INT16)nosignex(fontfp,(BYTE)1); + min_m = max_m - min_m; + min_n = (INT16)nosignex(fontfp,(BYTE)1); + max_n = (INT16)nosignex(fontfp,(BYTE)1); + min_n = max_n - min_n; + } + if ((min_m < MIN_M) || (MAX_M < max_m) || + (min_n < MIN_N) || (MAX_N < max_n)) + { + (void)warning( + "chargf(): GF font file character box too large for me"); + return(EOF); + } + m = min_m; + n = max_n; + paint_switch = WHITE; + img_words = (UNSIGN16)((max_m - min_m + 1 + 31) >> 5); + if (do_output) + (void)clrrow(); + tcharptr->hp = (COORDINATE)(max_n - min_n + 1); + tcharptr->wp = (COORDINATE)(max_m - min_m + 1); + tcharptr->xoffp = -(COORDINATE)(min_m); + tcharptr->yoffp = (COORDINATE)(max_n); + if (!VISIBLE(tcharptr)) + return(0);/* empty character raster -- nothing to output */ + break; + + case GFEOC: /* end-of-character */ + if (do_output) + { + (void)(*outfcn)(c,max_n-n); /* output current row */ + (void)clrrow(); /* clear next one */ + --n; /* advance to next row below */ + for ( ; n >= min_n ; --n) /* output any remaining rows */ + (void)(*outfcn)(c,max_n-n); + } + return(0); /* exit outer loop */ + + case GFSKIP0: + if (do_output) + { + (void)(*outfcn)(c,max_n-n); /* output current row */ + (void)clrrow(); /* clear next one */ + } + --n; /* advance to next row below */ + m = min_m; + paint_switch = WHITE; + break; + + case GFSKIP1: + if (do_output) + { + (void)(*outfcn)(c,max_n-n); /* output current row */ + (void)clrrow(); /* clear next one */ + } + --n; /* advance to next row below */ + d = (UNSIGN16)nosignex(fontfp,(BYTE)1); + if (do_output) + { + for (k = 0; k < d; (--n,++k)) /* output d white rows */ + (void)(*outfcn)(c,max_n-n); + } + else + n -= (INT16)d; + m = min_m; + paint_switch = WHITE; + break; + + case GFSKIP2: + if (do_output) + { + (void)(*outfcn)(c,max_n-n); /* output current row */ + (void)clrrow(); /* clear next one */ + } + --n; /* advance to next row below */ + d = (UNSIGN16)nosignex(fontfp,(BYTE)2); + if (do_output) + { + for (k = 0; k < d; (--n,++k)) /* output d white rows */ + (void)(*outfcn)(c,max_n-n); + } + else + n -= (INT16)d; + m = min_m; + paint_switch = WHITE; + break; + + case GFSKIP3: /* METAFONT never needs this */ + if (do_output) + { + (void)(*outfcn)(c,max_n-n); /* output current row */ + (void)clrrow(); /* clear next one */ + } + --n; /* advance to next row below */ + d = (UNSIGN16)nosignex(fontfp,(BYTE)3); /* NOTE truncation */ + if (do_output) + { + for (k = 0; k < d; (++k, --n)) /* output d white rows */ + (void)(*outfcn)(c,max_n-n); + } + else + n -= (INT16)d; + m = min_m; + paint_switch = WHITE; + break; + + case GFXXX1: + case GFXXX2: + case GFXXX3: + case GFXXX4: + case GFYYY: + case GFNOOP: + (void)UNGETC((char)the_byte,fontfp); + (void)skgfspec(); + break; + + default: + if (((BYTE)GFPAINT0 < the_byte) && (the_byte < GFPAINT1)) + { + d = (UNSIGN16)(the_byte - GFPAINT0); + if (do_output && (paint_switch == BLACK)) + { + for (k = 0; k < d; (++m, ++k)) + SETBIT(m); + } + else + m += (INT16)d; + paint_switch = (BYTE)(!paint_switch); + } + else if (((BYTE)GFNROW0 <= the_byte) && (the_byte <= GFNROWMAX)) + { + if (do_output) + { + (void)(*outfcn)(c,max_n-n); /* output current row */ + (void)clrrow(); /* clear next one */ + } + n--; /* advance to next row below */ + paint_switch = BLACK; + m = min_m + (UNSIGN16)(the_byte - GFNROW0); + } + else + { + (void)sprintf(message, + "chargf(): Unexpected byte %d (0x%02x) in GF font file \ +at position %ld", + the_byte,the_byte,(long)FTELL(fontfp)); + (void)warning(message); + return(EOF); + } + break; + } /* end switch */ + the_byte = (BYTE)nosignex(fontfp,(BYTE)1); + } /* end for() */ +} |