v14i073: cat2deskjet (Part 3 of 3)

vp at cui.unige.ch vp at cui.unige.ch
Fri Aug 31 10:20:23 AEST 1990


Posting-number: Volume 14, Issue 73
Submitted-by: vp at cui.unige.ch
Archive-name: cat2deskjet/part03

#! /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 3 (of 3)."
# Contents:  railmag.c vf.c
# Wrapped by vp at cuisun29 on Tue Aug 28 14:24:51 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'railmag.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'railmag.c'\"
else
echo shar: Extracting \"'railmag.c'\" \(21822 characters\)
sed "s/^X//" >'railmag.c' <<'END_OF_FILE'
X/*
X *	railmag.c -- downloads vfonts to a Hewlett-Packard DeskJet.
X *  Copyright (C) 1990 Vassilis Prevelakis
X *
X *  This program is free software; you can redistribute it and/or modify
X *  it under the terms of the GNU General Public License as published by
X *  the Free Software Foundation and included with this distribution in the
X *  file named LICENSE.
X *
X *  This program is distributed in the hope that it will be useful,
X *  but WITHOUT ANY WARRANTY; without even the implied warranty of
X *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X *  GNU General Public License for more details.
X *
X *  You should have received a copy of the GNU General Public License
X *  along with this program; if not, write to the Free Software
X *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X *
X *  Bug fixes, comments etc. to:
X *       Vasilis Prevelakis
X *       Centre Universitaire d'Informatique (CUI)
X *       12 Rue du Lac, Geneva, Switzerland CH-1207
X *  email: vp at cui.unige.ch
X *  uucp:  ...!mcsun!cui!vp
X *
X */
X
X#include <assert.h>
X#include <stdio.h>
X#ifdef UNIX
X#include <string.h>
X#include <vfont.h>
X#include <sys/file.h>
X#else
X#include <string.h>
X#include <vp/vfont.h>
X#include <fcntl.h>
X#include <alloc.h>
X#endif
X
Xtypedef unsigned short	u_short;
Xtypedef unsigned char	u_char;
X
X#ifdef UNIX
X#define max(X, Y)	((X > Y) ? X : Y)
X#define min(X, Y)	((X < Y) ? X : Y)
X#endif
X
X#define FDB_LEN	sizeof(struct fdb)
X
Xstruct fdb {
X	u_short	size;		/* always 72 */
X	u_char	format;		/* DeskJet only: header format (5 or 9) */
X	u_char	ftype;		/* zero for 7-bit font */
X	short	xxx1;		/* RESERVED, must be zero */
X	u_short	baseline;	/* in dots */
X	u_short cell_width;	/* in dots */
X	u_short cell_height;	/* in dots */
X	u_char orientation;	/* 0 portrait, 1 landscape */
X	u_char spacing;		/* 0 fixed, 1 proportional */
X	u_short symbol;
X	u_short pitch;		/* in quarter dots */
X	u_short height;		/* in quarter dots */
X	u_short xHeight;	/* in quarter dots -- IGNORED */
X	u_char w_type;		/* IGNORED, == 0 */
X	u_char style;
X	char str_weight;
X	u_char typeface;
X	u_char	slant;		/* DeskJet only */
X	u_char s_style;
X	u_char quality;		/* DeskJet only */
X	u_char placement;	/* DeskJet only */
X	char ud_dst;
X	u_char ud_height;	/* IGNORED, == 3 */
X	u_short	t_height;	/* IGNORED, == 0 */
X	u_short t_width;	/* IGNORED, == 0 */
X	u_short firstcode;	/* DeskJet only */
X	u_short lastcode; 	/* DeskJet only */
X	u_char ext_pitch;	/* IGNORED by DeskJet == 0 */
X	u_char ext_height;	/* IGNORED by DeskJet == 0 */
X	short xxx5[3];		/* RESERVED, must be zero */
X#define MAXNAME 16
X	char fname[MAXNAME];
X	/* following fields DeskJet only */
X	u_short hres;		/* horizontal resolution == 600 */
X	u_short vres;		/* vertical resolution == 300 */
X	char ud2_dst;
X	u_char ud2_height;
X	char bud_dst;
X	u_char bud_height;
X	u_short psbs;		/* number of subsequent bytes == 20 */
X	u_short font_size;
X	char oneway;
X	char compressed;
X	u_char holdtime;
X	char nohalfpitch;
X	char nodoublepitch;
X	char nohalfheight;
X	char nobold;
X	char nodraft;
X	char boldmethod;
X	char xxx7;		/* RESERVED, must be zero */
X	u_short baseoff2;
X/* following fields used by DeskJet PLUS **ONLY** */
X	u_short baseoff3;
X	u_short baseoff4;
X} myfdb;
X
X#define CDB_LEN	sizeof(struct cdb)
Xstruct cdb {
X	u_char	format;		/* 9 for large, 5 for small! */
X	u_char	continuation;
X	u_char	size;		/* always == 6 */
X	u_char	type;		/* single pass (=0) or pass number (=2,3,4,5) */
X	u_char	width;
X	u_char	compr_width;
X	u_char	left_pad;
X	u_char	right_pad;
X};
X
X#define NCHAR 127
X/* NPASS is the maximum number of passes that the printer can make
X * when printing a character, its 2 for the original DeskJet and 4 for
X * the DeskJet PLUS.
X */
X#define NPASS 4
Xstruct char_info {
X	struct cdb mycdb;
X	int cwidth;	/* width in bytes */
X	int cheight;	/* character height */
X	int top_pad;	/* blank rows above character cell */
X	int bottom_pad;	/* blank rows bellow character cell */
X	u_char *flagbytes[NPASS];	/* flag bytes for each pass */
X	int flaglen;			/* size of flagbytes, same on all passes */
X	u_char *databytes[NPASS];	/* data bytes for each pass */
X	int datalen[NPASS];			/* size of databytes for each pass */
X	
X} cinfo[NCHAR];
X
X#define IMG_SIZE	50000
X#define DATA_SIZE	5000
Xstruct header vf_header;
Xstruct dispatch dsp[NUM_DISPATCH];
X#ifdef UNIX
Xu_char imageTable[IMG_SIZE];
Xu_char raster[IMG_SIZE];
Xu_char dataptr[DATA_SIZE];
X#else
Xu_char *imageTable;
Xu_char *raster;
Xu_char *dataptr;
X#endif
Xchar *fontname;
XFILE* printer;	/* file descriptor for printer */
Xu_short font_size;
X
X/* for the DeskJet the value used for dots is 300 despite the
X * fact that the fonts are defined in 600ths of an inch.
X */
X#define DPI 300
X
X/* number of pins on the DeskJet print head */
X#define DJ_CELLHEIGHT 50
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X	int wt = 0;
X	char *sname = "2000V";	/* by default use ESC(2000V to select */
X	char *fname = NULL;
X#ifdef MSDOS
X	char* printername = NULL;
X#endif
X	int isprop = 1;		/* proportional spacing by default */
X	int nofid = 0;		/* do not generate fontid info */
X	int isperm = 1;		/* by default fornts are permanent */
X	int fpitch = -1;
X	int offset = 0;		/* for BSD vfonts that have ascii mapping */
X				/* i.e. 33rd character of vfont is "!" */
X	int fid = 2;		/* a bit arbitrary */
X	int tpface = 30;	/* use an undefined typeface */
X	int i;
X	char *vp;
X	int npass, pass;	/* number of passes per char */
X
X#ifndef UNIX
X	/* allocate things that should have been global!!! */
X	if ((imageTable = malloc(IMG_SIZE)) == NULL)
X	{
X		fprintf(stderr, "Couldn't allocate memory for imageTable\n");
X		exit(1);
X	}
X	if ((raster = malloc(IMG_SIZE)) == NULL)
X	{
X		fprintf(stderr, "Couldn't allocate memory for raster\n");
X		exit(1);
X	}
X	if ((dataptr = malloc(DATA_SIZE)) == NULL)
X	{
X		fprintf(stderr, "Couldn't allocate memory for dataptr\n");
X		exit(1);
X	}
X#endif
X	argv++;
X	argc--;
X	if (argc > 0)	/* process parameters */
X	{
X		while (argc > 0 && **argv == '-')
X		{
X			switch (*(*argv+1)) {
X			case 'T':
X				isperm = 0;
X				argv++;
X				argc--;
X				break;
X			case 'D':
X				nofid = 1;
X				argv++;
X				argc--;
X				break;
X			case 'f':
X				isprop = 0;
X				argv++;
X				argc--;
X				break;
X			case 'p':
X				isprop = 0;	/* force fixed width */
X				fpitch = atoi(*(++argv));
X				argv++;
X				argc -= 2;
X				break;
X			case 'o':
X				offset = atoi(*(++argv));
X				argv++;
X				argc -= 2;
X				break;
X			case 'n':
X				fname = *++argv;
X				argv++;
X				argc -= 2;
X				break;
X#ifndef UNIX
X			case 'F':
X				printername = *++argv;
X				argv++;
X				argc -= 2;
X				break;
X#endif
X			case 's':
X				sname = *++argv;
X				argv++;
X				argc -= 2;
X				break;
X			case 'i':
X				fid = atoi(*(++argv));
X				argv++;
X				argc -= 2;
X				break;
X			case 't':
X				tpface = atoi(*(++argv));
X				argv++;
X				argc -= 2;
X				break;
X			default:
X				usage(1);
X			}
X		}
X	
X		/*
X		 * filename
X		 */
X		if (argc <= 0)
X			usage(2);
X		else {
X			fontname = *argv++;
X			argc--;
X		}
X		if (argc > 0)
X			usage(3);
X	}
X
X	if (nofid)
X		fid = -1;
X#ifdef UNIX
X	/* under unix railmag is just a filter */
X	printer = stdout;
X#else
X	/* under MSDOS we have to go to the printer directly */
X	if (printername == NULL)
X		printername = "PRN:";
X
X	if ((printer = fopen(printername, "wb")) == NULL)
X	{
X		fprintf(stderr, "Could not open printer %s.\n", printername);
X		exit(1);
X	}
X#endif
X
X	loadfont(fontname);
X	myfdb.size = 72;
X	myfdb.ftype = 1;
X	myfdb.cell_height = vf_header.maxy;
X	/* raise cell_height to the next DJ_CELLHEIGHT multiple */
X	myfdb.cell_height += (DJ_CELLHEIGHT-(myfdb.cell_height%DJ_CELLHEIGHT));
X
X	/* baseline is calculated as the the distance from the top of
X	 * the BOTTOM pass for the font.
X	 */
X	if ((myfdb.baseline = calcmaxdown(1, NCHAR)) > DJ_CELLHEIGHT)
X	{
X		fprintf(stderr, "Baseline (%d) greater than DJ_CELLHEIGHT\n",
X			myfdb.baseline);
X		exit(1);
X	}
X	myfdb.baseline = DJ_CELLHEIGHT - myfdb.baseline;
X
X	myfdb.orientation = (fontname[strlen(fontname)-1] == 'r') ? 1 : 0;
X	myfdb.spacing = isprop;
X	myfdb.symbol = symbol_cvt(sname);
X	/*
X	 * if fpitch is specified force cell width and pitch
X	 * otherwise calculate them from the header
X	 */
X	if (fpitch > 0)
X	{
X		myfdb.cell_width = DPI/fpitch;
X		/* multiply by four because these are quater dots */
X		myfdb.pitch = myfdb.cell_width * 4;
X	} else {
X		myfdb.cell_width = vf_header.maxx;
X		/* multiply by four because these are quater dots */
X		myfdb.pitch = dsp['m'].width * 4;
X	}
X	myfdb.height = myfdb.cell_height * 4;
X	myfdb.xHeight = dsp['x'].up * 4;
X	myfdb.w_type = wt;
X	/* following four should really be derived from fontname */
X	myfdb.style = 0;
X	myfdb.str_weight = 0;
X	myfdb.typeface = tpface;
X	myfdb.s_style = 0;
X
X	myfdb.ud_dst = -(dsp['_'].down + 4);
X	myfdb.ud_height = 3;
X	myfdb.t_height = vf_header.maxy * 4;
X	myfdb.t_width = average('a', 'z') * 4;
X	myfdb.ext_pitch = myfdb.ext_height = 0;
X	if (fname != NULL)
X		strncpy(myfdb.fname, fname, MAXNAME);
X	else {
X		/* use basename(fontname) */
X#ifdef BSD
X		vp = rindex(fontname, '/');
X#else
X		vp = strrchr(fontname, '/');
X#endif
X		strncpy(myfdb.fname, (vp != NULL) ? vp+1 : fontname, MAXNAME);
X	}
X
X	/* all the following values are for the DeskJet only */
X	myfdb.slant = 0;	/* ignored */
X	myfdb.quality = 2;	/* letter quality */
X	myfdb.placement = 0;	/* ignored */
X	myfdb.firstcode = offset + 1;
X	myfdb.lastcode = NCHAR;
X	myfdb.hres = 600;	/* horizontal resolution == 600 */
X	myfdb.vres = 300;	/* vertical resolution == 300 */
X	myfdb.ud2_dst = -(dsp['_'].down);
X	myfdb.ud2_height = 3;
X	myfdb.bud_dst = -(dsp['_'].down + 4);
X	myfdb.bud_height = 3;
X	myfdb.psbs = 20;	/* number of subsequent bytes == 20 */
X	myfdb.font_size = 0;	/* fill it up later */
X	myfdb.oneway = 0;	/* bidirectional */
X	myfdb.compressed = 0;	/* no compression info */
X	myfdb.nohalfpitch = 0;	/* allow half pitch */
X	myfdb.nodoublepitch = 0;	/* allow double pitch */
X	myfdb.nohalfheight= 0;	/* allow half height */
X	myfdb.nobold = 0;	/* allow algorithmic bold */
X	myfdb.nodraft = 0;	/* allow draft mode */
X	myfdb.boldmethod = 1;	/* dark bold, if too dark try = 0 */
X	/* now for the tricky fields! */
X	/* since cell_height is a multiple of DJ_CELLHEIGHT: */
X	npass = myfdb.cell_height / DJ_CELLHEIGHT;
X	if (npass <= 2)
X	{
X		myfdb.format = 5;	/* DeskJet type font */
X		myfdb.holdtime = 0;	/* RESERVED == 0 */
X	} else {
X		myfdb.format = 9;	/* DeskJet PLUS type font */
X		myfdb.holdtime = 80;	/* just a guess */
X	}
X	if (npass >= 2)
X		myfdb.baseoff2 = myfdb.baseline + DJ_CELLHEIGHT;
X	else
X		myfdb.baseoff2 = 0;
X/* following fields used by DeskJet PLUS **ONLY** */
X	if (npass >= 3)
X		myfdb.baseoff3 = myfdb.baseline + 2*DJ_CELLHEIGHT;
X	else
X		myfdb.baseoff3 = 0;
X	if (npass >= 4)
X		myfdb.baseoff4 = myfdb.baseline + 3*DJ_CELLHEIGHT;
X	else
X		myfdb.baseoff4 = 0;
X
Xfprintf(stderr, "main: npass=%d, cell_height=%d, baseline=%d\n",
X	npass, myfdb.cell_height, myfdb.baseline);
X	/* convert each character and calculate size of font */
X	/* the numbers for the header come from the deskjet developers
X	 * guide:
X	 *	 +-----------------+--------------+--------------+
X	 *	 | Font type       | <= 128 chars | <= 256 chars |
X	 *	 +-----------------+--------------+--------------+
X	 *	 | fixed, no compr |     320      |     832      |
X	 *	 +-----------------+--------------+--------------+
X	 *	 | fixed, compr    |     448      |    1088      |
X	 *	 +-----------------+--------------+--------------+
X	 *	 | fixed, no compr |     576      |    1344      |
X	 *	 +-----------------+--------------+--------------+
X	 * Here we deal only with 127 char fonts without compression,
X	 * so we have to select between 448 and 576.
X	 */
X	if (isprop)
X		font_size = 576;
X	else
X		font_size = 448;
X
X	for (i = 1; i < NCHAR-offset; i++)
X		font_size += char_cvt(i, npass);
X	myfdb.font_size = font_size;
X
X	/* if DJ+ font divide size by 1024 cause the DJ+ wants Kbytes */
X	if (myfdb.format == 9)
X		myfdb.font_size /= 1024;
X
X	/*
X	 * fid specifies font position, so that more than one font
X	 * can be loaded simultaneously.
X	 */
X	pr_header(fid);
X
X	/*
X	 * BSD vfonts are arranged in ASCII order, i.e. '!' is number 33
X	 * for these fonts offset should be zero!
X	 */
X
X	if (npass == 1)
X		for (i = 1; i < NCHAR-offset; i++)
X			pr_glyph(i, i+offset, 0, 0);
X	else
X		for (pass = 0; pass < npass; pass++)
X			for (i = 1; i < NCHAR-offset; i++)
X				pr_glyph(i, i+offset, npass-pass-1, pass+2);
X
X	pr_trailer(fid, isperm);
X}
X
Xusage(i)
Xint i;
X{
X#ifdef UNIX
X	fprintf(stderr, "usage(%d): railmag [-n name] [-s sname] [-f] [-p nn] [-o nn] [-i fid] fontname\n", i);
X#else
X	fprintf(stderr, "usage(%d): railmag [-n name] [-s sname] [-f] [-p nn] [-o nn] [-i fid]\n\t[-F filename] [-D] fontname\n", i);
X#endif
X	exit(-1);
X}
X
X
X
Xsymbol_cvt(s)
Xchar *s;
X{
X	return((s[strlen(s)-1] - '@') + (atoi(s) * 32));
X}
X
Xcalcmaxdown(st, fin)
Xint st, fin;
X{
X	int i, w;
X	long res;
X
X	res = 0;
X	for (i = st; i <= fin; i++)
X	{
X		w = dsp[i].down;
X		res = (res > w) ? res : w;
X	}
X	return(res);
X}
X
Xaverage(st, fin)
Xint st, fin;
X{
X	int i;
X	long sum;
X
X	sum = 0;
X	for (i = st; i <= fin; i++)
X		sum += dsp[i].width;
X	return(sum/(i-st));
X}
X
Xpr_header(fid)
Xint fid;
X{
X	if (fid >= 0)
X		fprintf(printer, "\033*c%dD", fid);	/* select font */
X	fprintf(printer, "\033)s%dW", FDB_LEN);
X#ifdef MSDOS
X/* swap bytes on all shorts */
X#define vp_swab(X) ((((u_short)X & 0xff) << 8) | (((u_short)X & 0xff00) >> 8))
X	myfdb.size = vp_swab(myfdb.size);
X	myfdb.baseline = vp_swab(myfdb.baseline);
X	myfdb.cell_width = vp_swab(myfdb.cell_width);
X	myfdb.cell_height = vp_swab(myfdb.cell_height);
X	myfdb.symbol = vp_swab(myfdb.symbol);
X	myfdb.pitch = vp_swab(myfdb.pitch);
X	myfdb.height = vp_swab(myfdb.height);
X	myfdb.xHeight = vp_swab(myfdb.xHeight);
X	myfdb.t_height = vp_swab(myfdb.t_height);
X	myfdb.t_width = vp_swab(myfdb.t_width);
X	myfdb.firstcode = vp_swab(myfdb.firstcode);
X	myfdb.lastcode = vp_swab(myfdb.lastcode);
X	myfdb.hres = vp_swab(myfdb.hres);
X	myfdb.vres = vp_swab(myfdb.vres);
X	myfdb.psbs = vp_swab(myfdb.psbs);
X	myfdb.font_size = vp_swab(myfdb.font_size);
X	myfdb.baseoff2 = vp_swab(myfdb.baseoff2);
X	myfdb.baseoff3 = vp_swab(myfdb.baseoff3);
X	myfdb.baseoff4 = vp_swab(myfdb.baseoff4);
X#endif
X	fwrite(&myfdb, FDB_LEN, 1, printer);
X}
X
Xpr_trailer(fid, isperm)
Xint fid, isperm;
X{
X	if (fid < 0)
X		return;
X	if (isperm)
X		fprintf(printer, "\033*c5F");	/* make font permanent, */
X	fprintf(printer, "\033(%dX", fid);	/* and select it */
X}
X
Xint char_cvt(idx, npass)
Xint idx;
Xint npass;
X{
X	int i, j;
X	unsigned char *vp, *cp;
X	int bottom_pad, top_pad, cheight, cwidth;
X	int maxheight, maxbase;
X	int size, band;
Xstatic long int mem = 0L;
X
X	if (dsp[idx].nbytes == 0)
X		return(0);
X
X	cheight = cinfo[idx].cheight = dsp[idx].up + dsp[idx].down;
X	cinfo[idx].mycdb.format = myfdb.format; /* same as the font format */
X	cinfo[idx].mycdb.continuation = 0;	/* always == 0 */
X	cinfo[idx].mycdb.size = 6;		/* always == 6 */
X	/* we leave the type undefined, as it will be filled by pr_glyph */
X	cinfo[idx].mycdb.type = -1;	/* illegal value */
X
X	/* double as its in 600ths of an inch */
X	cinfo[idx].mycdb.width = (dsp[idx].left + dsp[idx].right) * 2;
X	/* flaglen is same as width */
X	cinfo[idx].flaglen =  cinfo[idx].mycdb.width;
X	/* width in whole bytes */
X	cwidth = cinfo[idx].cwidth = (dsp[idx].left + dsp[idx].right + 7) /8;
X	cinfo[idx].mycdb.compr_width = 0;
X	/* double as its in 600ths of an inch */
X	cinfo[idx].mycdb.left_pad = 2 * max(-dsp[idx].left, 0);
X	/* double as its in 600ths of an inch */
X	cinfo[idx].mycdb.right_pad = 0;
X
X	/* bottom_pad is the distance between the bottom of the character
X	 * cell to the bottom of the design cell
X	 */
X	bottom_pad = cinfo[idx].bottom_pad =
X		(DJ_CELLHEIGHT - myfdb.baseline) - dsp[idx].down;
X	/* top_pad is the distance between the top of the character cell
X	 * and the top of the design cell.
X	 */
X	top_pad = cinfo[idx].top_pad =
X		myfdb.cell_height - (cheight + bottom_pad);
X	vp = raster;
X	for (i=0; i<top_pad; i++)
X		for (j=0; j<cwidth; j++)
X			*vp++ = 0;
X	cp = &imageTable[dsp[idx].addr];
X	for (i=0; i<cheight; i++)
X		for (j=0; j<cwidth; j++)
X			*vp++ = *cp++;
X	for (i=0; i<bottom_pad; i++)
X		for (j=0; j<cwidth; j++)
X			*vp++ = 0;
X	/*
X	 * at this stage raster contains the character bitmap
X	 * (row order) correctly centered within the design cell,
X	 */
X	size = CDB_LEN + npass*cwidth;
X	for (band=0; band < npass; band++)
X	{
X		u_char *dp, *fp;
X		int len;
X
X		if ((fp = cinfo[idx].flagbytes[band]= (u_char*)malloc(cinfo[idx].flaglen))==NULL)
X		{
X			fprintf(stderr, "Couldn't allocate flagbytes for char %d\n", idx);
X			fprintf(stderr, "Pass %d, memory given so far = %ld\n", band, mem);
X			exit(1);
X		}
X		mem += cinfo[idx].flaglen;
X		/*
X	 	 * We will now convert the character bitmap
X	 	 * into something acceptable to the DeskJet.
X	 	 * We feed the bitmap to rast_cvt() which creates flag and data
X	 	 * bytes suitable for the DeskJet.
X	 	 */
X		dp = dataptr;
X		/*
X		 * Since we don't know how many databytes will be needed,
X		 * we use a temporary area, and after they have been generated
X		 * we allocate the memory and copy them.
X		 */
X		rast_cvt(raster + band * (DJ_CELLHEIGHT * cwidth),
X			cinfo[idx].mycdb.width/2, cwidth, &dp, &fp);
X			
X		len = cinfo[idx].datalen[band] = dp - dataptr;
X		size += len;
X		if (len > 0)
X		{
X			if ((cinfo[idx].databytes[band] = (u_char*)malloc(len))==NULL)
X			{
X				fprintf(stderr,
X					"Couldn't allocate databytes for char %d\n", idx);
X				fprintf(stderr,
X					"Pass %d, memory given so far = %ld\n", band, mem);
X				exit(1);
X			}
X			mem += len;
X			memcpy(cinfo[idx].databytes[band], dataptr, len);
X		}
X	}
X	/* we now return the memory taken up by this character */
X	return(size);
X}
X
X/*
X * pr_glyph -- send the definition of a character glyph to the printer.
X *
X *	idx is the position of the glyph in the vfont file and
X *	dstidx will be the position that the glyph will occupy
X *	in the downloaded font.
X *	type designates the pass number, while band designates
X *	the band of the design cell corresponding to the current
X *	pass.
X */
Xpr_glyph(idx, dstidx, band, type)
Xint idx, dstidx, band, type;
X{
X	struct char_info *cp;
X
X	if (dsp[idx].nbytes == 0)
X		return;
X
X	cp = &cinfo[idx];
X	cp->mycdb.type = type;
X
X	fprintf(printer, "\033*c%dE", dstidx);
X	fprintf(printer, "\033(s%dW", CDB_LEN+cp->flaglen+cp->datalen[band]);
X	fwrite(&cinfo[idx].mycdb, CDB_LEN, 1, printer);
X	fwrite(cp->flagbytes[band], cp->flaglen, 1, printer);
X	if (cp->datalen[band] > 0)
X		fwrite(cp->databytes[band], cp->datalen[band], 1, printer);
X}
X
X/*
X * rast_cvt -- convert raster to DeskJet format
X * 
X * NOTE: the data in the source raster ARE MODIFIED by rast_cvt!!!
X * Also this routine assumes that character raster is padded so that
X * it its height is exactly equal to the DeskJet cell height (DJ_CELLHEIGHT).
X * 
X * Now some comments:
X * 
X * Think of the raster as a two dimentional array of boxes 1 byte wide
X * and 8 bytes high.  Since our raster is DJ_CELLHEIGHT (==50) bytes high
X * there will be two rows at the bottom that will be left out.  These
X * two rows form a little box.
X * 
X * We now pick each box isolate the most significant bit in each byte.
X * We then use the following scheme to put all those bits in one byte:
X * 
X *		1 A0000000       A0000000
X *		2 B0000000       0B000000
X *		3 C0000000       00C00000  |
X *		4 D0000000 --->  000D0000  |
X *		5 E0000000       0000E000 \|/
X *		6 F0000000       00000F00
X *		7 G0000000       000000G0
X *		8 H0000000       0000000H
X *                		----------
X *                 		 ABCDEFGH
X * We now have the grouped the first column of our box in one byte
X * we then shift all the bytes of that box one bit to the left and
X * repeat the whole process until all the columns of the box have been
X * stored in bytes.  We then move to the next box and so on.
X * 
X * The last two rows are treated similarly.
X */
X
Xrast_cvt(raster, width, cwidth, dataptr, flagptr)
Xu_char *raster;
Xint width;
Xint cwidth;
Xu_char **dataptr;
Xu_char **flagptr;
X{
X	register u_char *vp;
X	register u_char *dp = *dataptr;
X	register u_char *fp = *flagptr;
X	u_char w, flag;
X	int boxes, cols, row;
X	int remw;
X	int i;
X
X	for (remw = width; remw > 0; remw -= 8, raster++)
X		for (cols = 1; cols <= min(8, remw); cols++)
X		{
X			flag = 0;
X			for (row = 0; row < DJ_CELLHEIGHT-2; row += 8)
X			{
X				w = 0;	/* initialize data byte */
X				vp = raster+(row*cwidth);
X				for (i = 0; i <8; i++)
X				{
X					w |= ((*vp & 0x80) >> i);
X					(*vp) <<= 1;	/* move next column to MSB position */
X					vp += cwidth;
X				}
X				flag >>= 1;
X				if (w != 0)
X				{
X					flag |= 0x80;
X					*dp++ = w;
X				}
X			}
X			/* and now the last (little) box */
X			w = (*vp & 0x80);		/* 49th bit */
X			(*vp) <<= 1;
X			vp += cwidth;
X			w |= ((*vp & 0x80) >> 1);	/* 50th bit */
X			(*vp) <<= 1;
X			vp += cwidth;
X			/* here we both set the flag and leave MSBit clear */
X			flag >>= 2;
X			if (w != 0)
X			{
X				flag |= 0x40;
X				*dp++ = w;
X			}
X			*fp++ = flag;
X			*fp++ = 0;		/* leave next column blank */
X		}
X	*flagptr = fp;
X	*dataptr = dp;
X}
X
Xloadfont(fontBuf)
Xchar    *fontBuf;
X{
X	int fd;		/* file handle for vfont file */
X	int i;
X	int len;
X	unsigned int size;
X
X#ifdef UNIX
X	if ((fd = open(fontBuf, O_RDONLY)) < 0)
X#else
X	if ((fd = open(fontBuf, O_RDONLY|O_BINARY)) < 0)
X#endif
X	{
X		fprintf(stderr, "railmag: Could not load font %s\n", fontBuf);
X		exit(1);
X	}
X	fprintf(stderr, "Loaded font %s\n", fontBuf);
X	len = sizeof(struct header);
X	if (read(fd, &vf_header, len) != len)
X	{
X		fprintf(stderr, "railmag: Bad font file header\n");
X		exit(1);
X	}
X	if (vf_header.magic != VFONT_MAGIC)
X	{
X		fprintf(stderr, "railmag: Bad font magic number\n");
X		exit(1);
X	}
X	len = NUM_DISPATCH*sizeof(struct dispatch);
X	if ((i=read(fd, dsp, len)) != len)
X	{
X		fprintf(stderr,
X			"railmag: Could not load font dispatch table\n");
X		fprintf(stderr, "\tlen = %d, read = %d\n", len, i);
X		exit(1);
X	}
X	size = vf_header.size;
X	if (size > IMG_SIZE)
X	{
X		fprintf(stderr, "railmag: image table size (= %u) TOO BIG\n",
X			size);
X		exit(1);
X	}
X	if (read(fd, imageTable, size) != size)
X	{
X		fprintf(stderr, "railmag: Error reading image table\n");
X		exit(1);
X	}
X	return;
X}
END_OF_FILE
if test 21822 -ne `wc -c <'railmag.c'`; then
    echo shar: \"'railmag.c'\" unpacked with wrong size!
