summaryrefslogtreecommitdiff
path: root/dviware/beebe/src/chargf.h
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/beebe/src/chargf.h')
-rw-r--r--dviware/beebe/src/chargf.h344
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() */
+}