dviselect (Part 5 of 6)

Skip Montanaro montnaro at sprite.crd.ge.com
Tue Nov 14 08:23:59 AEST 1989


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 6)."
# Contents:  lib/pkfont.c lib/pxlfont.c
# Wrapped by montnaro at sprite on Sat Nov 11 17:13:32 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/pkfont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/pkfont.c\"
else
echo shar: Extracting \"lib/pkfont.c\" \(18209 characters\)
sed "s/^X//" >lib/pkfont.c <<'END_OF_lib/pkfont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/pkfont.c,v 1.9 89/02/13 14:31:13 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "types.h"
X#include "font.h"
X#include "num.h"
X
X/*
X * PK font operations.
X *
X * The spelling `nybble' is a concession to the authors of the PK format.
X */
X
Xstatic pk_read();
Xstatic scan_characters();
Xstatic pk_getgly();
Xstatic pk_rasterise();
Xstatic pk_freefont();
X
Xstruct	fontops pkops =
X	{ "pk", 1.0, pk_read, pk_getgly, pk_rasterise, pk_freefont };
X
X/*
X * Local info.
X */
X
X/*
X * Commands.
X */
X#define	PK_XXX1		240	/* 1 byte special */
X#define	PK_XXX2		241	/* 2 byte special */
X#define	PK_XXX3		242	/* 3 byte special */
X#define	PK_XXX4		243	/* 4 byte special */
X#define	PK_YYY		244	/* METAFONT numspecial */
X#define	PK_POST		245	/* marks postamble */
X#define	PK_NO_OP	246	/* do nothing */
X#define	PK_PRE		247	/* marks preamble */
X				/* 248..255 undefined */
X#define PK_IsUndef(c)	((c) > PK_PRE)
X
X#define	PK_ID		89	/* marks this brand of PK file */
X
X/*
X * Information about a character packet.
X */
Xstruct cp {
X	char	*cp_packet;	/* the beginning of the packet */
X	int	cp_type;	/* decoded pre type, see below */
X};
X
X#define	CP_SHORT	0	/* short preamble */
X#define	CP_EXT_SHORT	1	/* extended short preamble */
X#define	CP_LONG		2	/* long preamble */
X
X/*
X * The PK details include:
X *  ->	a pointer to the next byte to fetch;
X *  ->	the most recent byte fetched (when we are using nextnyb());
X *  ->	a flag indicating that we have used nybble 0 (bits 4..7) and
X *	should use nybble 1 next;
X *  ->	the base address of the memory allocated for the PK file;
X *  ->	the value of dyn_f (during character translation);
X *  ->	the repeat count (during rasterisation);
X *  ->	the lowest glyph number that is legal;
X *  ->	the highest glyph number that is legal;
X *  ->	glyph instructions for the standard glyphs;
X *  ->	glyph instructions for more (nonstandard) glyphs;
X * and	the number of glyphs left unrasterised.
X */
Xstruct pk_details {
X	char	*pk_ptr;	/* next byte to fetch */
X	int	pk_c;		/* most recent byte fetched, if nybbling */
X	int	pk_1nyb;	/* true => nybble 1 is next (bits 0..3) */
X	char	*pk_base;	/* base of allocated memory */
X	int	pk_dyn_f;	/* the dyn_f value */
X	int	pk_repeat;	/* the repeat count */
X	int	pk_minc;	/* minimum character value */
X	int	pk_maxc;	/* maximum character value */
X#define MAXSTD	256		/* maximum `standard' character value */
X	int	pk_gleft;	/* number of valid glyphs left uninterpreted */
X	struct	cp pk_cpack[MAXSTD];	/* for characters in [0..MAXSTD) */
X	struct	cp *pk_morec;		/* for characters in [MAXSTD..maxc] */
X};
X
X/*
X * Fetch the next byte from the PK file.
X */
X#define	nextbyte(pk) pgetbyte((pk)->pk_ptr)
X
X/*
X * PK packed number encoding.  Nybbles in [1..dyn_f] represent themselves.
X * Values in (dyn_f..13] are two-nybble values, and represent values
X * dyn_f+1 through (13-dyn_f+1)*16+15.  Zero marks a long number; 14 and
X * 15 specify repeat counts instead (which are another packed number).
X * Note that we cannot represent the number zero as a packed number.
X */
X#define	PK_LONGNUM	0	/* a `long number' */
X#define	PK_REPEAT	14	/* set repeat count */
X#define	PK_REPEAT1	15	/* set repeat to 1 */
X
X/*
X * Get the next nybble.  This is an expression rendition of
X *	if (--pk->pk_1nyb < 0) {
X *		pk->pk_1nyb = 1;
X *		pk->pk_c = nextbyte(pk);
X *		return (pk->pk_c >> 4);
X *	} else
X *		return (pk->pk_c & 0xf);
X */
X#define	nextnyb(f) \
X	(--(pk)->pk_1nyb < 0 ? \
X	 ((pk)->pk_1nyb = 1, ((pk)->pk_c = nextbyte(pk)) >> 4) : \
X	 (pk)->pk_c & 0xf)
X
X/*
X * Get the pk_details from font f.
X */
X#define	ftopk(f) ((struct pk_details *) (f)->f_details)
X
Xextern	int errno;
Xchar	*malloc();
X
X/*
X * PK subroutines.
X */
X
X/*
X * Unpack a packed number.
X */
Xstatic int
Xpk_unpack(pk)
X	register struct pk_details *pk;
X{
X	register int i, j;
X
Xtop:
X	if ((i = nextnyb(pk)) == PK_LONGNUM) {
X#if PK_LONGNUM != 0		/* this may be silly, but . . . */
X		i = 0;
X#endif
X		/*
X		 * Expand a long number.  There are one fewer leading
X		 * zeros than there are nonzero digits to obtain, so
X		 * count up the leading zeros, add one, and get that
X		 * many digits.  (The `digits' are hexadecimal values.)
X		 */
X		do {
X			i++;
X		} while ((j = nextnyb(pk)) == 0);
X		while (--i >= 0) {
X			j <<= 4;
X			j += nextnyb(pk);
X		}
X		return (j - 15 + (13 - pk->pk_dyn_f) * 16 + pk->pk_dyn_f);
X	}
X	if (i <= pk->pk_dyn_f)
X		return (i);
X	if (i < PK_REPEAT)
X		return ((i - pk->pk_dyn_f - 1) * 16 + nextnyb(pk) +
X			pk->pk_dyn_f + 1);
X
X	/*
X	 * There is a repeat count, either one or a packed number.
X	 * Get it first, then start over.  (tail recursion)
X	 */
X	if (i == PK_REPEAT)
X		pk->pk_repeat = pk_unpack(pk);
X	else
X		pk->pk_repeat = 1;
X	goto top;
X}
X
X/*
X * Skip over special commands (PK_XXX?, PK_YYY).
X */
Xstatic
Xskip_specials(f)
X	struct font *f;
X{
X	struct pk_details *pk = ftopk(f);
X	register char *p = pk->pk_ptr;
X	register i32 i;
X
X	for (;;) {
X	    int tmp;
X	    tmp = UnSign8(*p);
X	    p++;
X		 switch (tmp) {
X
X		case PK_XXX1:
X			i = UnSign8(*p);
X			p++;
X			p += i;
X			break;
X
X		case PK_XXX2:
X			pGetWord(p, i);
X			p += i;
X			break;
X
X		case PK_XXX3:
X			pGet3Byte(p, i);
X			p += i;
X			break;
X
X		case PK_XXX4:
X			pGetLong(p, i);
X			p += i;
X			break;
X
X		case PK_YYY:
X			p += 4;
X			break;
X
X		case PK_NO_OP:
X			break;
X
X		case PK_PRE:
X			error(1, 0, "unexpected PK_PRE in \"%s\"", f->f_path);
X			break;
X
X		default:
X			p--;
X			if (PK_IsUndef(UnSign8(*p)))
X				error(1, 0, "invalid opcode %d in \"%s\"",
X					f->f_path);
X			pk->pk_ptr = p;
X			return;
X		}
X	}
X}
X
X/*
X * Read a PK file.
X */
Xstatic int
Xpk_read(f)
X	register struct font *f;
X{
X	register struct pk_details *pk;
X	register char *p;
X	int i, fd;
X	struct stat st;
X	char *reason;
X
X	if ((fd = open(f->f_path, 0)) < 0)
X		return (-1);
X	pk = NULL;		/* prepare for failure */
X	reason = NULL;
X	(void) fstat(fd, &st);
X	if (st.st_size < 4) {	/* ??? */
X		reason = "file is too small";
X		goto fail;
X	}
X	if ((pk = (struct pk_details *) malloc(sizeof (*pk))) == NULL)
X		goto fail;
X	pk->pk_morec = NULL;
X	if ((pk->pk_base = malloc(st.st_size)) == NULL)
X		goto fail;
X	if (read(fd, pk->pk_base, st.st_size) != st.st_size)
X		goto fail;
X	pk->pk_ptr = pk->pk_base;
X	if (nextbyte(pk) != PK_PRE) {
X		reason = "file does not begin with PK_PRE";
X		goto fail;
X	}
X	if (nextbyte(pk) != PK_ID) {
X		reason = "bad PK_ID";
X		goto fail;
X	}
X	i = nextbyte(pk);
X	p = pk->pk_ptr + i;	/* skip comment */
X	pGetLong(p, f -> f_design_size);
X	pGetLong(p, f -> f_checksum);
X	pGetLong(p, f -> f_hppp);
X	pGetLong(p, f -> f_vppp);
X	pk->pk_ptr = p;
X/* DEBUG */
X	f->f_details = (char *) pk;
X
X	/* scan the characters, fail if necessary */
X	if (scan_characters(f, &reason))
X		goto fail;
X
X	/* ignore the postamble */
X
X	/* COMPRESS pk->pk_base DATA? */
X
X	if (FontHasGlyphs(f, pk->pk_minc, pk->pk_maxc + 1))
X		goto fail;
X	(void) close(fd);
X	return (0);
X
Xfail:
X	if (reason) {
X		error(0, 0, "%s", reason);
X		error(0, 0, "(are you sure %s is a PK file?)", f->f_path);
X		errno = 0;
X	}
X	if (pk != NULL) {
X		if (pk->pk_base != NULL) {
X			free(pk->pk_base); pk -> pk_base = 0; 
X		      }
X		if (pk->pk_morec != NULL) {
X			free((char *) pk->pk_morec); pk -> pk_morec = 0;
X		      }
X		free((char *) pk); pk = 0;
X	}
X	(void) close(fd);
X	return (-1);
X}
X
X/*
X * Scan through the characters in the PK file, and set the offsets
X * and preamble types for each of the character packets.
X */
Xstatic int
Xscan_characters(f, reason)
X	struct font *f;
X	char **reason;
X{
X	register struct pk_details *pk = ftopk(f);
X	register i32 c, pl;
X  	register char *p;
X  	register struct cp *cp;
X  	int type;
X
X#ifdef lint
X	/* reason will be used someday ... I think */
X	reason = reason;
X#endif
X
X	/* set up the minimisers and the glyph count */
X	pk->pk_minc = 1;
X	pk->pk_maxc = 0;
X	pk->pk_gleft = 0;
X
X	/* mark all character packets as untouched */
X	for (cp = pk->pk_cpack, c = MAXSTD; --c >= 0; cp++)
X		cp->cp_packet = NULL;
X
X  	/*
X  	 * Loop through the packets until we reach a POST, skipping
X 	 * the glyph instructions themselves after each definition,
X 	 * and specials (if any) before each.
X  	 */
X 	for (;; pk->pk_ptr = p + pl) {
X 		skip_specials(f);
X 		p = pk->pk_ptr;
X 		if ((c = pgetbyte(p)) == PK_POST)
X 			break;	/* whoops, done after all */
X
X		/*
X		 * Look at the low three bits to decide preamble size.
X		 * A value of 7 is a `long preamble'; 4, 5, and 6 are
X		 * `extended short preambles'; and 0, 1, 2, and 3 are
X		 * `short preambles'.
X		 *
X		 * We ignore most of the preamble, reading only the
X		 * `packet length' and the character code at this time.
X		 */
X		switch (c & 7) {
X
X		case 7:		/* long */
X			type = CP_LONG;
X			pGetLong(p, pl);
X			pGetLong(p, c);
X			break;
X
X		case 6:
X		case 5:
X		case 4:		/* extended short */
X			type = CP_EXT_SHORT;
X			pGetWord(p, pl);
X			pl += (c & 3) << 16;
X			c = pgetbyte(p);
X			break;
X
X		default:	/* short */
X			type = CP_SHORT;
X			pl = ((c & 3) << 8) + pgetbyte(p);
X			c = pgetbyte(p);
X			break;
X		}
X
X		if (c >= MAXSTD) {
X			/*
X			 * BEGIN XXX - should alloc pk_morec, but is hard
X			 * and not now useful
X			 */
X			error(0, 0, "ignoring character %d in \"%s\"",
X				f->f_path);
X			error(0, 0, "because some darn programmer was lazy!");
X			continue;
X			/* END XXX */
X		} else
X			cp = &pk->pk_cpack[c];
X
X		cp->cp_packet = pk->pk_ptr;
X		cp->cp_type = type;
X
X		/* adjust range */
X		if (c < pk->pk_minc)
X			pk->pk_minc = c;
X		if (c > pk->pk_maxc)
X			pk->pk_maxc = c;
X
X		pk->pk_gleft++;	/* and count the glyph */
X	}
X	return (0);		/* no problems */
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xpk_getgly(f, l, h)
X	register struct font *f;
X	int l, h;
X{
X	register struct pk_details *pk = ftopk(f);
X	register char *p;
X	register struct glyph *g;
X	register int i;
X	register struct cp *cp;
X
X	if (pk == NULL)
X		panic("pk_getgly(%s)", f->f_path);
X	for (i = l; i < h; i++) {
X  		if (i < MAXSTD)
X  			cp = &pk->pk_cpack[i];
X 		else {
X 			if (i > pk->pk_maxc)
X 				panic("pk_getgly(%s, %d)", f->f_path, i);
X  			cp = &pk->pk_morec[i - MAXSTD];
X 		}
X  		p = cp->cp_packet;
X  		if (p == NULL)	/* glyph is not valid */
X			continue;
X		g = f->f_gly[i];
X		p++;		/* skip flag */
X		switch (cp->cp_type) {
X
X		case CP_LONG:
X			p += 8;	/* skip packet len, character code */
X			pGetLong(p, g->g_tfmwidth);
X			g -> g_rawtfmwidth = g -> g_tfmwidth;
X			pGetLong(p, g->g_xescapement);
X			pGetLong(p, g->g_yescapement);
X			pGetLong(p, g->g_width);
X			pGetLong(p, g->g_height);
X			pGetLong(p, g->g_xorigin);
X			pGetLong(p, g->g_yorigin);
X			break;
X
X		case CP_EXT_SHORT:
X			p += 3;	/* skip packet len, character code */
X			pGet3Byte(p, g->g_tfmwidth);
X			g -> g_rawtfmwidth = g -> g_tfmwidth;
X			{ i32 dm; pGetWord(p, dm);
X			g->g_xescapement = dm << 16; }
X			g->g_yescapement = 0;
X			pGetWord(p, g->g_width);
X			pGetWord(p, g->g_height);
X			pGetWord(p, g->g_xorigin);
X			g->g_xorigin = Sign16(g->g_xorigin);
X			pGetWord(p, g->g_yorigin);
X			g->g_yorigin = Sign16(g->g_yorigin);
X			break;
X
X		case CP_SHORT:
X			p += 2;	/* skip packet len, character code */
X			pGet3Byte(p, g->g_tfmwidth);
X			g -> g_rawtfmwidth = g -> g_tfmwidth;
X			g->g_xescapement = pgetbyte(p) << 16;
X			g->g_yescapement = 0;
X			g->g_width = pgetbyte(p);
X			g->g_height = pgetbyte(p);
X			g->g_xorigin = pgetbyte(p);
X			g->g_xorigin = Sign8(g->g_xorigin);
X			g->g_yorigin = pgetbyte(p);
X			g->g_yorigin = Sign8(g->g_yorigin);
X			break;
X		}
X		g->g_flags = GF_VALID;
X		g->g_un.g_details = p;
X	}
X	return (0);
X}
X
X/*
X * Bit masks for pk_rasterise().
X */
Xstatic char bmask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
Xstatic char rbits[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
X
X/*
X * Obtain rasters for the specified glyphs.
X */
Xstatic int
Xpk_rasterise(f, l, h)
X	struct font *f;
X	int l, h;
X{
X	struct pk_details *pk0;
X	struct glyph *g0;
X	char *p0, *rp0;
X	int flag, ii;
X
X	if ((pk0 = ftopk(f)) == NULL)
X		panic("pk_rasterise(%s)", f->f_path);
X	for (ii = l; ii < h; ii++) {
X		{
X			register struct glyph *g;
X			register char *p;
X			register int i;
X
X			g = f->f_gly[i = ii];
X			if ((g->g_flags & GF_VALID) == 0)
X				continue;	/* no glyph */
X			if (!HASRASTER(g))	/* empty raster */
X				goto done;
X
X			/*
X			 * Allocate a raster.
X			 */
X			rp0 = malloc(((g->g_width + 7) >> 3) * g->g_height);
X			if ((g->g_raster = rp0) == NULL)
X				return (-1);/* ??? */
X			g->g_rotation = ROT_NORM;
X
X			/*
X			 * Pick up the flag byte, then start at the real
X			 * packet, which we saved in g_details.
X			 */
X			if (i < MAXSTD)
X				p = pk0->pk_cpack[i].cp_packet;
X			else
X				p = pk0->pk_morec[i - MAXSTD].cp_packet;
X			flag = UnSign8(*p);
X			p0 = g->g_un.g_details;
X			g0 = g;
X		}
X		if ((pk0->pk_dyn_f = flag >> 4) == 14) {
X			register char *p = p0, *rp = rp0;
X			register int j, ls, rs, i, w;
X
X			/*
X			 * Expand a bit-packed representation.
X			 * If we get lucky, it is byte packed and
X			 * we can just copy it over.
X			 */
X			i = g0->g_height;
X			j = g0->g_width;
X			if ((j & 7) == 0) {
X				bcopy(p, rp, i * (j >> 3));
X				goto done;
X			}
X
X			/*
X			 * No such luck.
X			 */
X			w = j;
X			ls = 0;
X			while (--i >= 0) {
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X				/* have to work on the compiler someday */
X				rs = ls - 8;
X#else
X				rs = 8 - ls;
X#endif
X				/* know j always != 8 */
X				for (j = w; j > 8; j -= 8) {
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X					asm("	movb	(r11)+,r0");
X					asm("	ashl	r8,r0,r0");
X					asm("	movb	r0,(r10)");
X					asm("	movzbl	(r11),r0");
X					asm("	ashl	r7,r0,r0");
X					asm("	bisb2	r0,(r10)+");
X#else
X					*rp = *p << ls;
X					p++;
X					*rp |= UnSign8(*p) >> rs;
X					rp++;
X#endif
X				}
X
X				/*
X				 * We need j more bits; there are rs
X				 * bits available at *p.  Ask for j,
X				 * which gets min(j, rs).
X				 */
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X				  
X#ifdef BROKEN_COMPILER_HACKS
X				/*void*/; /* avoid asm() label botch */
X				asm("	movb	(r11),r0");
X				asm("	ashl	r8,r0,r0");
X				asm("	mcomb	_bmask[r9],r1");
X				asm("	bicb2	r1,r0");
X				asm("	movb	r0,(r10)+");
X#else
X				*rp++ = (*p << ls) & bmask[j];
X#endif
X				/* account for j bits */
X				ls += j; ls &= 7;
X				/* then adjust j based on rs */
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X				j += rs;
X#else
X				j -= rs;
X#endif
X				/* still need j more bits */
X				if (j < 0)	/* got them all */
X					continue;
X				p++;
X				if (j == 0)	/* there were just enough */
X					continue;
X				/* take j more bits */
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X				/*void*/; /* avoid asm() label botch */
X				asm("	mcomb	_bmask[r9],r0");
X				asm("	bicb3	r0,(r11),r0");
X				asm("	movzbl	r0,r0");
X				asm("	ashl	r7,r0,r0");
X				asm("	bisb2	r0,-1(r10)");
X#else
X				rp[-1] |= UnSign8(*p & bmask[j]) >> rs;
X#endif
X			}
X		} else {
X			register struct pk_details *pk = pk0;
X			register int on = flag & 8 ? 0xff : 0;
X			register char *rowp;	/* pointer into this row */
X			register int j;		/* trimmed run count */
X			register int k;		/* misc */
X			register int b;		/* bit index in current col */
X			register int i;		/* run count */
X			register int colsleft;	/* columns left this row */
X			register int rowsleft;	/* rows left */
X			static char *row;	/* a one-row buffer */
X			static int rowsize;	/* and its size in bytes */
X			int wb;			/* row width in bytes */
X
X			wb = (g0->g_width + 7) >> 3;
X			if (rowsize < wb) {	/* get more row space */
X				if (row) {
X				  free(row); row = 0;
X				}
X				/* keep a slop byte */
X				row = malloc((unsigned) (wb + 1));
X				if (row == NULL)
X					return (-1);	/* ??? */
X				rowsize = wb;
X			}
X			bzero(row, wb);
X			rowsleft = g0->g_height;
X			colsleft = g0->g_width;
X			pk->pk_repeat = 0;
X			pk->pk_ptr = p0;
X			pk->pk_1nyb = 0;	/* start on nybble 0 */
X			rowp = row;
X			b = 0;
X			while (rowsleft > 0) {	/* do all rows */
X				/* EXPAND IN LINE? */
X				i = pk_unpack(pk);
X				/*
X				 * Work until the run count is exhausted
X				 * (or at least pretty tired).
X				 *
X				 * (Okay, so the joke is stolen!)
X				 */
X				while ((j = i) > 0) {
X					/*
X					 * If the count is more than the
X					 * rest of this row, trim it down.
X					 */
X					if (j > colsleft)
X						j = colsleft;
X					i -= j;	/* call them done */
X					/*
X					 * We need k=8-b bits to finish
X					 * up the current byte.  If we
X					 * can finish it, do so; the proper
X					 * bits to set are in rbits[k].
X					 */
X					if (j >= (k = 8 - b)) {
X						j -= k;
X						colsleft -= k;
X						*rowp++ |= on & rbits[k];
X						b = 0;
X					}
X					/*
X					 * Set any full bytes.
X					 */
X					while (j >= 8) {
X						*rowp++ = on;
X						j -= 8;
X						colsleft -= 8;
X					}
X					/*
X					 * Finally, begin a new byte, or
X					 * add to the current byte, with
X					 * j more bits.  We know j <= 8-b.
X					 * (If j==0, we may be writing on
X					 * our slop byte, which is why we
X					 * keep one around....)
X					 */
Xif (j > 8-b) panic("pk_rasterise j>8-b");
X					*rowp |= (on & bmask[j]) >> b;
X					colsleft -= j;
X					b += j; b &= 7;
X					if (colsleft == 0) {
X						pk->pk_repeat++;
X						rowsleft -= pk->pk_repeat;
X						while (--pk->pk_repeat >= 0) {
X							bcopy(row, rp0, wb);
X							rp0 += wb;
X						}
Xif (rowsleft == 0 && i) panic("pk_rasterise leftover bits");
X						pk->pk_repeat = 0;
X						rowp = row;
X						colsleft = g0->g_width;
X						bzero(row, wb);
X						b = 0;
X					}
X				}
X				on = 0xff - on;
X			}
X		}
X
Xdone:
X		/*
X		 * Successfully converted another glyph.
X		 */
X		pk0->pk_gleft--;
X	}
X
Xif (pk0->pk_gleft < 0)
Xpanic("%s: gleft==%d", f->f_path, pk0->pk_gleft);
X	if (pk0->pk_gleft == 0) {
X		free(pk0->pk_base); pk0 -> pk_base = 0;
X		if (pk0->pk_morec != NULL) {
X		  free((char *) pk0->pk_morec); pk0 -> pk_morec = 0;
X		}
X		free((char *) pk0); pk0 = 0;
X		f->f_details = NULL;
X	}
X	return (0);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xpk_freefont(f)
X	struct font *f;
X{
X	register struct pk_details *pk = ftopk(f);
X
X	if (pk != NULL) {
X		free(pk->pk_base); pk -> pk_base = 0;
X		if (pk->pk_morec != NULL) {
X		  free((char *) pk->pk_morec); (char *) pk->pk_morec = 0;
X		}
X		free((char *) pk); (char *) pk = 0;
X	}
X}
END_OF_lib/pkfont.c
if test 18209 -ne `wc -c <lib/pkfont.c`; then
    echo shar: \"lib/pkfont.c\" unpacked with wrong size!
fi
chmod +x lib/pkfont.c
# end of overwriting check
fi
if test -f lib/pxlfont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/pxlfont.c\"
else
echo shar: Extracting \"lib/pxlfont.c\" \(6872 characters\)
sed "s/^X//" >lib/pxlfont.c <<'END_OF_lib/pxlfont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/pxlfont.c,v 1.4 89/02/13 14:31:16 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X#include "types.h"
X#include "font.h"
X#include "fio.h"
X
X/*
X * PXL font operations.
X */
X
Xstatic pxl_read();
Xstatic pxl_getgly();
Xstatic pxl_rasterise();
Xstatic pxl_freefont();
X
X
Xstruct	fontops pxlops =
X	{ "pxl", 5.0, pxl_read, pxl_getgly, pxl_rasterise, pxl_freefont };
X
X/*
X * Local info.
X */
X
X#define	PXLID	1001		/* ID denoting PXL files */
X#define	TAILSIZE (517 * 4)	/* size of pxl tail info */
X
X/*
X * pc describes one PXL character information block.
X */
Xstruct pc {
X	i16	pc_width;	/* character width (pixels) */
X	i16	pc_height;	/* character height (pixels) */
X	i16	pc_xoffset;	/* X offset of reference point */
X	i16	pc_yoffset;	/* Y offset of reference point */
X	i32	pc_rastoff;	/* raster offset */
X	i32	pc_TFMwidth;	/* TFM width (FIXes) */
X};
X
X/*
X * pxl_details are the PXL-specific font details.
X *
X * We keep track of the number of characters converted to internal
X * glyph form, and when all have been done, we discard the now-
X * useless details.
X */
Xstruct pxl_details {
X	int	pd_nconv;	/* number of characters converted */
X	char	*pd_ras;	/* raster space, until converted */
X	struct	pc pd_pc[128];	/* `font directory' */
X};
X
X/*
X * Get the pxl_details from font f.
X */
X#define	ftopd(f) ((struct pxl_details *) (f)->f_details)
X
Xextern	errno;
Xchar	*malloc();
X
X/*
X * Read a PXL file.
X */
Xstatic int
Xpxl_read(f)
X	struct font *f;
X{
X	register struct pxl_details *pd;
X	register FILE *fp;
X	register struct pc *pc;
X	register int i;
X	int fd, saverr;
X	i32 pxlid;
X	struct stat st;
X
X	if ((fd = open(f->f_path, 0)) < 0)
X		return (-1);
X
X	fp = NULL;
X	if ((pd = (struct pxl_details *) malloc(sizeof (*pd))) == 0)
X		goto fail;
X	pd->pd_ras = 0;
X
X	/*
X	 * There should be 4n bytes, with an absolute minimum of TAILSIZE+4
X	 * (+4 for the initial PXLID).
X	 */
X	(void) fstat(fd, &st);
X	if ((st.st_size & 3) != 0 || st.st_size < (TAILSIZE + 4)) {
X		errno = EINVAL;
X		goto fail;
X	}
X
X	/*
X	 * Set up the raster pointer (if we need rasters).
X	 */
X	if (f->f_flags & FF_RASTERS) {
X		i = st.st_size - (TAILSIZE + 4);
X		if (i != 0)  {
X			if ((pd->pd_ras = malloc((unsigned) i)) == 0)
X				goto fail;
X			(void) lseek(fd, 4L, 0);
X			if (read(fd, pd->pd_ras, i) != i)
X				goto fail;
X		}
X	}
X
X	/*
X	 * Read the glyph information.
X	 */
X	errno = 0;		/* try to make errno meaningful */
X	if ((fp = fdopen(fd, "r")) == NULL) {
X		if (errno == 0)
X			errno = EMFILE;
X		goto fail;
X	}
X	(void) fseek(fp, (long) -TAILSIZE, 2);
X	for (i = 128, pc = pd->pd_pc; --i >= 0; pc++) {
X		fGetWord(fp, pc->pc_width);
X		fGetWord(fp, pc->pc_height);
X		fGetWord(fp, pc->pc_xoffset);
X		fGetWord(fp, pc->pc_yoffset);
X		fGetLong(fp, pc->pc_rastoff);
X		fGetLong(fp, pc->pc_TFMwidth);
X	}
X	f->f_checksum = GetLong(fp);
X	(void) GetLong(fp);	/* mag */
X	f -> f_design_size = GetLong(fp);	/* designsize */
X	(void) GetLong(fp);	/* dirpointer */
X	pxlid = GetLong(fp);
X	if (pxlid != PXLID)
X		error(0, 0, "Warning: strange PXL id (%d) in \"%s\"",
X			pxlid, f->f_path);
X
X	f->f_details = (char *) pd;
X	if (FontHasGlyphs(f, 0, 128))
X		goto fail;
X	(void) fclose(fp);
X	pd->pd_nconv = 0;
X	return (0);
X
Xfail:
X	saverr = errno;
X	if (pd) {
X		if (pd->pd_ras) {
X		  free(pd->pd_ras); pd->pd_ras = 0;
X		}
X		free((char *) pd); (char *) pd = 0;
X	}
X	if (fp)
X		(void) fclose(fp);
X	else
X		(void) close(fd);
X	errno = saverr;
X	return (-1);
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xpxl_getgly(f, l, h)
X	register struct font *f;
X	int l;
X	register int h;
X{
X	register struct glyph *g;
X	register struct pc *pc;
X	register int i;
X	struct pxl_details *pd;
X
X	if ((pd = ftopd(f)) == NULL)
X		error(1, 0, "pxl_getgly details==0: cannot happen");
X	/*
X	 * By definition, all 128 glyphs are valid.  Just copy the
X	 * PXL information.
X	 */
X	for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
X		g = f->f_gly[i];
X		g->g_flags = GF_VALID;
X		g->g_height = pc->pc_height;
X		g->g_width = pc->pc_width;
X		g->g_yorigin = pc->pc_yoffset;
X		g->g_xorigin = pc->pc_xoffset;
X		g->g_tfmwidth = pc->pc_TFMwidth;
X		g -> g_rawtfmwidth = g -> g_tfmwidth;
X	}
X	return (0);
X}
X
X/*
X * Helper function for rasterise: return a pointer to a converted
X * (malloc()ed and minimised) raster.
X */
Xstatic char *
Xmakeraster(h, w, rp)
X	register int h, w;
X	register char *rp;
X{
X	register char *cp;
X	register int i, o;
X	char *rv;
X
X	/*
X	 * The height and width values are in bits.  Convert width to
X	 * bytes, rounding up.  The raw raster (at rp) is almost what
X	 * we want, but not quite: it has `extra' bytes at the end of
X	 * each row, to pad out to a multiple of four bytes.
X	 */
X	w = (w + 7) >> 3;
X	o = (4 - w) & 3;	/* offset (number of `extra' bytes) */
X	if ((cp = malloc((unsigned) (h * w))) == NULL)
X		return (NULL);
X	if (o == 0) {
X		/*
X		 * The raster fits exactly; just copy it to the allocated
X		 * memory space.  (We must copy anyway, so that glyphs
X		 * can be freed, e.g., after rotation.)
X		 */
X		bcopy(rp, cp, h * w);
X		return (cp);
X	}
X	rv = cp;
X	while (--h >= 0) {
X		/*
X		 * Copy each row, then skip over the extra stuff.
X		 */
X		for (i = w; --i >= 0;)
X			*cp++ = *rp++;
X		rp += o;
X	}
X	return (rv);
X}
X
X/*
X * Obtain rasters for the specified glyphs.
X */
Xstatic int
Xpxl_rasterise(f, l, h)
X	register struct font *f;
X	int l;
X	register int h;
X{
X	register struct glyph *g;
X	register struct pc *pc;
X	register int i;
X	register struct pxl_details *pd;
X
X	if ((pd = ftopd(f)) == NULL)
X		error(1, 0, "pxl_rasterise details==0: cannot happen");
X	if (pd->pd_ras == NULL)
X		error(1, 0, "pxl_rasterise pd_ras==NULL: cannot happen");
X	for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
X		g = f->f_gly[i];
X		if (pc->pc_rastoff == 0) {
X			/*
X			 * g should not claim a raster, since it has none.
X			 */
X			if (HASRASTER(g))
X				error(1, 0, "bad PXL glyph %d in \"%s\"",
X					g->g_index, f->f_path);
X		} else {
X			g->g_raster = makeraster(pc->pc_height, pc->pc_width,
X				pd->pd_ras + ((pc->pc_rastoff - 1) << 2));
X			if (g->g_raster == NULL)
X				return (-1);	/* ??? */
X			g->g_rotation = ROT_NORM;
X		}
X	}
X
X	/*
X	 * If we have converted all the characters, dump the
X	 * pre-conversion rasters.  In fact, dump everything.
X	 */
X	pd->pd_nconv += h - l;
X	if (pd->pd_nconv == 128) {
X		free(pd->pd_ras); pd->pd_ras = 0;
X		free((char *) pd); (char *) pd = 0;
X		f->f_details = NULL;
X	}
X	return (0);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xpxl_freefont(f)
X	struct font *f;
X{
X	struct pxl_details *pd;
X
X	if ((pd = ftopd(f)) != NULL) {
X		if (pd->pd_ras != NULL) {
X		  free(pd->pd_ras); pd->pd_ras = 0;
X		}
X		free((char *) pd); (char *) pd = 0;
X	}
X}
END_OF_lib/pxlfont.c
if test 6872 -ne `wc -c <lib/pxlfont.c`; then
    echo shar: \"lib/pxlfont.c\" unpacked with wrong size!
fi
chmod +x lib/pxlfont.c
# end of overwriting check
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro at crdgw1.ge.com)



More information about the Alt.sources mailing list