fi
# end of 'railmag.c'
fi
if test -f 'vf.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vf.c'\"
else
echo shar: Extracting \"'vf.c'\" \(11787 characters\)
sed "s/^X//" >'vf.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char ScrId[] = "@(#) vfonts.c:1.3";
X#endif
X
X/*****************************************************************
X
X    Copyright 1985. All Rights Reserved Chris Lewis
X
X    Module          : vfonts.c 1.3
X    Date submitted  : 86/01/30 09:19:57
X    Author          : Chris Lewis
X    Origin          : Permission to copy and further distribute is 
X		      freely given provided this copyright notice remains 
X		      intact and that this software is not sold for profit.
X    Description     : Description of the file
X    Modifications:
X
X	- modified to work with the HP DeskJet printer, by maintaining
X	  each line in an internal buffer and then dumping it in one
X	  go.  The original way of printing each character individually
X	  didn't work because the DeskJet cannot reverse feed the paper.
X
X	- added draft-mode printing at 150 dpi.  Problem is that with
X	  the bitmap you just can't mix fonts of different resolutions.
X	  The quick&dirty way out of this is to consider the low-ress
X	  option as binding (i.e. if you start low-res and you don't
X	  have the fonts, your job aborts!).
X
X******************************************************************/
X
X#include <assert.h>
X#include <stdio.h>
X#include <fcntl.h>
X#ifdef UNIX
X#include <ctype.h>
X#include <vfont.h>
X#else
X#include <alloc.h>
X#include <mem.h>
X#include <vp/vfont.h>
X#endif
X#define LCAT
X#include "lcat.h"
X
Xextern FILE	*diagFile;
Xextern FILE	*outFile;
X#define	DEBUGPRINTF	if (diagFile) fprintf
X#define REGISTER	/**/
Xstatic char	*fontFamily;
X#define FONTS	"RIBS"
Xchar	fpos[] = FONTS;
X
X#define STD_DPI 300
Xstatic int	dpi = STD_DPI;
Xstatic int	gl_dpi = STD_DPI;
X
X#define MAX_FONT	3
X#define SPEC_FONT	3
X#define IMG_SIZE	(unsigned int)(50000)
X
Xstatic long xpos = -1;
Xstatic long ypos = -1;
X
Xstatic struct header vf_header;
Xstruct fcache {
X	int fnum;	/* number of cached font (R=0, I=1, B=2, S=3) */
X	int psize;	/* pointsize of font */
X	int count;	/* usage counter for LRU caching */
X	struct dispatch *dsp;	/* font description table */
X	u_char *image;	/* font bitmaps */
X} fontcache[MAX_FONT];
X
X/*
X * following vars hold data for selected font
X */
Xint cfnum, cpsize;
Xstruct dispatch *cdsp;
Xu_char huge* imageTable;
Xint use_count=1;
X
X
X/* raster related definitions */
Xextern u_char raster[NLINES][RASTWIDTH];
X#define TRUE 1
X#define FALSE 0
Xstatic int new_page = TRUE;
Xstatic long y_base;	/* vertical position of baseline for current line */
Xstatic long max_up;	/* max height above baseline of glyphs on current line */
Xstatic long max_down;	/* max depth below baseline of glyphs on cur line */
Xstatic long min_x;	/* left horizontal offset of cur. line */
Xstatic long max_x;	/* rightmost position on current line */
X
X#ifdef NOALLOC
Xchar* vpalloc(i, k)
Xint i, k;
X{
X	int j;
X	static char c;
X
X	j = i;
X	j = k;
X	return(&c);
X}
X#else
X#define vpalloc	calloc
X#endif
X
Xvf_init(quality, ff)
Xint quality;
Xchar* ff;
X{
X	int i, j;
X	u_char huge* vp;
X
X	fontFamily = ff;
X	new_page = TRUE;
X	for (i = 0; i < NLINES; i++)
X		for (j = 0, vp = raster[i]; j < RASTWIDTH; j++)
X			*vp++ = 0;
X	if (quality == 2)
X	{
X		gl_dpi = dpi = 150;
X		fprintf(outFile, "\033*r1Q");
X	} else
X		fprintf(outFile, "\033*r0Q");
X	cfnum = -1;
X	for (i=0; i < MAX_FONT; i++)
X	{
X		fontcache[i].fnum = -1;
X		if ((fontcache[i].dsp = (struct dispatch *)
X			vpalloc(NUM_DISPATCH, sizeof(struct dispatch))) == NULL)
X		{
X			fprintf(stderr, "malloc failed (A, %d)\n", i);
X	
X			exit(1);
X		}
X		if ((fontcache[i].image = (u_char *)
X			vpalloc(IMG_SIZE, 1)) == NULL)
X		{
X			fprintf(stderr, "malloc failed (B, %d)\n", i);
X			exit(1);
X		}
X	}
X}
X
X/*
X *	loadfont -- load vfont
X *
X */
Xloadfont(fnum, psize)
Xint fnum, psize;
X{
X	int i, c, sel;
X
X	if (cfnum == fnum && cpsize == psize)
X		return;
X	for (i=0; i < MAX_FONT; i++)
X	{
X		if (fontcache[i].fnum == fnum && fontcache[i].psize == psize)
X		{
X			cfnum = fnum;
X			cpsize = psize;
X			cdsp = fontcache[i].dsp;
X			imageTable = fontcache[i].image;
X			fontcache[i].count = use_count++;
X			return;
X		}
X	}
X	/* not in cached set => load in place of LRU font */
X	c = use_count;
X	sel = -1;
X	for (i=0; i < MAX_FONT; i++)
X	{
X		if (fontcache[i].count < c)
X		{
X			c = fontcache[i].count;
X			sel = i;
X		}
X	}
X	assert(sel != -1);
X	getfont(fnum, psize, sel);
X	/* recursively call loadfont to properly select the
X	 * font we've just loaded.  i.e. retry loadfont operation
X	 */
X	loadfont(fnum, psize);
X}
X
X
Xgetfont(fnum, psize, position)
Xint fnum, psize, position;
X{
X	static char fontBuf[BUFSIZ];
X	int fd;		/* file handle for vfont file */
X	int i;
X	unsigned int len;
X
X	assert(fnum <= (strlen(FONTS)-1));
X#ifdef UNIX
X	sprintf(fontBuf, "%s%c.%d", fontFamily, tolower(fpos[fnum]), psize);
X	if ((fd = open(fontBuf, O_BINARY|O_RDONLY)) < 0)
X	{
X		sprintf(fontBuf, "%s%c.%d", fontFamily, fpos[fnum], psize);
X		if ((fd = open(fontBuf, O_BINARY|O_RDONLY)) < 0)
X		{
X			fprintf(stderr,
X				"lcat: Could not load font %s\n", fontBuf);
X			exit(1);
X		}
X	}
X#else
X	sprintf(fontBuf, "%s%c.%d", fontFamily, fpos[fnum], psize);
X
X	if ((fd = open(fontBuf, O_BINARY|O_RDONLY)) < 0)
X	{
X		fprintf(stderr, "lcat: Could not load font %s\n", fontBuf);
X		exit(1);
X	}
X#endif
X	DEBUGPRINTF(diagFile, "Loaded font %s (dpi: %d)\n", fontBuf, gl_dpi);
X	fprintf(stderr, "Loaded font %s (dpi: %d)\n", fontBuf, gl_dpi);
X	len = sizeof(struct header);
X	if (read(fd, &vf_header, len) != len)
X	{
X		fprintf(stderr, "lcat: Bad font file header\n");
X		exit(1);
X	}
X	if (vf_header.magic != VFONT_MAGIC)
X	{
X		fprintf(stderr, "lcat: Bad font magic number\n");
X		exit(1);
X	}
X	len = NUM_DISPATCH*sizeof(struct dispatch);
X	if (read(fd, fontcache[position].dsp, len) != len)
X	{
X		fprintf(stderr, "lcat: Could not load font dispatch table\n");
X		exit(1);
X	}
X	len = vf_header.size;
X	if (len > IMG_SIZE)
X	{
X		fprintf(stderr, "lcat: image table size (= %u) TOO BIG\n", len);
X		exit(1);
X	}
X	if ((unsigned)read(fd, fontcache[position].image, len) != len)
X	{
X		fprintf(stderr, "lcat: Error reading image table\n");
X		exit(1);
X	}
X	close(fd);
X	fontcache[position].fnum = fnum;
X	fontcache[position].psize = psize;
X	return;
X}
X
X#define CAT_L	'\004'
X#define CAT_I	'\005'
X#define CAT_F	'\013'
X#define CAT_FI	'\0122'
X#define CAT_FL	'\0123'
X#define CAT_FF	'\0124'
X#define CAT_FFL	'\0126'
X#define CAT_FFI	'\0127'
X
Xflashrast(ch, ps, ftype)
Xint	ch, ps, ftype;
X{
X	int up, down, left, right;
X	register int idx;
X	register int i,j,H,V;
X	u_char huge *bp;
X	u_char huge *vp;
X	int points;
X	long x;
X	long oxpos;
X
X	points = (gl_dpi == 150) ? ps>>1: ps;
X	if (ftype != cfnum || points != cpsize)
X		loadfont(ftype, points);
X
X	idx = (ftype==SPEC_FONT) ? spectab[ch] : asctab[ch];
X	/*
X	 * composite glyphs ff, fi, fl, ffi, ffl get special treatment
X	 * since they are not available on all fonts.
X	 * If we don't have the glyph, we call flashrast recursivelly
X	 * until all but the last characters making up the composite
X	 * glyph have been printed.  Then we continue executing
X	 * flashrast with the last character.
X	 */
X	if (ftype != SPEC_FONT)
X		switch (ch) {
X		case CAT_FFI:
X			if (cdsp[idx].nbytes > 0)
X				break;
X			flashrast(CAT_F, ps, ftype);
X			idx = asctab[CAT_F];
X			xpos += cdsp[idx].width;
X			idx = asctab[CAT_FI];
X			/* NOTE --> NO BREAK HERE */
X		case CAT_FI:
X			if (cdsp[idx].nbytes > 0)
X				break;
X			flashrast(CAT_F, ps, ftype);
X			idx = asctab[CAT_F];
X			xpos += cdsp[idx].width;
X			idx = asctab[CAT_I];
X			break;
X		case CAT_FFL:
X			if (cdsp[idx].nbytes > 0)
X				break;
X			flashrast(CAT_F, ps, ftype);
X			idx = asctab[CAT_F];
X			xpos += cdsp[idx].width;
X			idx = asctab[CAT_FL];
X			/* NOTE --> NO BREAK HERE */
X		case CAT_FL:
X			if (cdsp[idx].nbytes > 0)
X				break;
X			flashrast(CAT_F, ps, ftype);
X			idx = asctab[CAT_F];
X			xpos += cdsp[idx].width;
X			idx = asctab[CAT_L];
X			break;
X		case CAT_FF:
X			if (cdsp[idx].nbytes > 0)
X				break;
X			flashrast(CAT_F, ps, ftype);
X			idx = asctab[CAT_F];
X			xpos += cdsp[idx].width;
X			break;
X		}
X#ifdef VERBOSE
X	if (idx >= ' ' && idx <= 126)
X		putchar(idx);
X#endif VERBOSE
X	up = cdsp[idx].up;
X	down = cdsp[idx].down;
X	left = cdsp[idx].left;
X	right = cdsp[idx].right;
X	V = up + down;
X	H = (left + right + 7) / 8;
X	bp = imageTable + cdsp[idx].addr;
X	DEBUGPRINTF(diagFile, "ch=%d,fnt=%d,idx=%d,V=%d,H=%d\n", ch, ftype, idx, V, H);
X	x = xpos + left + right;
X	max_x = MAX(max_x, x);
X	max_up = MAX(max_up, up);
X	max_down = MAX(max_down, down);
X	oxpos = xpos;
X	xpos -= left;
X	min_x = MIN(min_x, xpos);
X	DEBUGPRINTF(diagFile, "y_base=%ld,min_x=%ld,max_x=%ld,max_up=%ld,max_down=%ld\n",
X		y_base, min_x, max_x, max_up, max_down);
Xvp=&raster[BASELINE - up][(int)(xpos >> 3)]; DEBUGPRINTF(diagFile, "\ttop of cell %lx\n", vp);
X	DEBUGPRINTF(diagFile, "vp = %lx, xposMOD8= %d, xpos = %ld, V=%d, H=%d, bp=%lx\n", vp, (int)(xpos%8), xpos, V, H, bp);
X	for (i = 0; i < V; i++, bp+=H)
X	{
X		vp = &raster[BASELINE - up + i][(int)(xpos >> 3)];
X		bit_move(vp, (int)(xpos%8), bp, H);
X	}
X	xpos = oxpos;
X}
X
X/*
X *	print_raster -- we print the raster from y_base-max_up to
X *	y_base+max_down
X */
Xprint_raster()
X{
X	long l_width;	/* width of line in bytes */
X	int i,j;
X	u_char huge* vp;
X	long lx, ly;
X#ifndef LASERJET
X#define MAX_REP_COUNT	128
X	int count, offset;
X	char c;
X#endif
X
X#ifdef VERBOSE
X	putchar('\n');
X#endif VERBOSE
X	lx = min_x*720L/dpi;
X	ly = (y_base-max_up)*720L/dpi;
X	fprintf(outFile, "\033&a%ldh%ldV", lx, ly);
X	l_width = ((max_x - min_x + 7) / 8) + 1;
X	DEBUGPRINTF(diagFile, "move(%ld, %ld), l_width=%ld\n", lx, ly, l_width);
X	if (l_width >= RASTWIDTH)
X	{
X		fprintf(stderr, "print_raster: l_width(%ld) exceeds RASTWIDTH\n",
X			l_width);
X		exit(1);
X	}
X	fprintf(outFile, "\033*t%dR\033*r%ldS", dpi, l_width<<3);
X	fprintf(outFile, "\033*r1A");
X	for (i = BASELINE - max_up; i <= BASELINE + max_down; i++)
X	{
X		vp = &raster[i][min_x >> 3];
X		DEBUGPRINTF(diagFile, "printing line %lx\n", vp);
X#ifdef LASERJET
X		fprintf(outFile, "\033*b%ldW", l_width);
X		fwrite((void *)vp, l_width, 1, outFile);
X#ifdef BSD
X		bzero(vp, l_width);
X#else
X		memset((void *)vp, '\0', l_width);
X#endif
X#else
X		for (offset = 0; offset < l_width;)
X		{
X			for (count = 0, c = *vp;
Xc == *vp && offset < l_width && count < MAX_REP_COUNT; offset++, count++)
X				*vp++ = 0;
X			if (count <= 1)
X				push_buf(c);
X			else {
X				flush_buf();
X				multiprint(c, count);
X			}
X		}
X		flush_outbuf();
X#endif
X#ifdef XXX
X		for (j = 0; j < l_width; j++)
X		{
X			putc(*vp, outFile);
X			*vp++ = 0;	/* ready raster for next pass */
X		}
X#endif XXX
X	}
X	fprintf(outFile, "\033*rB");
X}
X
Xvf_move(x, y)
Xlong x, y;
X{
X	xpos = x * dpi/720;
X	ypos = y * dpi/720;
X
X	if (new_page || (y_base != ypos))
X	{
X		if (new_page)
X			new_page = FALSE;
X		else
X			print_raster();
X		y_base = ypos;
X		max_up = max_down = 0;
X		min_x = max_x = xpos;
X	}
X}
X
Xvf_newpage()
X{
X	new_page = TRUE;
X	print_raster();
X	putc('\f', outFile);
X	fflush(outFile);
X}
X
Xprt(s, vp, nb, nl)
Xchar *s;
Xu_char huge* vp;
Xint nb, nl;
X{
X	int i;
X
X	DEBUGPRINTF(diagFile, "%s= ", s);
X	for(i=0; i< nb; i++)
X		DEBUGPRINTF(diagFile, "%2x, ", *vp++);
X	if (nl)
X		DEBUGPRINTF(diagFile, "%2x\n", *vp);
X	else
X		DEBUGPRINTF(diagFile, "%2x\t", *vp);
X}
X
X#ifndef LASERJET
X/*
X * routines used with the DeskJet graphics compression scheme
X */
X#define MAXBUF 400
Xchar out_buffer[MAXBUF];
Xchar *outbuf = out_buffer;
Xint outoff = 0;
X
Xflush_outbuf()
X{
X	flush_buf();
X	fprintf(outFile, "\033*b2m%dW", outoff);
X	fwrite(out_buffer, outoff, 1, outFile);
X	outbuf = out_buffer;
X	outoff = 0;
X}
X
X#define PUSHBUFLEN MAX_REP_COUNT
Xchar pushbuf[PUSHBUFLEN];
Xint pushoff = 0;
X
Xpush_buf(c)
Xchar c;
X{
X	pushbuf[pushoff++] = c;
X	if (pushoff >= PUSHBUFLEN)
X		flush_buf();
X}
X
Xmultiprint(c, count)
Xchar c;
Xint count;
X{
X	*outbuf++ = -(count-1);
X	*outbuf++ = c;
X	outoff += 2;
X}
X
Xflush_buf()
X{
X	if (pushoff == 0)
X		return;
X	assert(outoff+pushoff+1 < MAXBUF);
X	*outbuf++ = pushoff-1;
X#ifdef BSD
X	bcopy(pushbuf, outbuf, pushoff);
X#else
X	memcpy(outbuf, pushbuf, pushoff);
X#endif
X	outbuf += pushoff;
X	outoff += (pushoff + 1);
X	pushoff = 0;
X}
X#endif /* !LASERJET */
X
END_OF_FILE
if test 11787 -ne `wc -c <'vf.c'`; then
    echo shar: \"'vf.c'\" unpacked with wrong size!
fi
# end of 'vf.c'
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    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



More information about the Comp.sources.misc mailing list