donn (10/20/82)
/* * devf.c * * Purpose: Edit vtroff fonts in an expanded (ASCII) format. * Usage: devf < infile > fontfile * The input file contains an ASCII version of a fontfile in the format * of "vfontinfo -z0 -v", suitable for hand editing. Actually, * /usr/lib/vfontinfo -v -z0 [font] | devf > [font] * is a very tedious no-op and a good test of the program. * Date: 7/18/82 * Author: Donn Seeley UCSD Linguistics Dept. * Remarks: */ # include <stdio.h> # include <vfont.h> # define LEFT 0 # define RIGHT 1 # define MAXINT 0x7fffffff # define LINESIZE 256 # define GLYPHSIZE 4096 struct header header; struct dispatch dispatch[256]; struct dispatch *getdisp(); char *bitmap[256]; char glyphbuf[GLYPHSIZE]; /* * Macro for identifying dispatch info lines. */ # define DISP(x) ((x) != NULL && strlen(x) > 5 \ && (x)[4] >= '0' && (x)[4] <= '9') main() { register char *pg = &glyphbuf[0]; char *startg, *endg; register int n; register int nlines, nblanks; int addr = 0; int left_offset, right_offset, top_offset, bottom_offset; register struct dispatch *pd; /* * Get initial header information. */ if ( fgets( pg, LINESIZE, stdin ) == NULL ) { fprintf( stderr, "Can't read input\n" ); exit( 1 ); } if ( ! gethead( pg ) ) { fprintf( stderr, "Input is not vfontinfo format\n" ); exit( 1 ); } /* * Read the first dispatch description line. */ fgets( pg, LINESIZE, stdin ); fgets( pg, LINESIZE, stdin ); if ( fgets( pg, LINESIZE, stdin ) == NULL ) { fprintf( stderr, "Can't read input\n" ); exit( 1 ); } /* * Loop on glyphs. */ while ( (pd = getdisp( pg )) != NULL ) { left_offset = MAXINT; right_offset = 0; top_offset = -1; bottom_offset = 0; pg = &glyphbuf[0]; startg = pg; endg = pg; nlines = 0; nblanks = 0; /* * Fetch a glyph. */ fgets( pg, LINESIZE, stdin ); while( ! DISP( pg ) ) { /* * Eat extra blank lines at the tops of glyphs. */ ++nlines; if ( blank( pg ) ) ++nblanks; else { if ( top_offset == -1 ) { top_offset = nblanks; startg = pg; } nblanks = 0; endg = pg; } /* * Eat extra rows on left and right margins. */ if ( (n = margin( pg, LEFT )) < left_offset ) left_offset = n; if ( (n = margin( pg, RIGHT )) >= right_offset ) right_offset = n + 1; /* * Read next line, test for end. */ pg += strlen( pg ) + 1; if ( fgets( pg, LINESIZE, stdin ) == NULL ) { # ifdef DEBUG fprintf(stderr, "END OF FILE\n"); fwrite( glyphbuf, 1, pg-glyphbuf, stderr ); fprintf( stderr, "%s", pg ); # endif pg = NULL; break; } } bottom_offset = nblanks; /* * Adjust dispatch values. */ pd->down = (nlines - pd->up) - bottom_offset; pd->up -= top_offset; n = pd->right; pd->right = right_offset - pd->left; pd->left -= left_offset; pd->width += pd->right - n; pd->nbytes = ((pd->left + pd->right + 7) / 8) * (pd->up + pd->down); pd->addr = addr; addr += pd->nbytes; /* * Make raster data. */ do_bitmap( pd, startg, endg, left_offset, right_offset ); } /* * Output the file. */ header.size = addr; fwrite( &header, sizeof (struct header), 1, stdout ); fwrite( &dispatch[0], sizeof (struct dispatch), 256, stdout ); for ( n = 0; n < 256; ++n ) if ( dispatch[n].nbytes > 0 && bitmap[n] != NULL ) fwrite( bitmap[n], sizeof (char), dispatch[n].nbytes, stdout ); exit( 0 ); } /* * gethead( buf ) -- Read ascii vfontinfo information out of buf into a header. * Sample: "Font S.10, raster size 4334, max width 96, max height 96, xtend 21" */ int gethead( buf ) char *buf; { register int n; header.magic = 0436; n = sscanf( buf, "%*s %*s %*s %*s %hd, %*s %*s %hd, %*s %*s %hd, %*s %hd", &header.size, &header.maxx, &header.maxy, &header.xtend ); return ( n == 4 ); } /* * getdisp( buf ) -- Read ascii dispatch information out of buf, store it in * the right dispatch structure and return a pointer to the structure. * ASCII offset size left right up down width * Sample: " 1 ^A 0 24 -3 20 12 -4 21" */ struct dispatch * getdisp( buf ) char *buf; { register struct dispatch *pd; int n, l, r, u, d, w, count; if ( buf == NULL ) return ( NULL ); count = sscanf( buf, " %o %*s %*d %*d %d %d %d %d %d", &n, &l,&r,&u,&d,&w ); if ( count != 6 ) { # ifdef DEBUG fprintf(stderr, "BAD INPUT\n"); fwrite( glyphbuf, 1, buf-glyphbuf, stderr ); fprintf( stderr, "%s", buf ); # endif return ( NULL ); } pd = &dispatch[n]; pd->addr = 0; pd->nbytes = 0; pd->left = l; pd->right = r; pd->up = u; pd->down = d; pd->width = w; return ( pd ); } /* * blank( buf ) -- True if the line in buf is empty or contains only blanks. */ int blank( buf ) register char *buf; { if ( buf == NULL ) return ( 1 ); while ( *buf >= ' ' ) if ( *buf++ != ' ' ) return ( 0 ); return ( 1 ); } /* * margin( buf, side ) -- Return distance from left margin of the data point * nearest the indicated side using vfontinfo data in buf. * Return MAXINT for left, 0 for right if the line is blank. */ int margin( buf, side ) char *buf; int side; { register char *pb = buf; register char *lastp = buf; while ( *pb >= ' ' ) { if ( *pb > ' ' ) { if ( side == LEFT ) return ( (pb - buf) >> 1 ); lastp = pb; } if ( *++pb < ' ' ) break; ++pb; } if ( side == RIGHT ) return ( (lastp - buf) >> 1 ); else return ( MAXINT ); } /* * do_bitmap( pd, start, end, left, right ) -- Read vfontinfo format buffer from * line start up to line end and fill a bitmap buffer associated with * dispatch structure *pd with data from left margin to right margin. */ do_bitmap( pd, start, end, left, right ) struct dispatch *pd; char *start; char *end; int left; int right; { register char *pb; register char *pg = start; register int i, j; if ( pd->nbytes == 0 ) return; /* * Make a bitmap buffer. */ i = pd - &dispatch[0]; pb = (char *) calloc( pd->nbytes, sizeof (char) ); if ( pb == NULL ) { fprintf( stderr, "Out of memory\n" ); exit( 1 ); } bitmap[i] = pb; /* * Loop on glyph lines. */ while ( pg <= end ) { /* * Skip left margin. */ for ( i = 0; i < 2 * left && *pg >= ' '; ++i, ++pg ); /* * Map data points to bits. * Note that bits in a byte are arranged so that the most * significant bit prints in the leftmost position... sigh. * An inelegant decision on the part of Versatec, given * that *bytes* of *least* significance print leftmost on * a plotted line. */ i = 0; j = 0; while ( i < right - left ) { if ( *pg > ' ' ) *pb |= 1 << 7-j; ++i, ++j; if ( j >= 8 ) { j = 0; ++pb; } if ( *pg >= ' ' && *++pg >= ' ' ) ++pg; } /* * Pad out raster rows to byte multiples. */ if ( j > 0 ) ++pb; /* * Get next line. */ while ( *pg >= ' ' ) ++pg; while ( *pg < ' ' ) ++pg; } } ============================================================================== .TH DEVF 1 .SH NAME devf \- fontfile converter for vtroff .SH SYNOPSIS .B devf < input_file > fontfile .SH DESCRIPTION .I Devf is the inverse program to .I vfontinfo(1). .I Devf will take an input file of the sort produced by `/usr/lib/vfontinfo -v -z0 < fontfile > input_file' and make a `fontfile'. Files like `input_file' may be edited to produce bitmaps for new characters which will appear in the fontfile which .I devf makes, which you can then use with .I vtroff. The basic information on how to use this program is given in the manual entry for .I makefont(1) (q.v.); read on only if you like esoteric stuff. .PP Every character in the font is represented in the expanded fontfile as a header containing useful information and a diagram. There are several numbers in the header for each letter; the names of columns are given in a main header at the very top. The first field is an octal number which uniquely identifies a character. If you create a new character be sure that its number is distinct. The left, right, up, down and width parameters describe distances in relation to a fixed point of reference for a character. You can visualize this reference point as being vertically on the line on which you would write the character on ruled paper, and horizontally near the left edge of the character. If you don't manipulate the numbers in the header then when you edit a character this point stays fixed with respect to the top and left margins. In particular if you add rows on top or columns on the left this has the effect of translating the character down or right with respect to the fixed reference point. To prevent this sliding you must increment the ``left'' parameter for every column added on the left and increment the ``up'' parameter for every row added on top, changing the position of the reference point. The ``right'', ``down'' and ``width'' parameters are handled automatically by .I devf. You may sometimes want to tune the ``width'' parameter though -- this represents the distance to go to the right in order to reach the reference point of the next letter in the text and thus it ultimately determines proportional character spacing. .PP The diagram is a representation of the bitmap for the character. Every raster position occupies two horizontal screen positions and one vertical screen position. Printing bits are indicated by a pair of matching square brackets: `[]'. Nonprinting bits are simply left blank, or omitted altogether if they lie on the right margin. To change the bitmap for a character you merely change the distribution of the square brackets and blanks. Replacing a pair of brackets by a pair of blanks (or trimming them from the right margin) turns off a printing bit; similarly, replacing blanks with brackets (or adding onto the right margin) turns on a printing bit. The rules are actually fairly lax: .I devf assumes that a raster position is nonprinting if the first screen position in a pair is a blank or is unoccupied, otherwise it assumes that it is printing. .SH AUTHOR Donn Seeley, UCSD Linguistics Dept. .SH BUGS Probably lots of them. This version of ``devf'' depends on your having the latest version of ``vfontinfo'', with the `-z' option; older versions will require some retooling.