[mod.sources] v08i089: Hershey fonts to 'vfont' rasterizer

sources-request@mirror.UUCP (03/02/87)

Submitted by: William LeFebvre <phil@rice.edu>
Mod.sources: Volume 8, Issue 89
Archive-name: her2vfont

I have gotten many requests for this program, but I have been slow to
resond to them.  Sorry about the delay.

This program, hfont, rasterizes characters from the public domain
vector font called "Hershey's Repertory" using a symmetric DDA
algorithm.  It stores the resulting fonts in vfont format.  I'm not
sure if Bell Unix has the proper include file for vfont format:
"/usr/include/vfont.h".  Some of you may have to go searching for it:
I cannot provide it for you.

This software is provided AS IS.  I'm not particularly interested in
supporting it, but I am providing it in the interests of sharing
knowledge.  So don't expect this program to be as well polished as,
say, "top" is.  Share and enjoy!

			William LeFebvre
			Department of Computer Science
			Rice University
			<phil@Rice.edu>

------------------------------ CUT HERE ------------------------------
echo 'Start of distribution file hfont.shar:'
echo 'Extracting README...'
sed 's/^X//' > README << '/'
XHFONT
X
XThis is a program that rasterizes the Hershey vector fonts using a
Xsymmetric DDA.  It builds fonts in the standard vfont format.  It takes as
Xinput lines describing what hershey character should be placed in what
Xposition in the vfont, along with certain rasterization options.  It is
Xcapable of building fonts of any point size using a pen shape provided by
Xthe user.
X
XBefore running this program, you need the following files: hershey format
Xfile, pen file, descriptor file.  I will describe each one in turn:
X
Xhershey format file:
X   The standard Hershey repertory, as distributed, will do.  This program
X   understands a rather loose format that includes the format used by
X   Hershey.  The default is "occidental" in the current directory.
X
Xpen file:
X   This describes the shape of the pen at various point sizes.  Each pen
X   description in this file starts with the line "pen x" where "x" is the
X   point size at which this pen should be used.  The last line in the file
X   is always "penend".  Each pen itself is described with a simple diagram
X   consisting of spaces and stars (*).  Here is an example of a simple pen
X   shape:
X
X           *
X          ***
X           *
X
X   The file "pen.round" in this distribution will give you a good idea
X   what a pen file should look like.  It is also the default.
X
Xdescriptor file:
X   Hfont expects to see this on standard input.  You can type them in by
X   hand from the terminal (especially convenient when testing things out),
X   but it is best to keep permanent descriptions in separate files and
X   use shell redirection when running hfont.  This file has two areas.
X   Each line in the first area contains a keyword and possible arguments.
X   This allows for description specific options.  The keywords and their
X   functions are:
X
X        repertory filename
X            use "filename" as the vector repertory rather than the default
X
X        maxchar num
X            an outdated keyword that should no longer be used
X
X        pen filename
X            use "pen" as the penfile
X
X        aspect num
X            use the (fractional) number "num" as the standard aspect ratio
X            for all characters (explained in more detail later)
X
X        charset
X            start of the character set description
X
X   The "charset" keyword is always the last one, and it separates the
X   first area from the second.  Each line after "charset" has the
X   following form:
X
X        index,char[,vmot][,rxxx]
X
X   "index" is the character number of the desired character in the vector
X   repertory (for example, 2001 is the Duplex Roman "A" in the Hershey
X   occidental repertory); "char" is the character position in the vfont
X   where the character will be placed (it can either be a single
X   character, or "\" followed by an octal number -- simply "\" is sufficint
X   for the backslash); "vmot" is a number giving vertical displacement;
X   "rxxx" is a specific aspect ratio for this character (where "xxx" is
X   replaced with a fractional number).
X
X   There are two options that can be specified in the "index" field.  If
X   the index number is really "p", then an exact image of the drawing pen
X   is used as a character.  If the index starts with a "s", remainder of
X   the field is taken to be an integer specifying the width of a space.
X   This space is then used as the character (and no bitmap is associated
X   with it).  For example:
X
X        p,\210     places an image of the pen at octal 210 in the vfont.
X        s15,\212   places a 15 pixel wide space at octal 212.
X
X   Oversight:  there is no way to generate a point size specific space.
X
XRasterizing options:
X
XVertical displacement:
X   When I first wrote this, I found this option very useful.  It allows
X   one to shift a character's rasterized image vertically.  So, for
X   example, the same horizontal line can be used for a hyphen and an
X   underline.  This also helped me get the fonts produced closer to what
X   troff expected them to be.  The vertical displacement can be negative
X   if desired.
X
XAspect ratio:
X
X   By default, all characters are rasterized with an aspect ratio of 1.
X   The aspect ratio is a fraction:  the horizontal amplification divided by
X   the vertical amplification.  Since this program is rasterizing a vector
X   fonts, one can play such games with the co-ordinates during
X   rasterization.  An aspect ratio of 1 is normal (and, thus, the
X   default).  An aspect ratio of .8 will stretch characters vertically,
X   and a ratio of 1.2 will stretch them horizontally.  Again, this option
X   was deemed desirable for our applications at Rice.  I noticed that one
X   of the primary differences between the Hershey duplex Roman font and a
X   standard Times Roman font was that all the lower case Hershey
X   characters looked like someone had stepped on them.  So, I played a
X   little with varying aspect ratios and decided that a ratio of 0.8 for
X   just the lower case characters came very close to the Times Roman font
X   (I used the original AT&T troff documentation as a sample of a Times
X   Roman font).  A standard aspect ratio can be defined for the whole font
X   by using the "aspect" keyword at the front of the description, and
X   individual ratios can be specified for each character as described above.
X
XAgain, examples of descriptor files are included in this distribution.
XThey have a suffix of ".spec".  There is one for three of the four standard
Xtroff fonts:  R, I, and B.  They should give you some good examples.  The
Xspecial font (S) had a specially hand-crafted repertory file that
Xcontained different character specifications for things like the bracket
Xbuilding characters.  If you are interested in this special repertory send
Xme mail and I can arrange to have it sent to you, provided you have
Xalready obtained the original Hershey repertory on tape (this requires
Xsigning a license agreement with NTIS, and some of the characters in this
Xspecial repertory are straight from the original Hershey).
X
XA word about resolution:
X
XAs distributed, this program is set up to build 300 dpi fonts.  It should
Xbe very easy to change this for other resolutions, but I haven't given much
Xthought to how this would be done.  I suspect that it is as easy as
Xchanging the preprocessor constant "PT_Scale" to a different value.
X
XI am also sending a file called extra.occ, which contains some extra
Xcharacters defined in hershey format.  The descriptor files reference
Xthese characters.  They are all the characters I needed for the three
Xtroff fonts but couldn't find reasonable equivalents for in the original
XHershey font.  If you want to run hfont with the descriptor files I am
Xincluding, then you will either have to add these characters to your
XHershey repertory (maintaining the ascending order), or remove the extra
Xdefinitions from the descriptor files.
X
XFinally, there is a program called "vsc" (for Vfont Snarf Character),
Xwhich helps you peruse a vfont file.  Give it the name of a vfont file as
Xan argument, then it will print out the information in the font header
Xarea.  Type a character followed by a return and it will print out, first,
Xthe contents of the character dispatch, and then the raster image (in a
Xvisible manner).
X
XA warning about Sun fonts:  the fonts used by the Sun workstation for
XSuntools are not quite standard vfont format.  The bitmaps are padded out
Xto a short word boundary rather than a byte boundary.  The fonts that this
Xprogram produces will not work as Suntools fonts.  However, changing vfont
Xso that it does produce the right format should be easy.
X
XI hope you find this useful.  I'm not really using this program much
Xanymore, since the project I wrote it for fell through.  You are welcome
Xto use it as you want, but please credit me as the original author (unless
Xyou almost completely rewrite it).  I hate to say it, but I'm not really
Xall that interested in bug fixes and small enhancements.  If you are
Xhaving problems trying to track down a bug, I will lend what assistance I
Xcan.  If you add something that you think is just really spectacular, drop
Xme a line.  I'll be more interested in brief sketches than actual diffs.
XEssentially, this is an "as is" free piece of software.
X
X                        William LeFebvre
X                        Department of Computer Science
X                        Rice University
X                        <phil@Rice.edu>
/
echo 'Extracting Makefile...'
sed 's/^X//' > Makefile << '/'
X# Makefile for "hfont"; a program to rasterize Hershey font characters
X#
X# Written by William LeFebvre, Computer Science Department, Rice University
X
XFILES = README Makefile hfont.c painter.c vsc.c painter.h extra.occ \
X	pen.round R.spec I.spec B.spec
X
Xall: hfont vsc
X
Xhfont: hfont.o painter.o
X	cc $(CFLAGS) -o hfont hfont.o painter.o
X
Xvsc: vsc.o
X	cc $(CFLAGS) -o vsc vsc.o
X
Xpainter.o: painter.c painter.h
Xhfont.o: hfont.c painter.h
X
Xclean:
X	rm -f hfont.o painter.o vsc.o hfont vsc core
X
Xshar:
X	rm -f hfont.shar
X	packmail 1000000 hfont.shar $(FILES)
/
echo 'Extracting hfont.c...'
sed 's/^X//' > hfont.c << '/'
X/*
X *  hfont - build a vfont raster file from a hershey format vector file
X *
X *  Written by William LeFebvre, LCSE, Rice University
X */
X
X# include <sys/types.h>
X# include <vfont.h>
X# include "painter.h"
X
X# define  No	0
X# define  Yes	1
X
X# define  MAX_CHARS	256		/* number of chars in a vfont file */
X# define  Headersize	(sizeof(struct header) + sizeof(struct dispatch) * MAX_CHARS)
X
X# define  PT_Scale	.14		/* scaling factor for point sizes */
X# define  Base_scale	10.0		/* scaling factor for baseline */
X
Xchar   bitmap[Max_x][Max_y];
Xchar   input[256];
Xunsigned char filebuff[Max_x*(Max_y/8)];
Xunsigned char *fbufp;
Xdouble left_extent, right_extent;
Xint    left_max, right_max;
Xint    up_max, down_max;
Xint    vtrans;
Xdouble x_factor = 1.4;
Xdouble y_factor = 1.4;
Xdouble real_x_factor;
Xdouble x_trans;
Xdouble translate_x();
XFILE   *vecfont;
X
Xint  left_ex;
Xint  map_to_char;
Xint  vfont;
Xint  baseline;
Xint  hi_char = 168;
X
Xchar verbose = No;
X
Xchar *gets();
Xchar *vgets();
Xchar *index();
Xchar *process_option();
X
Xstruct header v_header;
Xstruct dispatch v_character[256];
X
Xmain(argc, argv)
X
Xint  argc;
Xchar *argv[];
X
X{
X    int i;
X    int j;
X    int arg;
X    int bytecnt;
X    int pt_size = 0;
X    int char_num;
X    int space_char;
X    int filesize;
X    unsigned char bytemask;
X    unsigned char byte;
X    char *inp;
X    char *p;
X    static char repertory[256] = "occidental";
X    static char pen_file[256] = "pen.round";
X    static char buff[256];
X    struct dispatch *character;
X
X    /* get optional arguments */
X
X    for (arg = 1; ((arg < argc) && (argv[arg][0] == '-')); arg++)
X    {
X	switch (argv[arg][1])
X	{
X	    case 'p':		/* point size */
X		pt_size = atoi(&argv[arg][2]);
X		strcpy(buff, &argv[arg][2]);
X		set_factor((double)pt_size * PT_Scale);
X		break;
X
X	    case 's':		/* scale factor */
X		sscanf(&argv[arg][2], "%F", &x_factor);
X		set_factor(x_factor);
X		break;
X
X	    case 'v':		/* verbose */
X		verbose = Yes;
X		break;
X
X	    default:
X		fprintf(stderr, "Illegal option `%s'\n", argv[arg]);
X		exit(1);
X	}
X    }
X    if (arg+1 > argc )
X    {
X	fprintf(stderr, "usage: hfont [-pn] [-sn] fontfile\n");
X	exit(1);
X    }
X
X    /* read options from stdin */
X
X    while (vgets(input) != NULL && strcmp(input, "charset") != 0)
X    {
X	/* get the option name */
X	if ((p = index(input, ' ')) != 0)
X	{
X	    *p = '\0';
X	}
X	while (*(++p) == ' ');
X
X	/* string switch on option names */
X	if (strcmp(input, "repertory") == 0)
X	{
X	    strcpy(repertory, p);
X	}
X	else if (strcmp(input, "maxchar") == 0)
X	{
X	    hi_char = atoi(p);
X	}
X	else if (strcmp(input, "pen") == 0)
X	{
X	    strcpy(pen_file, p);
X	}
X	else if (strcmp(input, "aspect") == 0)
X	{
X	    x_factor *= atof(p);
X	}
X	else
X	{
X	    fprintf(stderr, "Unknown option: `%s'\n", input);
X	    exit(1);
X	}
X    }
X
X    /* open the font files */
X    if ((vecfont = fopen(repertory, "r")) == NULL)
X    {
X	perror(repertory);
X	exit(1);
X    }
X    if ((vfont = creat(argv[arg], 0666)) == -1)
X    {
X	perror(argv[arg]);
X	exit(1);
X    }
X
X    /* read in the pens */
X    if ((i = read_pens(pen_file, pt_size)) < 0)
X    {
X	if (i == -1)
X	{
X	    perror("Pen file");
X	}
X	else
X	{
X	    fprintf(stderr, "Pen file: couldn't find pen for %d point\n",
X		pt_size);
X	}
X	exit(1);
X    }
X
X    /* leave space for the header, character descriptors, and space bitmap */
X    lseek(vfont, Headersize + 2, 0);
X    filesize = 2;
X
X    /* remember what the real x factor is */
X
X    real_x_factor = x_factor;
X
X    /* translate the characters */
X
X    while(vgets(input) != NULL)
X    {
X	/* get the character desired */
X
X	space_char = char_num = 0;
X	if (input[0] == 's')
X	{
X	    /* space character of specified width */
X	    space_char = atoi(&(input[1]));
X	}
X	else if (input[0] == 'p')
X	{
X	    /* image of the drawing pen */
X	    char_num = -1;
X	}
X	else
X	{
X	    /* normal vector character */
X	    char_num = atoi(input);
X	}
X
X	/* find the font character to use */
X
X	if ((inp = index(input, ',')) == 0)
X	{
X	    fprintf(stderr, "bad character designation in `%s'\n",
X		input);
X	    break;
X	}
X	if ((inp[1] == '\\') && (inp[2] != '\0'))
X	{
X	    /* octal format */
X	    sscanf(&(inp[2]), "%o", &map_to_char);
X	}
X	else
X	{
X	    /* character format */
X	    map_to_char = inp[1];
X	}
X
X	/* check for extra options */
X
X	vtrans = 0;
X	inp += 2;
X	if ((inp = process_option(inp)) != 0)
X	{
X	    process_option(inp);
X	}
X
X	/* get a pointer to the character descriptor */
X
X	character = &(v_character[map_to_char]);
X
X	/* find the character in the Hershey font */
X
X	if (space_char != 0)
X	{
X	    /* this is a special width space character */
X	    character->nbytes = 2;
X	    character->addr = 0;
X	    character->up = character->down =
X		character->left = character->right = 0;
X	    character->width = space_char;
X	}
X	else
X	{
X	    /* normal hershey character */
X	    /* clear the bitmap */
X	    bzero(bitmap, sizeof(bitmap));
X
X	    if (char_num == -1)
X	    {
X		/* paint just one blotch of the pen at the center */
X		reset_painter();
X		paint(0, baseline - Y_center, 0, 0, 2);
X	    }
X	    else
X	    {
X		/* find and paint a vector character */
X		if (find_num(char_num) != 0)
X		{
X		    fprintf(stderr, "character %d not found\n", char_num);
X		    break;
X		}
X    
X		/* paint the character */
X		paint_char(vtrans);
X	    }
X
X	    /* get integer left extent */
X	    left_ex = (int)(left_extent - 0.5) + X_center;
X
X	    /* fill in the character descriptor */
X	    character->width =
X		(int)(right_extent - left_extent + 0.5);
X
X	    character->down   = down_max - baseline;
X	    character->up     = baseline - up_max;
X	    character->left   = left_ex - left_max;
X	    character->right  = right_max - left_ex + 1;
X	    character->addr   = filesize;
X	    character->nbytes = bytecnt = ((right_max - left_max + 8) >> 3) *
X				    (down_max - up_max);
X
X	    /* write the bitmap --- this is a problem */
X	    fbufp = filebuff;
X	    for (i = up_max; i <= down_max; i++)
X	    {
X		for (j = left_max; j <= right_max; )
X		{
X		    byte = 0;
X		    for (bytemask=0x80; bytemask != 0; (bytemask >>= 1, j++))
X		    {
X			byte |= (bitmap[j][i] ? bytemask : 0);
X		    }
X		    *fbufp++ = byte;
X		}
X	    }
X	    write(vfont, filebuff, bytecnt);
X	    filesize += bytecnt;
X
X	}
X
X	/* restore x factor */
X	x_factor = real_x_factor;
X    }
X
X    /* write the font header with the real file size */
X    v_header.size = filesize;
X    v_header.magic = 0436;
X    v_header.maxx = v_header.maxy = v_header.xtend = 0;
X    lseek(vfont, 0, 0);
X    write(vfont, &v_header, sizeof(v_header));
X
X    /* write the character dispatch area */
X    write(vfont, v_character, sizeof(v_character));
X
X    close(vfont);
X}
X
X/*
X *  set_factor - set a new scaling factor (and all things associated with it)
X */
X
Xset_factor(factor)
X
Xdouble factor;
X
X{
X    y_factor = x_factor = factor;
X    baseline = (int)(Base_scale * factor + 0.5) + Y_center;
X    if (verbose)
X    {
X	fprintf(stderr, "scaling factor = %f, baseline = %d\n",
X	    y_factor, baseline);
X    }
X}
X
X/*
X *  process_option(ptr) - process possible line option pointed to by ptr.
X */
X
Xchar *process_option(ptr)
X
Xchar *ptr;
X
X{
X    if ((ptr = index(ptr, ',')) != 0)
X    {
X	ptr++;
X	if (ptr[0] == 'r')
X	{
X	    /* aspect ratio */
X	    x_factor *= atof(&ptr[1]);
X	}
X	else
X	{
X	    /* assume it's vertical translation */
X	    vtrans = atoi(&(ptr[0]));
X	}
X    }
X    return(ptr);
X}
X
Xchar *vgets(buff)
X
Xregister char *buff;
X
X{
X    register char *retval;
X
X    if ((retval = gets(buff)) != NULL && verbose)
X    {
X	fprintf(stderr, "%s\n", buff);
X    }
X    return(retval);
X}
/
echo 'Extracting painter.c...'
sed 's/^X//' > painter.c << '/'
X# include "painter.h"
X
X# define  No	0
X# define  Yes	1
X
Xextern char   bitmap[Max_x][Max_y];
Xextern char   input[256];
Xextern double left_extent, right_extent;
Xextern int    left_max, right_max;
Xextern int    up_max, down_max;
Xextern double x_factor;
Xextern double y_factor;
Xextern double x_trans;
Xextern double translate_x();
Xextern FILE   *vecfont;
Xint  vtrans;
Xchar shape_area[1024];		/* holds pen shapes */
Xchar *shape_hi = shape_area;
X
Xextern int errno;
X
X/* functions that adjust int/frac pairs (referenced in paint_line) */
Xint adjust_down();
Xint adjust_up();
Xint adjust_no();
Xint (*set_adjust())();
X
X/* setup the painting pen */
X
Xstruct pen
X{
X    int  x_off;
X    int  y_off;
X    char *shape;
X}
X    pen;
X
X/* each byte in shape_area is one of: */
X
X#define    Pen_blank	0
X#define    Pen_full	3
X#define    Pen_pos	2
X#define    Pen_neg	1
X#define    Pen_eol	4
X#define    Pen_eop	12
X
X/*
X *  read_pens(filename, point) - read in the pen shapes from "filename" and
X *  				 select the pen for size "point".  If point
X *  				 is 0, just use the first pen in the file.
X */
X
Xread_pens(filename, point)
X
Xchar *filename;
Xint  point;
X
X{
X    FILE *f;
X    int x, y, xmax;
X    int found;
X    char ch;
X    char line[256];
X    char *pshape;
X
X    /* open the pen file */
X    if ((f = fopen(filename, "r")) == NULL)
X    {
X	return(-1);
X    }
X
X    /* find the right sized pen */
X    found = No;
X    while (!found)
X    {
X	if (fgets(line, sizeof(line), f) == NULL)
X	{
X	    fclose(f);
X	    return(-2);
X	}
X	if (sscanf(line, "pen %d", &x) == 1 && (x == point || point == 0))
X	{
X	    /* found it */
X	    found = Yes;
X	}
X    }
X    
X    /* get this pen */
X    /* preset extremes and such */
X    xmax = x = y = 0;
X    pen.shape = pshape = shape_hi;
X
X    /* one character at a time ... */
X    while ((ch = getc(f)) != 'p')
X    {
X	switch(ch)
X	{
X	    case EOF:
X		/* that wasn't supposed to happen */
X		fclose(f);
X		return(-2);
X
X	    case '*':
X		/* completely filled in */
X		*pshape++ = Pen_full;
X		x++;
X		break;
X
X	    case '/':
X		/* filled in only on positive slope */
X		*pshape++ = Pen_pos;
X		x++;
X		break;
X
X	    case '\\':
X		/* filled in only on negative slope */
X		*pshape++ = Pen_neg;
X		x++;
X		break;
X
X	    case '\n':
X		/* end of line */
X		*pshape++ = Pen_eol;
X		y++;
X		if (xmax < x)
X		    xmax = x;
X		x = 0;
X		break;
X
X	    default:
X		/* anything else is not filled in */
X		*pshape++ = Pen_blank;
X		x++;
X		/* break; */
X	}
X
X	/* calculate offsets */
X	pen.x_off = (xmax - 1) / 2;
X	pen.y_off = (y - 1) / 2;
X    }
X
X    /* set end of pen marker */
X    *pshape++ = Pen_eop;
X
X    /* throw away rest of delimiting line and reset high water mark */
X    fgets(line, 132, f);
X    shape_hi = pshape;
X
X    /* close and leave */
X    fclose(f);
X    return(0);
X}
X
X/*
X *  find_num(num) - scan thru the font file to find character "num"
X */
X
Xfind_num(num)
X
Xint num;
X
X{
X    static int last_char_num = 0;
X    int this_num;
X
X    /* check for special case num = 0 */
X
X    if (num == 0)
X    {
X	/* use the next one in the file */
X	if (fgets(input, 256, vecfont) == NULL)
X	    return(-1);
X	last_char_num = atoi(input);
X	fseek(vecfont, -strlen(input), 1);
X	printf("%d\n", last_char_num);
X	return(0);
X    }
X
X    /* rewind the file if the character is behind us */
X
X    if (last_char_num >= num)
X    {
X	rewind(vecfont);
X    }
X
X    /* check the first number on each line */
X
X    while(fgets(input, 256, vecfont) != NULL)
X    {
X	if ((this_num = atoi(input)) == num)
X	{
X	    /* found it -- back up over the line */
X	    fseek(vecfont, -strlen(input), 1);
X
X	    /* remember where we are and return success */
X	    last_char_num = num;
X	    return(0);
X	}
X	if (this_num > num)
X	{
X	    /* we have gone past it -- it doesn't exist */
X	    /* remember where we are and return failure */
X	    last_char_num = this_num;
X	    return(-1);
X	}
X    }
X    /* off the end of the file */
X    /* remember this and return failure */
X    last_char_num = 32000;
X    return(-1);
X}
X
X/*
X *  paint_char() - paint the character where vecfont is positioned
X */
X
Xpaint_char(vtr)
X
Xint vtr;		/* vertical translation */
X
X{
X    double x, y;
X    double new_x, new_y;
X    int ret;
X    int i, j;
X
X    /* set vertical translation */
X
X    vtrans = vtr;
X
X    /* get the extents of the character */
X    move_to_colon();
X    get_pair(&i, &j);
X
X    /* calculate translation factors and translate extents */
X
X    x_trans      = -((double)i + (double)j) / 2.;
X    left_extent  = translate_x(i);
X    right_extent = translate_x(j);
X    
X    /* reset the painting process */
X    reset_painter();
X
X    /* grab succesive pairs and paint lines between them */
X    get_adj_pair(&x, &y);
X    while ((ret = get_adj_pair(&new_x, &new_y)) != -1)
X    {
X	if (ret == 1)
X	{
X	    /* pen up */
X	    get_adj_pair(&x, &y);
X	}
X	else
X	{
X	    paint_line(x, y, new_x, new_y);
X	    x = new_x;
X	    y = new_y;
X	}
X    }
X}
X
Xreset_painter()
X
X{
X    left_max = right_max = X_center;
X    up_max   = down_max  = Y_center;
X}
X
X/*
X *  get_pair(px, py) - get a pair of numbers from vecfont
X */
X
Xget_pair(px, py)
X
Xint *px;
Xint *py;
X
X{
X    char ch;
X
X    if ((ch = getc(vecfont)) == '\n')
X    {
X	move_to_colon();
X    }
X    else
X    {
X	ungetc(ch, vecfont);
X    }
X    fscanf(vecfont, "%d %d", px, py);
X    move_to_colon();
X    if (*px != -64)
X	return(0);
X
X    if (*py == 0)
X	return(1);
X
X    while(getc(vecfont) != '\n')
X	/* read */;
X
X    return(-1);
X}
X
X/*
X *  get_adj_pair(px, py) - get an adjusted pair of numbers
X */
X
Xget_adj_pair(px, py)
X
Xdouble *px;
Xdouble *py;
X
X{
X    int ret;
X    int x, y;
X
X    if ((ret = get_pair(&x, &y)) == 0)
X    {
X	*px = translate_x(x);
X	*py = ((double)(y + vtrans) * y_factor);
X    }
X    return(ret);
X}
X
Xdouble translate_x(x)
X
Xint x;
X
X{
X    return(((double)x + x_trans) * x_factor);
X}
X
X/*
X *  move_to_colon() - move to the next colon in vecfont
X */
X
Xmove_to_colon()
X
X{
X    while(getc(vecfont) != ':')
X	/* keep going */;
X
X    return;
X}
X
X/*
X *  paint_line - paints a line from one point to another, based on
X *		 a symmetric DDA algorithm
X */
X
Xpaint_line(x1, y1, x2, y2)
X
Xdouble x1;
Xdouble y1;
Xdouble x2;
Xdouble y2;
X
X{
X    double diff_x2_x1;
X    double diff_y2_y1;
X    double x;
X    double y;
X    double x_frac;
X    double y_frac;
X    double x_inc;
X    double y_inc;
X    double epsilon = 0.0078125;	/* 2 ^ -7 */
X    int i;
X    int x_int;
X    int y_int;
X    int slope;
X    int (*x_adjust)();
X    int (*y_adjust)();
X    register int xchange;
X    register int ychange;
X
X#ifdef DEBUG
X    fprintf(stderr, "painting a line from %f,%f to %f,%f\n", x1, y1, x2, y2);
X#endif
X    
X#ifdef notdef
X    /* for now, make sure we travel in a negative y direction */
X    if (y1 < y2)
X    {
X	x  = x1;
X	x1 = x2;
X	x2 = x;
X	y  = y1;
X	y1 = y2;
X	y2 = y;
X    }
X# endif
X
X    x = x1;
X    y = y1;
X
X    /* separaate x and y into integer and fraction */
X    x_frac = x - (double)(x_int = (int)x);
X    y_frac = y - (double)(y_int = (int)y);
X
X    /* determine differences and increments */
X    x_inc = (diff_x2_x1 = x2 - x1) * epsilon;
X    y_inc = (diff_y2_y1 = y2 - y1) * epsilon;
X
X    /*
X     *  set the "adjust" routine pointers to appropriate values, and insure
X     *	that the frac values are in the correct range: (-1, 0] going
X     *	downward and [0, 1) going upward.
X     */
X    x_adjust = set_adjust(&x_int, &x_frac, diff_x2_x1);
X    y_adjust = set_adjust(&y_int, &y_frac, diff_y2_y1);
X#ifdef DEBUG
X    fprintf(stderr, "after adjust: x = %d + %e, y = %d + %e\n",
X	x_int, x_frac, y_int, y_frac);
X#endif
X
X    /* calculate the line slope */
X    slope = sign(diff_x2_x1) == sign(diff_y2_y1) ? Pen_pos : Pen_neg;
X
X    /* paint the first pixel */
X    paint(x_int, y_int, 1, 1, slope);
X
X#ifdef DEBUG
X    fprintf(stderr, "x_inc = %e, y_inc = %e\n", x_inc, y_inc);
X#endif
X    for (i=0; i < 128; i++)
X    {
X	x_frac += x_inc;
X	y_frac += y_inc;
X	xchange = (*x_adjust)(&x_int, &x_frac);
X	ychange = (*y_adjust)(&y_int, &y_frac);
X	if (xchange || ychange)
X	{
X#ifdef DEBUG
X	    fprintf(stderr, "change (%c%c): x = %d + %f, y = %d + %f\n",
X		xchange ? 'x' : ' ', ychange ? 'y' : ' ',
X		x_int, x_frac, y_int, y_frac);
X#endif
X	    paint(x_int, y_int, (x_frac < 0.5), (y_frac < 0.5), slope);
X	}
X    }
X}
X
X/*
X *  int/frac pair adjusting routines.  These routines all have the form:
X *
X *  adjust_xx(int_part, frac_part) - adjust integer / fraction pair, return
X *				     Yes if adjustment was necessary, o/w No
X *
X *  The names are as follows:
X *	adjust_down() - adjust for a pair that is being decremented
X *	adjust_up()   - adjust for a pair that is being incremented
X *      adjust_no()   - never adjust (for a pair that never changes)
X */
X
Xadjust_down(int_part, frac_part)
X
Xint    *int_part;
Xdouble *frac_part;
X
X{
X    if (*frac_part <= -0.5)
X    {
X	if (*frac_part < -1.5)
X	{
X	    fprintf(stderr, "symmetric DDA jump %d (< -1)\n",
X		    (int)*frac_part);
X	}
X	(*int_part)--;
X	*frac_part += 1.;
X#ifdef DEBUG
X	fprintf(stderr, "adjust got downward change: ");
X#endif
X	return(Yes);
X    }
X    return(No);
X}
X
Xadjust_up(int_part, frac_part)
X
Xint    *int_part;
Xdouble *frac_part;
X
X{
X    if (*frac_part >= 0.5)
X    {
X	if (*frac_part > 1.5)
X	{
X	    fprintf(stderr, "symmetric DDA jump %d (> 1)\n",
X		    (int)*frac_part);
X	}
X	(*int_part)++;
X	*frac_part -= 1.;
X#ifdef DEBUG
X	fprintf(stderr, "adjust got upward change: ");
X#endif
X	return(Yes);
X    }
X    return(No);
X}
X
Xadjust_no(int_part, frac_part)
X
Xint    *int_part;
Xdouble *frac_part;
X
X{
X    return(No);
X}
X
Xint (*set_adjust(intp, fracp, direct))()
X
Xint *intp;
Xdouble *fracp;
Xdouble direct;
X
X{
X    /* frac needs to be in the range [-0.5, 0.5] */
X    if (*fracp >  0.5)
X    {
X	*fracp -= 1.0;
X	(*intp)++;
X    }
X    if (*fracp < -0.5)
X    {
X	*fracp += 1.0;
X	(*intp)--;
X    }
X    return(direct < 0.0 ? adjust_down : direct > 0.0 ? adjust_up : adjust_no);
X}
X
Xpaint(x, y, xhalf, yhalf, slope)
X
Xint x;
Xint y;
Xint xhalf;
Xint yhalf;
Xint slope;
X
X{
X    int x_low, x_hi;
X    int y_low, y_hi;
X    register int ix, iy, ixstart;
X    register char *pshape;
X
X#ifdef DEBUG
X    fprintf(stderr, "painting %d, %d\n", x, y);
X#endif
X
X    /* center the points in our bitmap */
X
X    ix = x + X_center;
X    iy = y + Y_center;
X
X    /* move bitmap pointers to upper left corner of pen */
X    ix -= pen.x_off;
X    iy -= pen.y_off;
X    ixstart = ix;
X
X    /* check maximums */
X    if (ix < left_max)
X	left_max = ix;
X    if (iy < up_max)
X	up_max = iy;
X
X    /* color in the shape of the pen */
X
X    for (pshape = pen.shape; *pshape != Pen_eop; pshape++)
X    {
X	if (*pshape == Pen_eol)
X	{
X	    if (ix > right_max)
X		right_max = ix;
X	    ix = ixstart;
X	    iy++;
X	}
X	else
X	{
X	    if (*pshape & slope)
X	    {
X		bitmap[ix][iy] = Yes;
X	    }
X	    ix++;
X	}
X    }
X
X    /* check y_down maximum */
X
X    if (iy  > down_max)
X	down_max = iy;
X
X}
X
Xsign(a)
X
Xdouble a;
X
X{
X    if (a < 0)
X	return(-1);
X    return(1);
X}
X
Xint pairound(pair_int, pair_frac)
X
Xint    pair_int;
Xdouble pair_frac;
X
X{
X    if (pair_int < 0)
X    {
X	if (pair_frac <= -0.5)
X	{
X	    pair_int--;
X	}
X    }
X    else
X    {
X	if (pair_frac >= 0.5)
X	{
X	    pair_int++;
X	}
X    }
X#ifdef DEBUG
X    fprintf(stderr, "pairound: returning %d\n", pair_int);
X#endif
X    return (pair_int);
X}
X
/
echo 'Extracting vsc.c...'
sed 's/^X//' > vsc.c << '/'
X#include <stdio.h>
X
X/*
X *  snarf a character out of a font file
X */
X
X#include <vfont.h>
X#define  Header_area_size \
X		(sizeof(struct header) + (sizeof(struct dispatch) * 256))
X
Xmain(argc, argv)
X
Xint argc;
Xchar *argv[];
X
X{
X    int ch;
X    int fd;
X    unsigned char byte;
X    int i,j;
X    int raster_size;
X    int curr;
X    int rotated = 0;
X    struct dispatch dispatch;
X    struct header header;
X
X    if (argc < 2)
X    {
X	printf("Give me a file, bozo!\n");
X	exit(1);
X    }
X    if ((fd = open(argv[1], 0)) == -1)
X    {
X	printf("Can't open it\n");
X	exit(1);
X    }
X
X    /* check for rotation */
X    if (argv[1][strlen(argv[1]) - 1] == 'r')
X    {
X	rotated = 1;
X    }
X
X    read(fd, &header, sizeof(header));
X    printf("header.magic = %d (0x%x)\n", header.magic, header.magic);
X    printf("header.size  = %d (0x%x)\n", header.size, header.size);
X    printf("header.maxx  = %d (0x%x)\n", header.maxx, header.maxx);
X    printf("header.maxy  = %d (0x%x)\n", header.maxy, header.maxy);
X    printf("header.xtend = %d (0x%x)\n\n", header.xtend, header.xtend);
X
X    while((ch = getchar()) != EOF)
X    {
X	lseek(fd, (ch * sizeof(struct dispatch)) + sizeof(struct header), 0);
X	read(fd, &dispatch, sizeof(dispatch));
X    
X	if (dispatch.nbytes == 0)
X	{
X	    printf("Character undefined\n");
X	}
X	else
X	{
X	    printf("dispatch.addr   = %d (0x%x)\n",
X			dispatch.addr, dispatch.addr);
X	    printf("dispatch.nbytes = %d (0x%x)\n",
X			dispatch.nbytes, dispatch.nbytes);
X	    printf("dispatch.up     = %d (0x%x)\n",
X			dispatch.up, dispatch.up);
X	    printf("dispatch.down   = %d (0x%x)\n",
X			dispatch.down, dispatch.down);
X	    printf("dispatch.left   = %d (0x%x)\n",
X			dispatch.left, dispatch.left);
X	    printf("dispatch.right  = %d (0x%x)\n",
X			dispatch.right, dispatch.right);
X	    printf("dispatch.width  = %d (0x%x)\n",
X			dispatch.width, dispatch.width);
X	    if (rotated)
X	    {
X		raster_size = (dispatch.up + dispatch.down + 7) / 8;
X	    }
X	    else
X	    {
X		raster_size = (dispatch.left + dispatch.right + 7) / 8;
X	    }
X	    printf("raster size     = %d\n", raster_size);
X
X	    lseek(fd, dispatch.addr + Header_area_size, 0);
X	    curr = 0;
X	    for(j=0; j<dispatch.nbytes; j++)
X	    {
X		read(fd, &byte, 1);
X		if (curr++ == raster_size)
X		{
X		    curr = 1;
X		    putchar('\n');
X		}
X		for(i=0; i<8; i++)
X		{
X		    if (byte & 0x80)
X			putchar('@');
X		    else
X			putchar(' ');
X		    byte <<= 1;
X		}
X	    }
X	}
X	getchar();	/* ignore newline */
X	putchar('\n');
X    }
X}
/
echo 'Extracting painter.h...'
sed 's/^X//' > painter.h << '/'
X# include <math.h>
X# include <stdio.h>
X
X# define  Max_x 400
X# define  Max_y 400
X# define  X_center 200
X# define  Y_center 200
X
X# define  Off   0
X# define  On	1
X
/
echo 'Extracting extra.occ...'
sed 's/^X//' > extra.occ << '/'
X  848  :-11  11:-11  14: 11  14:-64 -64:
X  910  :-10  10:-10 -10: 10 -10: 10  10:-10  10:-10 -10:-64 -64:
X  911  :-10  10:-10 -10: 10 -10: 10  10:-10  10:-10 -10:-64   0: -9  -9: -9   9: -8   9: -8  -9: -7  -9: -7   9: -6   9: -6  -9:
X       : -5  -9: -5   9: -4   9: -4  -9: -3  -9: -3   9: -2   9: -2  -9: -1  -9: -1   9:  0   9:  0  -9:  1  -9:  1   9:  2   9:
X       :  2  -9:  3  -9:  3   9:  4   9:  4  -9:  5  -9:  5   9:  6   9:  6  -9:  7  -9:  7   9:  8   9:  8  -9:  9  -9:  9   9:
X       :-64 -64:
X  913  : -7   7: -1  -7: -4  -6: -6  -4: -7  -1: -7   1: -6   4: -4   6: -1   7:  1   7:  4   6:  6   4:  7   1:  7  -1:  6  -4:
X       :  4  -6:  1  -7: -1  -7:-64   0: -4  -6:  4  -6:-64   0: -5  -5:  5  -5:-64   0: -6  -4:  6  -4:-64   0: -6  -2:  6  -2:
X       :-64   0: -7  -1:  7  -1:-64   0: -7   1:  7   1:-64   0: -6   2:  6   2:-64   0: -6   4:  6   4:-64   0: -5   5:  5   5:
X       :-64   0: -4   6:  4   6:-64 -64:
X  914  :-11  11: -2 -11: -5 -10: -8  -8:-10  -5:-11  -2:-11   2:-10   5: -8   8: -5  10: -2  11:  2  11:  5  10:  8   8: 10   5:
X       : 11   2: 11  -2: 10  -5:  8  -8:  5 -10:  2 -11: -2 -11:-64   0: 11 -11:-11  11:-64 -64:
X  990  :-10  10: -6   7:  0  -7:  6   7:-64 -64:
X  991  :-10  10: -6  -7:  0   7:  6  -7:-64 -64:
X  992  :-23  23:-14  -3: 14  -3:-64   0:-14   3: 14   3:-64   0: -4  -9:-20   0: -4   9:-64   0:  4  -9: 20   0:  4   9:-64 -64:
X  993  :-23  23:-14  -3: 14  -3:-64   0:-14   3: 14   3:-64   0:  4  -9: 20   0:  4   9:-64 -64:
X 2296  :-11  11: -2 -11: -5 -10: -8  -8:-10  -5:-11  -2:-11   2:-10   5: -8   8: -5  10: -2  11:  2  11:  5  10:  8   8: 10   5:
X       : 11   2: 11  -2: 10  -5:  8  -8:  5 -10:  2 -11: -2 -11:-64   0:  4  -4:  2  -5:  0  -5: -2  -4: -3  -2: -3   1: -2   3:
X       :  0   4:  2   4:  4   3:-64 -64:
X 2297  :-11  11: -2 -11: -5 -10: -8  -8:-10  -5:-11  -2:-11   2:-10   5: -8   8: -5  10: -2  11:  2  11:  5  10:  8   8: 10   5:
X       : 11   2: 11  -2: 10  -5:  8  -8:  5 -10:  2 -11: -2 -11:-64   0: -3  -5: -3   4:-64   0: -3  -5:  1  -5:  3  -4:  3  -1:
X       :  1   0: -3   0:-64   0:  0   0:  3   4:-64 -64:
X 2298  :-12  12:  8  -8:  1  -8: -3  -7: -5  -6: -7  -4: -8  -1: -8   1: -7   4: -5   6: -3   7:  1   8:  8   8:-64   0: 8   13:
X       :-8   13:-64 -64:
X 2299  :-12  12: -8  -8: -1  -8:  3  -7:  5  -6:  7  -4:  8  -1:  8   1:  7   4:  5   6:  3   7: -1   8: -8   8:-64   0: 8   13:
X       :-8   13:-64 -64:
/
echo 'Extracting pen.round...'
sed 's/^X//' > pen.round << '/'
Xpen 6
X *
X***
X *
Xpen 7
X *
X***
X *
Xpen 8
X *
X***
X *
Xpen 9
X *
X***
X *
Xpen 10
X * 
X***
X * 
Xpen 11
X *
X***
X *
Xpen 12
X *
X***
X *
Xpen 14
X **
X****
X****
X **
Xpen 16
X  *
X ***
X*****
X ***
X  *
Xpen 18
X  *
X ***
X*****
X ***
X  *
Xpen 20
X  **
X ****
X******
X******
X ****
X  **
Xpen 22
X   *
X *****
X ***** 
X*******
X *****
X *****
X   *  
Xpen 24
X  **
X ****
X******
X******
X ****
X  **
Xpen 28
X   **
X ******
X ******
X********
X********
X ******
X ******
X   **
Xpen 36
X     *     
X   *****   
X   *****   
X ********* 
X ********* 
X***********
X ********* 
X ********* 
X   *****   
X   *****   
X     *     
Xpenend
/
echo 'Extracting R.spec...'
sed 's/^X//' > R.spec << '/'
Xcharset
Xp,\240
Xs30, 
X224,-
X804,\
X848,_
X848,\205,-3
X848,\206,-14
X910,\210
X913,\207
X2001,A
X2002,B
X2003,C
X2004,D
X2005,E
X2006,F
X2007,G
X2008,H
X2009,I
X2010,J
X2011,K
X2012,L
X2013,M
X2014,N
X2015,O
X2016,P
X2017,Q
X2018,R
X2019,S
X2020,T
X2021,U
X2022,V
X2023,W
X2024,X
X2025,Y
X2026,Z
X2101,a,r.8
X2102,b,r.8
X2103,c,r.8
X2104,d,r.8
X2105,e,r.8
X2106,f,r.8
X2107,g,r.8
X2108,h,r.8
X2109,i,r.8
X2110,j,r.8
X2111,k,r.8
X2112,l,r.8
X2113,m,r.8
X2114,n,r.8
X2115,o,r.8
X2116,p,r.8
X2117,q,r.8
X2118,r,r.8
X2119,s,r.8
X2120,t,r.8
X2121,u,r.8
X2122,v,r.8
X2123,w,r.8
X2124,x,r.8
X2125,y,r.8
X2126,z,r.8
X2177,\203,r.8
X2178,\201,r.8
X2179,\202,r.8
X2180,\211,r.8
X2181,\212,r.8
X2200,0,r.8
X2201,1,r.8
X2202,2,r.8
X2203,3,r.8
X2204,4,r.8
X2205,5,r.8
X2206,6,r.8
X2207,7,r.8
X2208,8,r.8
X2209,9,r.8
X2210,.
X2211,,
X2212,:
X2213,;
X2214,!
X2215,?
X2216,\215
X2217,"
X2218,\213
X2219,*
X2220,/
X2221,(
X2222,)
X2223,[
X2224,]
X2225,{
X2226,}
X2229,|
X2231,\204
X2232,+
X2238,=
X2241,<
X2242,>
X2246,~
X2247,^
X2251,'
X2252,`
X2271,%
X2272,&
X2273,@
X2274,$
X2275,#
X2277,\214
X2296,\216
X2297,\217
/
echo 'Extracting I.spec...'
sed 's/^X//' > I.spec << '/'
Xaspect 0.8
Xcharset
Xp,\240
Xs30, 
X224,-
X800,\206
X804,\
X848,_
X848,\205,-3
X910,\210
X913,\207
X2051,A
X2052,B
X2053,C
X2054,D
X2055,E
X2056,F
X2057,G
X2058,H
X2059,I
X2060,J
X2061,K
X2062,L
X2063,M
X2064,N
X2065,O
X2066,P
X2067,Q
X2068,R
X2069,S
X2070,T
X2071,U
X2072,V
X2073,W
X2074,X
X2075,Y
X2076,Z
X2151,a
X2152,b
X2153,c
X2154,d
X2155,e
X2156,f
X2157,g
X2158,h
X2159,i
X2160,j
X2161,k
X2162,l
X2163,m
X2164,n
X2165,o
X2166,p
X2167,q
X2168,r
X2169,s
X2170,t
X2171,u
X2172,v
X2173,w
X2174,x
X2175,y
X2176,z
X2191,\203
X2192,\201
X2193,\202
X2194,\211
X2195,\212
X2217,"
X2219,*
X2223,[
X2224,]
X2225,{
X2226,}
X2229,|
X2231,\204
X2232,+
X2238,=
X2241,<
X2242,>
X2246,~
X2247,^
X2271,%
X2273,@
X2275,#
X2750,0
X2751,1
X2752,2
X2753,3
X2754,4
X2755,5
X2756,6
X2757,7
X2758,8
X2759,9
X2760,.
X2761,,
X2762,:
X2763,;
X2764,!
X2765,?
X2766,`
X2767,'
X2768,&
X2769,$
X2770,/
X2771,(
X2772,)
/
echo 'Extracting B.spec...'
sed 's/^X//' > B.spec << '/'
Xcharset
Xp,\240
Xs30, 
X224,-
X800,\206
X804,\
X848,_
X848,\205,-3
X911,\210
X913,\207
X2177,\203,r.8
X2178,\201,r.8
X2179,\202,r.8
X2180,\211,r.8
X2181,\212,r.8
X2225,{
X2226,}
X2229,|
X2241,<
X2242,>
X2246,~
X2247,^
X2271,%
X2273,@
X2275,#
X3001,A
X3002,B
X3003,C
X3004,D
X3005,E
X3006,F
X3007,G
X3008,H
X3009,I
X3010,J
X3011,K
X3012,L
X3013,M
X3014,N
X3015,O
X3016,P
X3017,Q
X3018,R
X3019,S
X3020,T
X3021,U
X3022,V
X3023,W
X3024,X
X3025,Y
X3026,Z
X3101,a,r.8
X3102,b,r.8
X3103,c,r.8
X3104,d,r.8
X3105,e,r.8
X3106,f,r.8
X3107,g,r.8
X3108,h,r.8
X3109,i,r.8
X3110,j,r.8
X3111,k,r.8
X3112,l,r.8
X3113,m,r.8
X3114,n,r.8
X3115,o,r.8
X3116,p,r.8
X3117,q,r.8
X3118,r,r.8
X3119,s,r.8
X3120,t,r.8
X3121,u,r.8
X3122,v,r.8
X3123,w,r.8
X3124,x,r.8
X3125,y,r.8
X3126,z,r.8
X3200,0,r.8
X3201,1,r.8
X3202,2,r.8
X3203,3,r.8
X3204,4,r.8
X3205,5,r.8
X3206,6,r.8
X3207,7,r.8
X3208,8,r.8
X3209,9,r.8
X3210,.
X3211,,
X3212,:
X3213,;
X3214,!
X3215,?
X3216,`
X3217,'
X3218,&
X3219,$
X3220,/
X3221,(
X3222,)
X3223,*
X3224,\204
X3225,+
X3226,=
X3227,\215
X3228,"
X3229,\213
/
echo 'Distribution file hfont.shar complete.'