|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 18079 (0x469f) Types: TextFile Names: »gf.c«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦this⟧ »./DVIware/laser-setters/dvi-to-ps/pdvi2ps/gf.c« └─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« └─⟦ca79c7339⟧ └─⟦this⟧ »DVIware/laser-setters/dvi-to-ps/pdvi2ps/gf.c«
#ifndef USEPXL /* modified by Peter Damron 1987 University of Washington */ /*---------------------------------------------------------------------*/ #ifndef lint static char rcsid[] = "$Header: gf.c,v 2.0 88/06/07 15:02:50 peterd Rel2 $"; #endif lint /*---------------------------------------------------------------------*/ #include <stdio.h> #include "gf.h" /*---------------------------------------------------------------------*/ /* This file contains routines for reading character descriptions from GF files (the output of Metafont). The following functions are defined: gf_gettochar() finds the next character, returns its code (reduced modulo 256 if necessary), and sets global variables gf_min_m, gf_max_m, gf_min_n, gf_max_n. A result of -1 indicates that there are no more characters and the postamble has been found. gf_readbits() After a character is found, this routine fills array gf_bits[] with the character image. The image is represented in Postscript format: the bits are packed into bytes (most significant bit first), and the bytes scan the image left-to-right, bottom-to-top. Set globals gf_num_cols, gf_num_rows, gf_x_offset, gf_y_offset (the latter give the offset of the origin from the upper bottom corner of the image, up being a positive gf_y_offset). gf_readpost() After the postamble is found, this routine reads it and sets the remaining global variables declared below. gf_seekpost() rapidly finds the postamble by random accessing the file. gf_seekchar(c) uses fseek() to find a character with code c (modulo 256), returning a nonzero result if successful. Global variables are set as they are by gf_gettochar. GF files may contain many characters with the same code, in which case subsequent calls to gf_seekchar(c) with the same c will find the other versions. This routine should only be called after gf_readpost(). No random access is attempted if gf_seekpost() and gf_seekchar() are not used. */ /*---------------------------------------------------------------------*/ /* use macros versus functions */ #define MACROS 1 #ifndef TRUE #define FALSE 0 #define TRUE 1 #endif TRUE /*---------------------------------------------------------------------*/ int gf_min_m; /* min horz bounding box for character */ int gf_max_m; /* max horz bounding box for character */ int gf_min_n; /* min vert bounding box for character */ int gf_max_n; /* max vert bounding box for character */ int32 gf_charfam; /* high order bytes of character code */ int gf_cur_char; /* current character - for error messages */ /*---------------------------------------------------------------------*/ /* these variables initialized by gf_readpost() */ int gf_font_min_m; /* min horz overall bounds of this font */ int gf_font_max_m; /* max horz overall bounds of this font */ int gf_font_min_n; /* min vert overall bounds of this font */ int gf_font_max_n; /* max vert overall bounds of this font */ int32 designsize; /* font size in points scaled by 1<<20 */ int32 gf_checksum; /* should match TFM file and DVI file */ int32 gf_hppp; /* horizontal and vertical pixels/point scaled 1<<16 */ int32 gf_vppp; /* horizontal and vertical pixels/point scaled 1<<16 */ int gf_char_wd[MAXCHARS]; /* character width in pixels, rounded if necessary */ int32 gf_tfm_wd[MAXCHARS]; /* width as a fraction of designsize scaled 1<<20 */ char gf_char_exists[MAXCHARS]; /* nonzero indicates presence of a char_loc */ int gf_bc; /* first nonzero gf_char_exists entries */ int gf_ec; /* last nonzero gf_char_exists entries */ int32 gf_char_pointer[MAXCHARS]; /* used by gf_seekchar() */ int32 gf_backpointer; /* set by gf_gettochar() for use by gf_seekchar() */ /*---------------------------------------------------------------------*/ #ifndef MACROS void gf_beginc(); /* prepare to paint white at (gf_min_m,gf_max_n) */ void gf_paint(); /* paint d pixels and switch colors */ void gf_skip(); /* finish a row and skip d rows */ void gf_endc(); /* finish the last row */ #endif not MACROS /*---------------------------------------------------------------------*/ extern void bad_gf(); /* aborts the program if the gf file is invalid */ FILE *gf_infile = stdin; /* change this externally if necessary */ char *gf_filename = 0; /* name of the currently open font file */ /*---------------------------------------------------------------------*/ /* The following macros describe gf file format */ #define GF_paint_0 0 #define GF_last_paint 63 #define GF_paint1 64 #define GF_paint2 65 #define GF_paint3 66 #define GF_boc 67 #define GF_boc1 68 #define GF_eoc 69 #define GF_skip0 70 #define GF_skip1 71 #define GF_skip2 72 #define GF_skip3 73 #define GF_new_row_0 74 #define GF_last_new_row 238 #define GF_xxx1 239 #define GF_xxx2 240 #define GF_xxx3 241 #define GF_xxx4 242 #define GF_yyy 243 #define GF_no_op 244 #define GF_char_loc 245 #define GF_char_loc0 246 #define GF_pre 247 #define GF_post 248 #define GF_postpost 249 #define undefined_cases 250: case 251: case 252: case 253: case 254: case 255 #define GF_trailer 223 #define GF_version 131 /*---------------------------------------------------------------------*/ /* misc macros for accessing bitmap */ #define row_start(n) (&(gf_bits[(n - gf_min_n)*gf_rowbytes])) #define m_byte(m) ((m - gf_min_m)>>3) /* byte within a row containing bit m */ #define m_bit(m) (7-(m - gf_min_m)&0x7) /* bit within byte for a given m */ /* bit m on byte boundary? */ #define m_notbyteboundary(m) ((m - gf_min_m)&0x7) /*---------------------------------------------------------------------*/ #define BITBUFSIZE 20000 unsigned char gf_bits[BITBUFSIZE]; int gf_num_cols; /* num cols (bits) in bitmap */ int gf_num_rows; /* num rows (bits) in bitmap */ int gf_num_bytes; /* num bytes in bitmap */ int gf_x_offset; /* horz offset of bitmap */ int gf_y_offset; /* vert offset of bitmap */ int gf_rowbytes; /* num bytes/row in bitmap */ static int gf_m0; /* current horz bit number (column) */ #ifndef MACROS static int gf_m; /* current horz bit number (column) */ static int gf_n; /* current horz bit number (row) */ static int gf_paint_switch; /* paint white or black */ static unsigned char *gf_row_ptr; /* pointer to start of current row */ #endif not MACROS /*---------------------------------------------------------------------*/ /* All gf file input goes through the following routines */ #define getbyte() (getc(gf_infile)&0xff) #ifdef NOTDEF int getbyte() { int b; b = getc(gf_infile) & 0xff; printf("Getting %d\n",b); return b; } #endif NOTDEF #define skip1byte() getc(gf_infile) int get2bytes() { register int ans; ans = getbyte() << 8; ans += getbyte(); return ans; } int32 get3bytes() { register int32 ans; ans = getbyte() << 16; ans += getbyte() << 8; ans += getbyte(); return ans; } int32 get4bytes() { register int32 ans; ans = getbyte() << 24; ans += getbyte() << 16; ans += getbyte() << 8; ans += getbyte(); return ans; } #ifdef MACROS #define skip_bytes(n) { \ while (n-- > 0) skip1byte(); \ } #else not MACROS void skip_bytes(n) int n; { while (n-- > 0) skip1byte(); } #endif MACROS /*---------------------------------------------------------------------*/ /* In the unlikely event of a character code outside of the range 0..255, the high order bytes are placed in the global variable gf_charfam. If no boc command is encountered, the result is -1 and the last byte read is guaranteed to be the post command. */ int gf_gettochar() { int32 c; /* the character code to be returned */ register int x; /* temporary */ register int len; /* temporary */ for(;;) switch(getbyte()) { case GF_yyy: skip1byte(); /* intended to fall through 3 times */ case GF_paint3: case GF_skip3: skip1byte(); case GF_paint2: case GF_skip2: skip1byte(); case GF_paint1: case GF_skip1: skip1byte(); continue; case GF_boc: c = get4bytes(); gf_backpointer = get4bytes(); gf_min_m = get4bytes(); gf_max_m = get4bytes(); gf_min_n = get4bytes(); gf_max_n = get4bytes(); gf_charfam = c<0 ? -((-c)>>8) : c>>8; gf_cur_char = c&0377; return c&0377; case GF_boc1: c = getbyte(); gf_backpointer = -1; x = getbyte(); /* del_m */ gf_max_m = getbyte(); gf_min_m = gf_max_m - x; x = getbyte(); /* del_n */ gf_max_n = getbyte(); gf_min_n = gf_max_n - x; gf_cur_char = c; return c; case GF_pre: if (getbyte() != GF_version) bad_gf(1); len = getbyte(); skip_bytes(len); continue; case GF_xxx1: len = getbyte(); skip_bytes(len); continue; case GF_xxx2: len = get2bytes(); skip_bytes(len); continue; case GF_xxx3: len = get3bytes(); skip_bytes(len); continue; case GF_xxx4: len = get4bytes(); skip_bytes(len); continue; case GF_post: return -1; case GF_char_loc: case GF_char_loc0: case GF_postpost: case undefined_cases: bad_gf(2); default: /* do nothing */; } } /*---------------------------------------------------------------------*/ /* read the post-amble of a gf format font file */ void gf_readpost() { register int i; register int b; register int c; get4bytes(); /* ignore back pointer to font-wide xxx commands */ designsize = get4bytes(); gf_checksum = get4bytes(); gf_hppp = get4bytes(); gf_vppp = get4bytes(); gf_font_min_m = get4bytes(); gf_font_max_m = get4bytes(); gf_font_min_n = get4bytes(); gf_font_max_n = get4bytes(); for(i = 0; i < MAXCHARS; i++) { gf_char_exists[i] = FALSE; gf_char_wd[i] = 0; gf_tfm_wd[i] = 0; gf_char_pointer[i] = -1; } gf_bc = MAXCHARS; gf_ec = 0; for (;;) { b = getbyte(); c = getbyte(); if (b == GF_char_loc0) { gf_char_wd[c] = getbyte(); } else if (b == GF_char_loc) { gf_char_wd[c] = (get4bytes()+0100000)>>16; get4bytes(); /* skip dy */ } else { break; } gf_tfm_wd[c] = get4bytes(); gf_char_pointer[c] = get4bytes(); gf_char_exists[c] = TRUE; if (gf_bc>c) gf_bc = c; if (gf_ec<c) gf_ec = c; } gf_cur_char = -1; } /*---------------------------------------------------------------------*/ /* find the post-amble of a gf format font file */ void gf_seekpost() { int c; fseek(gf_infile, -5L, 2); /* skip four 223's */ do { c = getbyte(); fseek(gf_infile, -2L, 1); } while (c == GF_trailer); if (c != GF_version) bad_gf(5); /* check version number */ fseek(gf_infile, -3L, 1); /* back up to the pointer */ if (fseek(gf_infile, (long) get4bytes(), 0) < 0) bad_gf(6); if (getbyte() != GF_post) bad_gf(7); gf_cur_char = -1; } /*---------------------------------------------------------------------*/ /* find a character definition in a gf format font file */ int gf_seekchar(c) int c; { if (c < 0 || c > MAXCHARS-1 || gf_char_pointer[c] < 0) return FALSE; if (fseek(gf_infile, gf_char_pointer[c], 0) < 0) bad_gf(8); if (gf_gettochar() != c) bad_gf(9); gf_cur_char = c; return TRUE; } /*---------------------------------------------------------------------*/ /* begin a character, initialize data */ #ifdef MACROS #define gf_beginc(dummy) { \ gf_num_cols = gf_max_m - gf_min_m + 1; \ gf_num_rows = gf_max_n - gf_min_n + 1; \ gf_x_offset = -gf_min_m; \ gf_y_offset = -gf_min_n; \ gf_rowbytes = (gf_num_cols+7)/8; \ gf_num_bytes = gf_num_rows*gf_rowbytes; \ if (gf_num_bytes >= BITBUFSIZE) \ bad_gf(10); /* really, should allocate a bigger one */ \ gf_m = gf_m0 = gf_min_m; \ gf_n = gf_max_n; \ gf_row_ptr = row_start(gf_max_n); \ bzero(gf_bits, gf_num_bytes); \ gf_paint_switch = FALSE; \ } #else not MACROS void gf_beginc() { gf_num_cols = gf_max_m - gf_min_m + 1; gf_num_rows = gf_max_n - gf_min_n + 1; gf_x_offset = -gf_min_m; gf_y_offset = -gf_min_n; gf_rowbytes = (gf_num_cols+7)/8; gf_num_bytes = gf_num_rows*gf_rowbytes; if (gf_num_bytes >= BITBUFSIZE) { bad_gf(10); /* really, should allocate a bigger one */ } gf_m = gf_m0 = gf_min_m; gf_n = gf_max_n; gf_row_ptr = row_start(gf_max_n); bzero(gf_bits, gf_num_bytes); gf_paint_switch = FALSE; } #endif MACROS /*---------------------------------------------------------------------*/ /* paint a portion of a row of bits into the bitmap */ /* this is a decoding of a run length encoding of a bitmap */ /* d is the number of bits (run length) to encode */ /* gf_paint_switch is a true for one-bits and false for zero bits */ /* this is the old version */ #ifdef NOTDEF void gf_paint(d) register int d; { if (d>0) { if (gf_paint_switch) { while (d-- >0) { gf_row_ptr[m_byte(gf_m)] |= 1<<m_bit(gf_m); gf_m++; } } else { gf_m += d; } } gf_paint_switch ^= 1; } #endif NOTDEF /*---------------------------------------------------------------------*/ /* paint a portion of a row of bits into the bitmap */ /* this is a decoding of a run length encoding of a bitmap */ /* d is the number of bits (run length) to encode */ /* gf_paint_switch is a true for one-bits and false for zero bits */ /* row-ptr is a pointer to the beginning of this row */ /* gf_m is the distance (bits) from the beginning of the row (output bitmap) */ #ifdef MACROS #define gf_paint(len) { \ if (len > 0) { \ if (gf_paint_switch) { \ /* paint white (==1) */ \ /* first fill in the first partial byte */ \ while ((len > 0) && m_notbyteboundary(gf_m)) { \ gf_row_ptr[m_byte(gf_m)] |= 1 << m_bit(gf_m); \ gf_m += 1; \ len -= 1; \ } \ /* now fill in the whole bytes */ \ while (len > 0) { \ /* note (gf_m & 0x7 == 0) */ \ /* this is an even byte boundary */ \ /* so we know what to put into this byte */ \ if (len >= 8) { \ /* this byte is full */ \ gf_row_ptr[m_byte(gf_m)] = 0xFF; \ gf_m += 8; \ len -= 8; \ } else { \ /* this byte is partial */ \ /* len&7 == len div 8 */ \ gf_row_ptr[m_byte(gf_m)] = (0xFF << (8-len)) & 0xFF; \ gf_m += len; \ len = 0; \ } \ } \ gf_paint_switch = FALSE; \ } else { \ /* paint black (==0) is easy */ \ gf_m += len; \ gf_paint_switch = TRUE; \ } \ } else { \ /* len <= 0 */ \ if (len < 0) { \ Warning("internal - unexpected value in gf_paint %d\n",len); \ } \ gf_paint_switch = !gf_paint_switch; \ } \ } #else not MACROS void gf_paint(len) register int len; { /* why was I called? */ if (len <= 0) { if (len < 0) { Warning("internal - unexpected value in gf_paint %d\n",len); } gf_paint_switch = !gf_paint_switch; return; } /* paint black (==0) is easy */ if (!gf_paint_switch) { gf_m += len; gf_paint_switch = TRUE; return; } /* paint white (==1) */ /* first fill in the first partial byte */ while ((len > 0) && m_notbyteboundary(gf_m)) { gf_row_ptr[m_byte(gf_m)] |= 1 << m_bit(gf_m); gf_m += 1; len -= 1; } /* now fill in the whole bytes */ while (len > 0) { /* note (gf_m & 0x7 == 0) */ /* this is an even byte boundary */ /* so we know what to put into this byte */ if (len >= 8) { /* this byte is full */ gf_row_ptr[m_byte(gf_m)] = 0xFF; gf_m += 8; len -= 8; } else { /* this byte is partial */ /* len&7 == len div 8 */ gf_row_ptr[m_byte(gf_m)] = (0xFF << (8-len)) & 0xFF; gf_m += len; len = 0; } } gf_paint_switch = FALSE; } #endif MACROS /*---------------------------------------------------------------------*/ /* skip to the next row of bits */ #ifdef MACROS #define gf_skip(d) { \ gf_n -= d+1; \ gf_m = gf_m0; \ gf_row_ptr = row_start(gf_n); \ gf_paint_switch = FALSE; \ } #else not MACROS void gf_skip(d) int d; { gf_n -= d+1; gf_m = gf_m0; gf_row_ptr = row_start(gf_n); gf_paint_switch = FALSE; } #endif MACROS /*---------------------------------------------------------------------*/ /* end of character */ #ifdef MACROS #define gf_endc(dummy) #else not MACROS void gf_endc() { /* do nothing */ } #endif MACROS /*---------------------------------------------------------------------*/ /* gf_readbits reads a raster description from the gf file and uses the external routines to actually process the raster information. */ void gf_readbits() { /* register unsigned char byt; */ register int byt; register int len; #ifdef MACROS register unsigned char *gf_row_ptr; /* start of current row */ register int gf_m; /* current horz bit number (column) */ register int gf_paint_switch; /* paint white or black */ register int gf_n; /* current horz bit number (row) */ #endif MACROS gf_beginc(); for (;;) { byt = getbyte(); if (byt <= GF_last_paint) { len = byt - GF_paint_0; gf_paint(len); } if (byt < GF_new_row_0) { switch(byt) { case GF_paint1: len = getbyte(); gf_paint(len); continue; case GF_paint2: len = get2bytes(); gf_paint(len); continue; case GF_paint3: len = get3bytes(); gf_paint(len); continue; case GF_boc: case GF_boc1: bad_gf(3); case GF_eoc: goto finish; case GF_skip0: gf_skip(0); continue; case GF_skip1: len = getbyte(); gf_skip(len); continue; case GF_skip2: len = get2bytes(); gf_skip(len); continue; case GF_skip3: len = get3bytes(); gf_skip(len); continue; } } else if (byt <= GF_last_new_row) { gf_skip(0); len = byt - GF_new_row_0; gf_paint(len); } else { switch(byt) { case GF_xxx1: len = getbyte(); skip_bytes(len); continue; case GF_xxx2: len = get2bytes(); skip_bytes(len); continue; case GF_xxx3: len = get3bytes(); skip_bytes(len); continue; case GF_xxx4: len = get4bytes(); skip_bytes(len); continue; case GF_yyy: get4bytes(); continue; case GF_no_op: continue; default: bad_gf(4); } } } finish: gf_endc(); } /*---------------------------------------------------------------------*/ /* report errors */ void bad_gf(n) int n; { Fatal("bad gf font file %s\n char %d offset %d case %d\n", gf_filename,gf_cur_char,ftell(gf_infile),n); } /*---------------------------------------------------------------------*/ #endif USEPXL