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