vp@cui.unige.ch (08/31/90)
Posting-number: Volume 14, Issue 73 Submitted-by: vp@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@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@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