DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T f

⟦2ee403729⟧ TextFile

    Length: 20760 (0x5118)
    Types: TextFile
    Names: »fonts.c«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./DVIware/crt-viewers/others/fonts.c« 

TextFile

/*
 * dvipage: DVI Previewer Program for Suns
 *
 * Neil Hunt (hunt@spar.slb.com)
 *
 * This program is based, in part, upon the program dvisun,
 * distributed by the UnixTeX group, extensively modified by
 * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
 * of Schlumberger Technologies, Inc.
 *
 * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
 * Anyone can use this software in any manner they choose,
 * including modification and redistribution, provided they make
 * no charge for it, and these conditions remain unchanged.
 *
 * This program is distributed as is, with all faults (if any), and
 * without any warranty. No author or distributor accepts responsibility
 * to anyone for the consequences of using it, or for whether it serves any
 * particular purpose at all, or any other reason.
 *
 * $Log:	fonts.c,v $
 * Revision 1.1  88/11/28  18:40:54  hunt
 * Initial revision
 * 
 * Stripped out of dvipage 1.4,
 * with additions from mitdrivers from TeX 1988 distribution tape.
 */

#include <stdio.h>
#include <sys/param.h>		/* For MAXPATHLEN */
#include <fcntl.h>
#include <suntool/sunview.h>
#include "dvipage.h"
#include "dvi.h"

forward FILE *			open_font_file();

forward bool			init_font_file();
forward bool			read_font_char();

static int			nopen = 0;	/* number of open FNT files */

/*
 * get_font_def:
 *	Read the font definitions as they are in the postamble of the DVI file.
 *	Returns TRUE unless the document can not be processed further.
 */

bool
get_font_def()
{
	char *calloc ();
	unsigned char   byte;

	while(((byte = get_unsigned(dvifp, 1)) >= FNT_DEF1) &&
	  (byte <= FNT_DEF4))
	{
		switch (byte)
		{
		case FNT_DEF1:
			if(! read_font_def(get_unsigned(dvifp, 1)))
				return FALSE;
			break;

		case FNT_DEF2:
			if(! read_font_def(get_unsigned(dvifp, 2)))
				return FALSE;
			break;

		case FNT_DEF3:
			if(! read_font_def(get_unsigned(dvifp, 3)))
				return FALSE;
			break;

		case FNT_DEF4:
			if(! read_font_def(get_unsigned(dvifp, 4)))
				return FALSE;
			break;

		default:
			message(
  "%s: Bad dvi file: bad font specification.", filename);
			return FALSE;
		}
	}
	if(byte != POST_POST)
	{
		message(
  "%s: Bad dvi file: no postpostamble after fontdefs.", filename);
		return FALSE;
	}

	return TRUE;
}

/*
 * skip_font_def:
 *	Ignore font definition when fonts have been read from the postamble.
 */

/* ARGSUSED */
void
skip_font_def(k)
int k;
{
	int a, l;

	(void)get_unsigned(dvifp, 4);
	(void)get_unsigned(dvifp, 4);
	(void)get_unsigned(dvifp, 4);
	a = get_unsigned(dvifp, 1);
	l = get_unsigned(dvifp, 1);
	fseek(dvifp, (long)a+l, 1);
}

/*
 * read_font_def:
 *	Reads font def, and attempts to open font file and read data.
 *	Returns TRUE unless a fatal error has occurred so that
 *	document processing cannot proceed.
 */

