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