bool
read_font_def(k)
int k;
{
	int i;
	struct char_entry *tcharptr;
	FILE *font_fp;

	/*
	 * Allocate and link new font entry.
	 */
	if((fontptr =
	  (struct font_entry *)calloc(1, sizeof(struct font_entry))) == NULL)
	{
		message(
		  "Out of memory for font entries; try a larger machine.");
		return FALSE;
	}
	fontptr->next = hfontptr;
	hfontptr = fontptr;

	/*
	 * Fill in new font entry.
	 */
	fontptr->font_file_fd = NULL;
	fontptr->k = k;
	fontptr->c = get_unsigned(dvifp, 4); /* checksum */
	fontptr->s = get_unsigned(dvifp, 4); /* space size */
	fontptr->d = get_unsigned(dvifp, 4); /* design size */
	fontptr->a = get_unsigned(dvifp, 1); /* area length for font name */
	fontptr->l = get_unsigned(dvifp, 1); /* device length */
	fread(fontptr->n, 1, fontptr->a+fontptr->l, dvifp);
	fontptr->n[fontptr->a+fontptr->l] = '\0';
	fontptr->font_space = fontptr->s/6; /* never used */
	fontptr->font_gf_mag = (int)((actual_factor((int)(((float)fontptr->s/
	  (float)fontptr->d)*1000.0 + 0.5)) *
#ifdef USEGLOBALMAG
	  actual_factor(mag) *
#endif
	  (float)resolution) + 0.5);
	fontptr->font_pxl_mag = (int)((actual_factor((int)(((float)fontptr->s/
	  (float)fontptr->d)*1000.0 + 0.5)) *
#ifdef USEGLOBALMAG
	  actual_factor(mag) *
#endif
	  (float)resolution * 5.0) + 0.5);

	/*
	 * Try to find the font file to match.
	 */
	if(! find_font_file(font_path, fontptr) ||
	  (font_fp = open_font_file(fontptr)) == NO_FILE)
	{
		message("Cant find or open font file \"%s\" .%dgf or .%dpxl",
		  fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
		if(verbose & DEBUG_FONTS)
			fprintf(stderr,
			  "Cant find font file %s %s .%dgf or .%dpxl\n",
			    font_path, fontptr->n,
			    fontptr->font_gf_mag, fontptr->font_pxl_mag);

		fontptr->font_file_fd = NO_FILE;
		fontptr->magnification = 0;
		fontptr->designsize = 0;
		for(i = 0; i < NFNTCHARS; i++)
		{
			tcharptr = &(fontptr->ch[i]);
			tcharptr->width = 0;
			tcharptr->height = 0;
			tcharptr->xOffset = 0;
			tcharptr->yOffset = 0;
			tcharptr->where.isloaded = FALSE;
			tcharptr->where.address.fileOffset = NONEXISTENT;
			tcharptr->tfmw = 0;
		}

		return TRUE;
	}
	else
		return init_font_file(font_fp, fontptr);
}

/*
 * open_font_file:
 *	Called with fontptr; opens a file for this font.
 *	May have to close another to do it.
 *	Returns a FILE * pointer, or NO_FILE.
 */

FILE *
open_font_file(fontptr)
struct font_entry *fontptr;
{
	register struct font_entry *tfontptr, *lufontptr;
	register int used;

	if(nopen >= MAXOPEN)
	{
		used = MAXINT;
		lufontptr = NULL;
		for(tfontptr = hfontptr; tfontptr; tfontptr = tfontptr->next)
		{
			if(tfontptr->font_file_fd == NO_FILE ||
			  tfontptr->font_file_fd == NULL ||
			  tfontptr == fontptr)
				continue;

			if(tfontptr->use_count < used)
			{
				used = tfontptr->use_count;
				lufontptr = tfontptr;
			}
		}

		if(lufontptr == NULL)
		{
			fprintf(stderr, "Cant have no least used font\n");
			exit(1);
		}

		if(verbose & DEBUG_FONTS)
			fprintf(stderr, "Closing (%x) font '%s'\n",
			  lufontptr->font_file_fd, lufontptr->name);
		fclose(lufontptr->font_file_fd);
		lufontptr->font_file_fd = NULL;
		--nopen;
	}

	/*
	 * Open the file; close-on-exec.
	 */
	if((fontptr->font_file_fd = fopen(fontptr->name, "r")) == NULL)
	{
		message("Cant open font file %s", fontptr->name);
		fontptr->font_file_fd = NO_FILE;
	}
	else
	{
		if(verbose & DEBUG_FONTS)
			fprintf(stderr, "Opened (%x) font '%s'\n",
			  fontptr->font_file_fd, fontptr->name);
		fcntl(fileno(fontptr->font_file_fd),  F_SETFD,  1);
		nopen++;
	}

	return fontptr->font_file_fd;
}

/*
 * close_fonts:
 *	Closes all the font files, and frees up all the memory.
 */

void
close_fonts()
{
	register struct font_entry *pf, *next;
	register struct pixrect *pr;
	register int i;

	for(pf = hfontptr; pf; pf = next)
	{
		if(verbose & DEBUG_FONTS)
			fprintf(stderr, "Freeing font %s\n", pf->name);

		/*
		 * Close the file if still open.
		 */
		if(pf->font_file_fd != NO_FILE && pf->font_file_fd != NULL)
		{
			fclose(pf->font_file_fd);
			--nopen;
		}
		pf->font_file_fd = NULL;

		/*
		 * Free the pixrects.
		 */
		for(i = 0; i < NFNTCHARS; i++)
		{
			if(pf->ch[i].where.isloaded == TRUE)
			{
				if(pr = pf->ch[i].where.address.pixrectptr)
					pr_destroy(pr);
			}
		}

		/*
		 * Get the next.
		 */
		next = pf->next;

		free(pf);
	}

	hfontptr = NULL;
	fontptr = NULL;

	if(nopen != 0)
	{
		fprintf(stderr, "Mislaid some font files; cant happen\n");
		exit(1);
	}
}

/*
 * load_char:
 *	Reads in a character from the font file.
 *	Returns TRUE unless document cannot be processed.
 */

bool
load_char(fontptr, ptr)
struct font_entry *fontptr;
struct char_entry *ptr;
{
	register FILE *font_fp;

	if(verbose & DEBUG_CHARS)
		fprintf(stderr, "Load char %d of font %s at offset %d\n",
		  (ptr - &fontptr->ch[0]), fontptr->name,
		  ptr->where.address.fileOffset);

	/*
	 * If the font file is currently unopen, then open it.
	 */
	if((font_fp = fontptr->font_file_fd) == NULL)
		font_fp = open_font_file(fontptr);

	/*
	 * If the font file is unavailable, forget it.
	 */
	if(font_fp == NO_FILE)
	{
		ptr->where.isloaded = TRUE;
		return TRUE;
	}

	/*
	 * Read the font character.
	 */
	return read_font_char(font_fp, fontptr, ptr);
}

/*
 * Generic Font reading functions.
 * ==============================
 */

forward bool		init_gf_font_file();
forward bool		init_pxl_font_file();
forward bool		read_gf_font_char();
forward bool		read_pxl_font_char();

/*
 * init_font_file:
 *	Reads general data from font file.
 *	Returns TRUE unless processing cannot continue.
 */

bool
init_font_file(font_fp, fontptr)
FILE *font_fp;
struct font_entry *fontptr;
{
	switch(fontptr->type)
	{
	case TYPE_GF:
		return init_gf_font_file(font_fp, fontptr);

	case TYPE_PXL:
		return init_pxl_font_file(font_fp, fontptr);

	default:
		fprintf(stderr, "Unknown type of font file; cant happen\n");
		exit(1);
	}
}

/*
 * read_font_char:
 *	Reads character from font file.
 *	Returns TRUE unless document cannot be processed.
 */

bool
read_font_char(font_fp, fontptr, ptr)
FILE *font_fp;
struct font_entry *fontptr;
struct char_entry *ptr;
{
	switch(fontptr->type)
	{
	case TYPE_GF:
		return read_gf_font_char(font_fp, fontptr, ptr);

	case TYPE_PXL:
		return read_pxl_font_char(font_fp, fontptr, ptr);

	default:
		fprintf(stderr, "Unknown type of font file; cant happen\n");
		exit(1);
	}
}

/*
 * GF font reading functions.
 * ==========================
 */

#define false	0
#define true	1

/* The following macros describe gf file format */

#define paint_0		0
#define last_paint	63
#define paint1		64
#define paint2		65
#define paint3		66
#define boc		67
#define boc1		68
#define eoc		69
#define skip0		70
#define skip1		71
#define skip2		72
#define skip3		73
#define new_row_0	74
#define last_new_row	238
#define xxx1		239
#define xxx2		240
#define xxx3		241
#define xxx4		242
#define yyy		243
#define no_op		244
#define char_loc	245
#define char_loc0	246
#define pre		247
#define post		248
#define postpost	249
#define undefined_cases	250: case 251: case 252: case 253: case 254: case 255
#define gf_version	131

/*
 * init_gf_font_file:
 *	Reads font data from file.
 *	If the file is unavailable, its fp is set to NO_FILE.
 *	Returns TRUE unless processing cannot continue.
 */

bool
init_gf_font_file(font_fp, fontptr)
FILE *font_fp;
struct font_entry *fontptr;
{
	register int b, c;
	register struct char_entry *tcharptr;

	long checksum;		/* should match TFM file and DVI file */
	long hppp, vppp;	/* horizontal and vertical pixels/point scaled
				 * 1<<16 */
	int font_min_m, font_max_m, font_min_n, font_max_n;
	int char_wd;		/* character width in pixels, rounded if
				 * necessary */

	/*
	 * Seek to the postamble part of the GF file.
	 */
	fseek(font_fp, -5L, 2);	/* skip four 223's */
	do
	{
		c = get_unsigned(font_fp, 1);
		fseek(font_fp, -2L, 1);
	} while(c == 223);

	if(c != gf_version)
	{
		message("Bad GF font version number (%d) in %s.",
		  c, fontptr->name);
		fclose(fontptr->font_file_fd);
		fontptr->font_file_fd = NO_FILE;
		return TRUE;
	}

	fseek(font_fp, -3L, 1);	/* back up to the pointer */
	if(fseek(font_fp, (long)get_unsigned(font_fp, 4), 0) < 0 ||
	  get_unsigned(font_fp, 1) != post)
	{
		message("Bad GF font file format in %s.", fontptr->name);
		fclose(fontptr->font_file_fd);
		fontptr->font_file_fd = NO_FILE;
		return TRUE;
	}

	(void)get_unsigned(font_fp, 4);	/* ignore back pointer to font-wide xxx
					 * commands */
	fontptr->designsize = get_unsigned(font_fp, 4);
	checksum = get_unsigned(font_fp, 4);
	hppp = get_unsigned(font_fp, 4);
	vppp = get_unsigned(font_fp, 4);
	font_min_m = get_unsigned(font_fp, 4);
	font_max_m = get_unsigned(font_fp, 4);
	font_min_n = get_unsigned(font_fp, 4);
	font_max_n = get_unsigned(font_fp, 4);

	if(verbose & DEBUG_FONTS)
		fprintf(stderr, "Initialising font %s\n", fontptr->name);

	for(tcharptr = &fontptr->ch[0]; tcharptr < &fontptr->ch[NFNTCHARS];
	  tcharptr++)
	{
		tcharptr->where.isloaded = FALSE;
		tcharptr->where.address.fileOffset = -1;
		tcharptr->tfmw = 0;
	}
	for(;;)
	{
		b = get_unsigned(font_fp, 1);
		c = get_unsigned(font_fp, 1);

		if(verbose & DEBUG_CHARS)
			fprintf(stderr, "Finding char %d type %d\n", c, b);

		if(b == char_loc0)
			char_wd = get_unsigned(font_fp, 1);
		else if(b == char_loc)
		{
			char_wd = (get_unsigned(font_fp, 4) + 0100000) >> 16;
			get_unsigned(font_fp, 4);	/* skip dy */
		}
		else
			break;

		tcharptr = &(fontptr->ch[c % NFNTCHARS]);
		tcharptr->tfmw =
		  ((float)get_unsigned(font_fp, 4) * (float)fontptr->s) /
		  (float)(1 << 20);
		tcharptr->where.address.fileOffset = get_unsigned(font_fp, 4);
	}

	if((fontptr->c != 0) && (checksum != 0) && (fontptr->c != checksum))
		message("Bad font checksum %d != %d, font %s.",
		  checksum, fontptr->c, fontptr->name);

	/*
	 * Return leaving font file open for use.
	 */
	return TRUE;
}

/*
 * read_font_char:
 *	Reads character from font file.
 *	Returns TRUE unless document cannot be processed.
 */

bool
read_gf_font_char(font_fp, fontptr, ptr)
FILE *font_fp;
struct font_entry *fontptr;
register struct char_entry *ptr;
{
	register int i, b, c;
	register int x, y;
	register struct pixrect *pr;
	int min_m, max_m, min_n, max_n;
	int bytes, lines, paint_switch;
	long backpointer;
	long charfam;

	if(verbose & DEBUG_CHARS)
		fprintf(stderr, "Reading char %d of font %s\n",
		  (ptr - &fontptr->ch[0]), fontptr->name);

	/*
	 * Seek to start of char.
	 */
	fseek(font_fp, (long)ptr->where.address.fileOffset, 0);

	/*
	 * Sync with char
	 */
	do
	{
		switch(i = get_unsigned(font_fp, 1))
		{
		case yyy:
			(void)get_unsigned(font_fp, 1);
			/* FALLTHROUGH */
		case paint3:
		case skip3:
			(void)get_unsigned(font_fp, 1);
			/* FALLTHROUGH */
		case paint2:
		case skip2:
			(void)get_unsigned(font_fp, 1);
			/* FALLTHROUGH */
		case paint1:
		case skip1:
			(void)get_unsigned(font_fp, 1);
			break;

		case boc:
		case boc1:
			break;

		case pre:
			if((c = get_unsigned(font_fp, 1)) != gf_version)
			{
				message(
				  "Bad GF font version number (%d); font %s.",
				  c, fontptr->name);
				return TRUE;
			}
			fseek(font_fp, (long)get_unsigned(font_fp, 1), 1);
			break;

		case xxx1:
			fseek(font_fp, (long)get_unsigned(font_fp, 1), 1);
			break;

		case xxx2:
			fseek(font_fp, (long)get_unsigned(font_fp, 2), 1);
			break;

		case xxx3:
			fseek(font_fp, (long)get_unsigned(font_fp, 3), 1);
			break;

		case xxx4:
			fseek(font_fp, (long)get_unsigned(font_fp, 4), 1);
			break;

		case post:
			if(verbose & DEBUG_FONTS)
				fprintf(stderr, "gettochar: found POST\n");
			return TRUE;

		case char_loc:
		case char_loc0:
		case postpost:
		case undefined_cases:
			message(
			  "Bad GF font file format (%d); font %s.",
			  i, fontptr->name);
			return TRUE;

		default: /* do nothing */ ;
			break;
		}

		if(i != boc && i != boc1 &&
		  verbose & DEBUG_FONTS)
			fprintf(stderr, "gettochar iterates with %d\n", i);
	}
	while(i != boc && i != boc1);

	/*
	 * Read character code and raster sizes.
	 */
	switch(i)
	{
	case boc:
		c = get_unsigned(font_fp, 4);
		backpointer = get_unsigned(font_fp, 4);
		min_m = get_unsigned(font_fp, 4);
		max_m = get_unsigned(font_fp, 4);
		min_n = get_unsigned(font_fp, 4);
		max_n = get_unsigned(font_fp, 4);
		charfam = c < 0 ? -((-c) >> 8) : c >> 8;
		break;

	case boc1:
		c = get_unsigned(font_fp, 1);
		x = get_unsigned(font_fp, 1);	/* del_m */
		max_m = get_unsigned(font_fp, 1);
		min_m = max_m - x;
		x = get_unsigned(font_fp, 1);	/* del_n */
		max_n = get_unsigned(font_fp, 1);
		min_n = max_n - x;
		break;

	default:
		fprintf(stderr,
		  "Font BOC code has corrupted in memory; cant happen.\n");
		exit(1);
	}
	ptr->width = max_m - min_m + 1;
	ptr->height = max_n - min_n + 1;
	ptr->xOffset = -min_m;
	ptr->yOffset = max_n;

	/*
	 * Create Pixrect for char.
	 * Clear to zero.
	 */
	pr = mem_create(ptr->width, ptr->height, 1);
	ptr->where.address.pixrectptr = pr;
	pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_SRC | PIX_COLOR(0),
	  NULL, 0, 0);
#ifdef NEVER
	pr_rop(pr, 0, 0, ptr->width, ptr->height, PIX_SRC | PIX_COLOR(1),
	  NULL, 0, 0);
	pr_rop(pr, 1, 1, ptr->width-2, ptr->height-2, PIX_SRC | PIX_COLOR(0),
	  NULL, 0, 0);
#endif NEVER
	x = 0;
	y = 0;
	paint_switch = 0;

	for(;;)
	{
		switch(b = get_unsigned(font_fp, 1))
		{
		case paint1:
			bytes = get_unsigned(font_fp, 1);
			goto paint;

		case paint2:
			bytes = get_unsigned(font_fp, 2);
			goto paint;

		case paint3:
			bytes = get_unsigned(font_fp, 3);
			goto paint;

		case skip0:
			lines = 0;
			goto skip;

		case skip1:
			lines = get_unsigned(font_fp, 1);
			goto skip;

		case skip2:
			lines = get_unsigned(font_fp, 2);
			goto skip;

		case skip3:
			lines = get_unsigned(font_fp, 3);
			goto skip;

		case xxx1:
			fseek(font_fp, (long)get_unsigned(font_fp, 1), 1);
			continue;

		case xxx2:
			fseek(font_fp, (long)get_unsigned(font_fp, 2), 1);
			continue;

		case xxx3:
			fseek(font_fp, (long)get_unsigned(font_fp, 3), 1);
			continue;

		case xxx4:
			fseek(font_fp, (long)get_unsigned(font_fp, 4), 1);
			continue;

		case yyy:
			get_unsigned(font_fp, 4);
			continue;

		case no_op:
			continue;

		case eoc:
			ptr->where.isloaded = TRUE;
			return TRUE;

		default:
			if(b >= paint_0 && b <= last_paint)
			{
				bytes = b - paint_0;

paint:;				/*
				 * Paint the specified number of bytes black
				 *	or white.
				 * Toggle the paint colour.
				 * Advance the current position.
				 */
				if(verbose & DEBUG_CHARS)
					fprintf(stderr,
  "  Paint %d line %d, %d for %d\n",  paint_switch, y, x, bytes);
				if(bytes > 0 && paint_switch)
					pr_rop(pr, x, y, bytes, 1,
					  PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
				paint_switch = ! paint_switch;
				x += bytes;
				continue;
			}
			else if(b >= new_row_0 && b <= last_new_row)
			{
				/*
				 * Special shortcut; skip to new row,
				 * and paint some white bytes.
				 * Leave switch ready for next black bytes.
				 */
				y++;
				x = b - new_row_0;
				paint_switch = 1;
				if(verbose & DEBUG_CHARS)
					fprintf(stderr,
  "  Jump to line %d, paint white to %d\n", y, x);
				continue;
			}
			else
			{
				message(
  "Bad GF file format code %d; char %d font %s.",
				  b, (ptr - &fontptr->ch[0]), fontptr->name);
				return TRUE;
			}

skip:;			/*
			 * Skip to the start of the line.th next line.
			 * Start at beginnning of line, ready to paint white.
			 */
			y += lines + 1;
			x = 0;
			paint_switch = 0;
			if(verbose & DEBUG_CHARS)
				fprintf(stderr,
  "  Jump to line %d at start\n", y);
			continue;
		}
	}
}

/*
 * PXL font reading functions.
 * ==========================
 */

#define NPXLCHARS	128

/*
 * init_pxl_font_file:
 *	Reads font data from file.
 *	If the file is unavailable, its fp is set to NO_FILE.
 *	Returns TRUE unless processing cannot continue.
 */

bool
init_pxl_font_file(font_fp, fontptr)
FILE *font_fp;
struct font_entry *fontptr;
{
	int t, i;
	register struct char_entry *tcharptr;

	/*
	 * Read the PXL file
	 */
	if((t = get_unsigned(font_fp, 4)) != PXLID)
	{
		message("Bad font file version %d; font %s.",
		  t, fontptr->name);
		fclose(fontptr->font_file_fd);
		fontptr->font_file_fd = NO_FILE;
		return TRUE;
	}
	fseek(font_fp, -20L, 2);
	t = get_unsigned(font_fp, 4);
	if((fontptr->c != 0) && (t != 0) && (fontptr->c != t))
		message("Bad font checksum %d != %d; font %s.",
		  t, fontptr->c, fontptr->name);

	fontptr->magnification = get_unsigned(font_fp, 4);
	fontptr->designsize = get_unsigned(font_fp, 4);

	fseek(font_fp, (long)get_unsigned(font_fp, 4) * 4, 0);

	for(i = 0; i < NPXLCHARS; i++)
	{
		tcharptr = &(fontptr->ch[i]);
		tcharptr->width = get_unsigned(font_fp, 2);
		tcharptr->height = get_unsigned(font_fp, 2);
		tcharptr->xOffset= get_signed(font_fp, 2);
		tcharptr->yOffset = get_signed(font_fp, 2);
		tcharptr->where.isloaded = FALSE;
		tcharptr->where.address.fileOffset =
		  get_unsigned(font_fp, 4) * 4;
		tcharptr->tfmw =
		  ((float)get_unsigned(font_fp, 4)*(float)fontptr->s) /
		  (float)(1<<20);
	}

	/*
	 * Return leaving font file open for access.
	 */
	return TRUE;
}

/*
 * read_font_char:
 *	Reads character from font file.
 *	Returns TRUE unless document cannot be processed.
 */

/* ARGSUSED */
bool
read_pxl_font_char(font_fp, fontptr, ptr)
FILE *font_fp;
struct font_entry *fontptr;
register struct char_entry *ptr;
{
	register struct pixrect *pr;
	register int nshorts, i, col, nints;
	register short *dp, *sp;
	int buf[8];

	/*
	 * Seek to start of char.
	 */
	fseek(font_fp, (long)ptr->where.address.fileOffset, 0);

	/*
	 * Create a mem pixrect.
	 * Read the char.
	 */
	pr = mem_create(ptr->width, ptr->height, 1);
	nshorts = mpr_mdlinebytes(pr) >> 1;
	nints = (ptr->width + 31) >> 5;
	dp = mpr_d(pr)->md_image;
	for(col = 0; col < ptr->height; col++)
	{
		fread(buf, 4, nints, font_fp);
		sp = (short *) &buf[0];
		for(i = nshorts; i > 0; i--)
			*dp++ = *sp++;
	}
	ptr->where.address.pixrectptr = pr;
	ptr->where.isloaded = TRUE;

	return TRUE;
}