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 4 of 6) Message-ID: Date: 13 Nov 89 21:22:58 GMT Sender: news@crdgw1.crd.ge.com Reply-To: (Skip Montanaro) Organization: GE Corporate Research & Development, Schenectady, NY Lines: 1387 #! /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/getopt.c <<'END_OF_lib/getopt.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/* X * getopt - get option letter from argv X * (From Henry Spencer @ U of Toronto Zoology, slightly edited) X */ X X#include X Xchar *optarg; /* Global argument pointer. */ Xint optind; /* Global argv index. */ X Xstatic char *scan; /* Private scan pointer. */ X Xextern char *index(); X Xint Xgetopt(argc, argv, optstring) X register int argc; X register char **argv; X char *optstring; X{ X register int c; X register char *place; X X optarg = NULL; X if (scan == NULL || *scan == 0) { X if (optind == 0) X optind++; X if (optind >= argc || argv[optind][0] != '-' || X argv[optind][1] == 0) X return (EOF); X if (strcmp(argv[optind], "--") == 0) { X optind++; X return (EOF); X } X scan = argv[optind] + 1; X optind++; X } X c = *scan++; X place = index(optstring, c); X X if (place == NULL || c == ':') { X fprintf(stderr, "%s: unknown option -%c\n", argv[0], c); X return ('?'); X } X place++; X if (*place == ':') { X if (*scan != '\0') { X optarg = scan; X scan = NULL; X } else { X if (optind >= argc) { X fprintf(stderr, X "%s: missing argument after -%c\n", X argv[0], c); X return ('?'); X } X optarg = argv[optind]; X optind++; X } X } X return (c); X} END_OF_lib/getopt.c if test 1380 -ne `wc -c lib/gfclass.c <<'END_OF_lib/gfclass.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/gfclass.c,v 1.3 89/02/13 14:31:07 grunwald Exp Locker: grunwald $"; X#endif X X/* X * gfclass - GF code classification tables. X */ X X#include "gfclass.h" X X/* shorthand---in lowercase for contrast (read on!) */ X#define three(x) x, x, x X#define four(x) x, x, x, x X#define five(x) four(x), x X#define six(x) four(x), x, x X#define eight(x) four(x), four(x) X#define sixteen(x) eight(x), eight(x) X#define thirty_two(x) sixteen(x), sixteen(x) X#define sixty_four(x) thirty_two(x), thirty_two(x) X#define one_twenty_eight(x) sixty_four(x), sixty_four(x) X#define one_sixty_five(x) one_twenty_eight(x), thirty_two(x), five(x) X X/* X * Length of the single (or first) operand, if any. X */ Xchar gf_oplen[256] = { X sixty_four(GPL_NONE), /* GF_PAINT_0 through GF_PAINT_63 */ X GPL_UNS1, /* GF_PAINT1 */ X GPL_UNS2, /* GF_PAINT2 */ X GPL_UNS3, /* GF_PAINT3 */ X GPL_NONE, /* GF_BOC */ X GPL_NONE, /* GF_BOC1 */ X GPL_NONE, /* GF_EOC */ X GPL_NONE, /* GF_SKIP0 */ X GPL_UNS1, /* GF_SKIP1 */ X GPL_UNS2, /* GF_SKIP2 */ X GPL_UNS3, /* GF_SKIP3 */ X one_sixty_five(GPL_NONE),/* GF_NEW_ROW_0 through GF_NEW_ROW_164 */ X GPL_UNS1, /* GF_XXX1 */ X GPL_UNS2, /* GF_XXX2 */ X GPL_UNS3, /* GF_XXX3 */ X GPL_SGN4, /* GF_XXX4 */ X GPL_SGN4, /* GF_YYY */ X GPL_NONE, /* GF_NOP */ X GPL_NONE, /* GF_CHAR_LOC */ X GPL_NONE, /* GF_CHAR_LOC0 */ X GPL_NONE, /* GF_PRE */ X GPL_NONE, /* GF_POST */ X GPL_NONE, /* GF_POSTPOST */ X six(GPL_NONE) /* 250 through 255 */ X}; X X/* X * Types of the various opcodes. X */ Xchar gf_gt[256] = { X sixty_four(GT_PAINT0), /* GF_PAINT_0 through GF_PAINT_63 */ X three(GT_PAINT), /* GF_PAINT1 through GF_PAINT3 */ X GT_BOC, /* GF_BOC */ X GT_BOC1, /* GF_BOC1 */ X GT_EOC, /* GF_EOC */ X GT_SKIP0, /* GF_SKIP0 */ X three(GT_SKIP), /* GF_SKIP1 through GF_SKIP3 */ X one_sixty_five(GT_NEW_ROW),/* GF_NEW_ROW_0 throgh GF_NEW_ROW_164 */ X four(GT_XXX), /* GF_XXX1 through GF_XXX4 */ X GT_YYY, /* GF_YYY */ X GT_NOP, /* GF_NOP */ X GT_CHAR_LOC, /* GF_CHAR_LOC */ X GT_CHAR_LOC0, /* GF_CHAR_LOC0 */ X GT_PRE, /* GF_PRE */ X GT_POST, /* GF_POST */ X GT_POSTPOST, /* GF_POSTPOST */ X six(GT_UNDEF) /* 250 through 255 */ X}; END_OF_lib/gfclass.c if test 2408 -ne `wc -c lib/gffont.c <<'END_OF_lib/gffont.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/gffont.c,v 1.4 89/02/13 14:31:08 grunwald Exp Locker: grunwald $"; X#endif X X#include X#include X#include X#include "types.h" X#include "font.h" X#include "gfcodes.h" X#include "gfclass.h" X#include "num.h" X X/* X * GF font operations. X * X * GF files may be compact, but this code surely is not! X * X * TODO: X * think about fonts with characters outside [0..255] X * find some way to free gf body when done X */ X Xstatic gf_read(); Xstatic gf_getgly(); Xstatic gf_rasterise(); Xstatic gf_freefont(); X Xstruct fontops gfops = X { "gf", 1.0, gf_read, gf_getgly, gf_rasterise, gf_freefont }; X X/* X * Local info. X */ X X/* X * A bounding box. The names follow those in the GF documentation. X */ Xstruct bounds { X i32 min_m, max_m; /* min and max `m' (colunm) values */ X i32 min_n, max_n; /* min and max `n' (row) values */ X}; X X/* X * char_loc is one `character locator' from a GF file, save for the X * `character residue', which we need not. X */ Xstruct char_loc { X i32 cl_dx; /* x escapement (scaled pixels) */ X i32 cl_dy; /* y escapement (scaled pixels) */ X i32 cl_w; /* TFM width */ X i32 cl_p; /* pointer to BOC (or specials) */ X}; X X/* X * GF details include: X * -> the main body of the GF file (all bytes save pre- and post-amble); X * -> global box boundaries; X * and character locators, addressed by `character residue'. Empty X * slots are indicated by a -1 `pointer'. X */ Xstruct gf_details { X char *gd_body; /* GF body */ X char *gd_base; /* == gd_body - preamble_size */ X struct bounds gd_gb; /* global boundaries */ X struct char_loc gd_cl[256]; /* character locators */ X}; X X/* X * Get the gf_details from font f. X */ X#define ftogd(f) ((struct gf_details *) (f)->f_details) X Xextern int errno; Xchar *malloc(), *copyit(); X Xstatic int gf_read(); Xstatic int gf_read(); Xstatic int gf_rasterise(); Xstatic int gf_freefont(); X X/* X * I am making the assumption that 530 bytes will always be enough X * to find the end of the GF file. 12 should suffice, as there X * should be at most seven GF_FILLER bytes, preceded by the GF ID, X * preceded by the four byte postamble pointer; but at least one X * VMS TeX pads pads DVI files to a full `sector', so I am assuming X * it may do the same to GF files. X */ X#ifdef vms X#define POSTSIZE 530 /* make only VMS pay for its ways; */ X#else X#define POSTSIZE 16 /* others get to use something reasonable */ X#endif X X/* X * Find the GF postamble. Store the offsets of the POST and POSTPOST X * opcodes through postp and postpostp. X */ Xstatic XfindGFpostamble(fd, postp, postpostp) X int fd; X long *postp, *postpostp; X{ X register long offset; X register char *p; X register int i; X register i32 n; X char postbuf[POSTSIZE]; X X /* X * Avoid lseek()ing beyond beginning of file; it may give odd X * results. Read the last POSTSIZE bytes (or however many we X * can get). X */ X offset = lseek(fd, 0L, 2) - (long) POSTSIZE; X if (offset < 0L) X offset = 0L; X (void) lseek(fd, offset, 0); X i = read(fd, postbuf, POSTSIZE); X if (i <= 0) X return (-1); X p = &postbuf[i]; X i -= 4; /* account for the pointer in advance */ X X /* X * Now search backwards for the GF_ID byte. The postamble X * pointer will be four bytes behind that. X */ X while (--i >= 0) { X if (UnSign8(*--p) == GF_ID) X goto foundit; X if (UnSign8(*p) != GF_FILLER) X break; X } X return (-1); /* cannot find postamble ptr */ X Xfoundit: X /* X * Store the (presumed) position of the POSTPOST byte, which X * is i-1 bytes beyond `offset'. X */ X *postpostp = offset + i - 1; X X /* X * Read out the postamble pointer and seek to the postamble, X * also saving the offset. X */ X p -= 4; X pGetLong(p, n); X *postp = offset = n; X (void) lseek(fd, offset, 0); X return (0); /* made it */ X} X X/* X * Read a GF file. X */ Xstatic int Xgf_read(f) X register struct font *f; X{ X register struct gf_details *gd; X register char *p; X register struct char_loc *cl; X register int i; X int fd, presize, postsize, bodysize, firstc, lastc; X char *postamble; X long postaddr, postpostaddr; X i32 lasteoc; X char *problem = NULL; X struct stat st; X char b[4]; X int saverr; X X if ((fd = open(f->f_path, 0)) < 0) X return (-1); X gd = NULL; /* prepare for failure */ X postamble = NULL; X X /* X * The file had best be at least 50 bytes long. A X * `completely empty' GF file might consist of a PRE, a GF_ID, X * no comment (one zero byte), then: POST, pointer to last X * EOC, design size, checksum, hppp, vppp, min_m, max_m, X * min_n, max_n, POSTPOST, pointer to POST, GF_ID, and four X * FILLERs. X */ X (void) fstat(fd, &st); X if (st.st_size < 50) { /* too small to be a GF file */ X problem = "file is too short"; X goto fail; X } X X /* X * Read the very beginning and pick up the preamble size. X */ X if (read(fd, b, 4) != 4) X goto fail; X if (UnSign8(b[0]) != GF_PRE) { X problem = "file does not begin with PRE"; X goto fail; X } X i = UnSign8(b[1]); X if (i != GF_ID) X error(0, 0, "Warning: strange GF id (%d) in \"%s\"", i, X f->f_path); X presize = 3 + UnSign8(b[2]); X X /* X * Find the postamble, allocate space, and read it in. X */ X if (findGFpostamble(fd, &postaddr, &postpostaddr)) { X problem = "cannot find postamble"; X goto fail; X } X postsize = postpostaddr - postaddr + 1; X if ((p = malloc(postsize)) == NULL) X goto fail; X if (read(fd, p, postsize) != postsize) X goto fail; X postamble = p; X X /* X * Make sure we found it. X */ X if (pgetbyte(p) != GF_POST) { X problem = "no GF_POST at postamble"; X goto fail; X } X X /* X * Looks okay. Allocate detail space and poke through the postamble. X */ X if ((gd = (struct gf_details *) malloc(sizeof (*gd))) == NULL) X goto fail; X gd->gd_body = NULL; X X pGetLong(p, lasteoc); /* actually one past last EOC */ 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 X pGetLong(p, gd->gd_gb.min_m); X pGetLong(p, gd->gd_gb.max_m); X pGetLong(p, gd->gd_gb.min_n); X pGetLong(p, gd->gd_gb.max_n); X X /* X * Zap all the character locators, then read those that are X * defined in the postamble. Remember the first and last X * characters so that we know which glyphs are defined. Lastc X * is actually the last-plus-one'th character. X */ X for (cl = gd->gd_cl, i = 256; --i >= 0; cl++) X cl->cl_p = -1; X firstc = 256; X lastc = 0; X for (;;) { X i32 dx, dy; X X switch (pgetbyte(p)) { X X case GF_CHAR_LOC: X i = pgetbyte(p); X pGetLong(p, dx); X pGetLong(p, dy); X goto merge; X X case GF_CHAR_LOC0: X i = pgetbyte(p); X dx = ((i32) pgetbyte(p)) << 16; X dy = 0; Xmerge: X if (i < firstc) X firstc = i; X if (i >= lastc) X lastc = i + 1; X cl = &gd->gd_cl[i]; X cl->cl_dx = dx; X cl->cl_dy = dy; X pGetLong(p, cl->cl_w); X pGetLong(p, cl->cl_p); X break; X X case GF_POSTPOST: X goto done; X X default: X error(0, 0, "I do not understand %d here", X UnSign8(p[-1])); X problem = "unexpected opcode in postamble"; X goto fail; X } X } Xdone: X free(postamble); X postamble = NULL; /* all done with it */ X X /* X * Alas, we need the instructions whether or not we need X * the rasters, since the raster bounding box information X * can only be properly determined by converting the rasters. X * Compute the size of the main body of the GF file, then X * read it in. X */ X bodysize = lasteoc - presize; X if ((gd->gd_body = malloc(bodysize + 1)) == NULL) X goto fail; X (void) lseek(fd, (long) presize, 0); X if (read(fd, gd->gd_body, bodysize) != bodysize) X goto fail; X /* X * The next byte might be a special, so we just X * arbitrarily stuff in a POST. X */ X gd->gd_body[bodysize] = GF_POST; X gd->gd_base = gd->gd_body - presize; X X f->f_details = (char *) gd; X if (FontHasGlyphs(f, firstc, lastc)) X goto fail2; X (void) close(fd); X return (0); X Xfail: X if (problem == NULL) X error(0, errno, "trouble reading \"%s\"", f->f_path); X else X error(0, 0, "%s\n\t(are you sure \"%s\" is a GF file?)", X problem, f->f_path); X errno = 0; Xfail2: X saverr = errno; X if (postamble != NULL) { X free(postamble); postamble = 0; X } X if (gd != NULL) { X if (gd->gd_body != NULL) { X free(gd->gd_body); gd -> gd_body = 0; X } X free((char *) gd); gd = 0; X } X (void) close(fd); X errno = saverr; X return (-1); X} X X/* X * Some global variables, used while building rasters. (These are X * referenced also in copyit(), so must be global. Fortunately, no X * one yet requires the font routines to be re-entrant.) X */ Xstatic char *buildraster; /* raster being built */ Xstatic int buildsize; /* size of buildraster (bytes) */ X Xstatic struct bounds tempb; /* bounds used during buildraster */ Xstatic struct bounds ob; /* observed bounds */ X X/* X * Bit tables: `left' and `right' bits. lbits[b] has all the bits X * that are to the left of bit b set; rbits[b] has all the bits X * that are to the right of bit b set, as well as bit b itself. X */ Xstatic char lbits[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe }; Xstatic char rbits[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; X X/* X * The magic address `nullraster' is known in getgly() as a valid X * but empty raster, and changed there to NULL. A NULL return from X * drawchar indicates failure; we need something to distinguish the X * empty raster. X */ Xstatic char nullraster[1]; X X/* X * `Inline functions': X * -> convert a bit number to a byte number (round down); X * -> convert a number of bits to a number of bytes (round up); X * and convert a bit to a bit index. X */ X#define btoby(b) ((b) >> 3) X#define btonb(b) (((b) + 7) >> 3) X#define btobi(b) ((b) & 7) X X/* X * Helper function for getgly: build the raster, and compute its X * minimal bounding box. Called with `p' pointing past the backpointer X * field of the BOC command (i.e., at min_m or del_m). `abbrev' is true X * iff this was a BOC1. `globalb' are the global bounds from the GF file, X * whose name is pointed to by gfname. X */ Xstatic char * Xdrawchar(p, abbrev, globalb, gfname) X register char *p; X int abbrev; X struct bounds globalb; X char *gfname; X{ X register i32 m; /* m register (column) */ X register char *colp; /* pointer to byte corresponding to m */ X register int c; /* temporary */ X register i32 i; /* temporary */ X register int black; /* true when paint_switch==black */ X register i32 n; /* n register (row) */ X int stride; /* multiplier to convert linear to 2d array */ X int wrotethisrow; /* true iff we wrote in the current row */ X char *virtrast; /* virtual origin version of buildraster */ X int mustcopy; /* true if we must copy the built raster */ X struct bounds gb; /* bounds from the GF file */ X X /* get the bounds */ X if (abbrev) { X c = pgetbyte(p);/* del_m */ X gb.min_m = (gb.max_m = pgetbyte(p)) - c; X c = pgetbyte(p);/* del_n */ X gb.min_n = (gb.max_n = pgetbyte(p)) - c; X } else { X pGetLong(p, gb.min_m); X pGetLong(p, gb.max_m); X pGetLong(p, gb.min_n); X pGetLong(p, gb.max_n); X } X X /* X * Trim the GF bounds according to the global bounds. We X * use the trimmed values to allocate the build space. X */ X tempb = gb; X#define GB_ADJ(field, cmp) \ X if (tempb.field cmp globalb.field) \ X tempb.field = globalb.field X GB_ADJ(min_m, <); X GB_ADJ(max_m, >); X GB_ADJ(min_n, <); X GB_ADJ(max_n, >); X#undef GB_ADJ X X /* X * Compute the distance between rows (the number of bytes per X * column), then make sure there is room in the build space X * for [min_n..max_n] of these, possibly by allocating a new raster. X */ X stride = btonb(tempb.max_m - tempb.min_m + 1); X c = stride * (tempb.max_n - tempb.min_n + 1); X if (c <= 0) /* completely empty character */ X return (nullraster); X if (c > buildsize) { X if (buildraster != NULL) { X free(buildraster); buildraster = 0; X } X if ((buildraster = malloc(c)) == NULL) { X buildsize = 0; X return (NULL); X } X buildsize = c; X } X X /* X * If we are using an old raster that is too big, remember to X * scrunch it down later. X */ X mustcopy = buildsize > c; X X /* clear the raster to white */ X bzero(buildraster, c); X X /* X * Make a virtual origin raster pointer. The virtual origin is X * where raster[0][0] is, whether or not there is a raster[0][0]. X * Normally, this would be X * &buildraster[-gb.min_n * stride - btoby(gb.min_m)], X * but it is complicated by two things. Firstly, we would like X * n==max_n to be the bottommost point in the raster (low X * addresses), and n==min_n to be the topmost (high addresses). X * In other words, we need to reflect the n (Y) values about X * the X axis: negate them. Secondly, the raster we create X * must be `flush left'. That is, somewhere along its rows, X * bit 0x80 must be set at the left edge of one of its columns. X * We need to subtract away the minimum bit index before X * calculating bit values. This cannot really be done in X * advance, since we cannot address bits directly. X */ X virtrast = &buildraster[gb.max_n * stride]; X X /* X * Set up the bounds-trimming variables. The observed m bounds X * are kept offset by gb.min_m until we finish drawing the X * character. X */ X ob.min_m = tempb.max_m - gb.min_m + 1; X ob.max_m = tempb.min_m - gb.min_m - 1; X ob.min_n = tempb.max_n + 1; X ob.max_n = tempb.min_n - 1; X wrotethisrow = 0; X X#define FIX_N_BOUNDS() { \ X if (wrotethisrow) { \ X c = -n; /* recall that n is reflected about X axis */ \ X if (c < ob.min_n) \ X ob.min_n = c; \ X if (c > ob.max_n) \ X ob.max_n = c; \ X wrotethisrow = 0; \ X } \ X} X X /* X * Initialise state variables: m = min_m, n = max_n, X * paint_switch = white. X */ X m = 0; /* gb.min_m - gb.min_m */ X n = -gb.max_n; /* reflected */ X colp = &virtrast[n * stride]; Xif (colp != buildraster) Xpanic("gffont drawchar colp != buildraster"); X black = 0; X X /* X * Now interpret the character. X * `for (;;)' pushes everything off the right edge, alas. X */ Xmore: X c = pgetbyte(p); X if (GF_IsPaint(c)) /* faster? */ X goto paint; X switch (GF_OpLen(c)) { X X case GPL_NONE: X break; X X case GPL_UNS1: X i = pgetbyte(p); X break; X X case GPL_UNS2: X pGetWord(p, i); X break; X X case GPL_UNS3: X pGet3Byte(p, i); X break; X X case GPL_SGN4: X pGetLong(p, i); X break; X X default: X panic("gffont drawchar GF_OpLen(%d) = %d", c, GF_OpLen(c)); X /* NOTREACHED */ X } X X switch (GF_TYPE(c)) { X X case GT_PAINT0: Xpaint: X i = c - GF_PAINT_0; X /* FALLTHROUGH */ X X case GT_PAINT: X /* X * Paint `i' bits in the current row at columns [m..m+i). X */ X if (i && black) { X /* remember to adjust n bounds later */ X wrotethisrow = 1; X /* adjust minimum m bound */ X if (m < ob.min_m) X ob.min_m = m; X X /* X * Finish the partial byte at colp. There are 8-k X * bits to set to finish it, where k is the bit X * index value from m. If we need to set fewer X * than 8-k bits, set them now and skip the rest X * of this. X */ X c = 8 - btobi(m); X if (i < c) { /* cannot finish it off */ X *colp |= UnSign8(lbits[i]) >> btobi(m); X m += i; X } else { /* finish it off */ X *colp++ |= rbits[btobi(m)]; X i -= c; X m += c; X X /* X * Update m to reflect having written the X * remaining i bits, then write them. X * First write all the full bytes, then X * start a partial byte with whatever X * is left over, if anything. X */ X m += i; X i >>= 3; X while (--i >= 0) X *colp++ = 0xff; X *colp |= lbits[btobi(m)]; X } X X /* adjust maximum m bound */ X if (m > ob.max_m) X ob.max_m = m; X } else { X /* X * Add the bit index so that we round up whenever X * this fills the partial byte at colp. X */ X colp += (i + btobi(m)) >> 3; X m += i; X } X black = !black; X break; X X case GT_EOC: /* all done */ X FIX_N_BOUNDS(); X goto done; X X case GT_SKIP0: /* skip no rows */ X i = 0; X /* FALLTHROUGH */ X X case GT_SKIP: /* skip some rows, draw white */ X m = 0; X black = 0; X goto skip_or_new_row; X X case GT_NEW_ROW: /* next row near left col, draw black */ X m = c - GF_NEW_ROW_0; X black = 1; X i = 0; /* n offset is 1: skip no rows */ Xskip_or_new_row: X FIX_N_BOUNDS(); X n += i + 1; /* += because reflected */ X colp = &virtrast[n * stride + btoby(m)]; X break; X X case GT_XXX: /* special */ X p += i; X break; X X case GT_YYY: /* numspecial */ X break; X X case GT_NOP: /* dull */ X break; X X case GT_BOC: /* should not appear */ X case GT_BOC1: X case GT_CHAR_LOC: X case GT_CHAR_LOC0: X case GT_PRE: X case GT_POST: X case GT_POSTPOST: X case GT_UNDEF: X error(0, 0, "unexpected GF opcode %d", c); X error(1, 0, "bad GF file \"%s\"", gfname); X /* NOTREACHED */ X X default: X panic("gffont drawchar GF_TYPE(%d) = %d", c, GF_TYPE(c)); X /* NOTREACHED */ X } X goto more; X Xdone: X /* X * The observed bounds `m' values are both off by gb.min_m, so X * fix them now. CONSIDER ADJUSTING n HERE TOO X */ X ob.min_m += gb.min_m; X ob.max_m += gb.min_m; X X /* X * If we used too much memory for the raster, copy it now. X */ X if (mustcopy || tempb.min_n != ob.min_n || tempb.max_n != ob.max_n || X btonb(ob.max_m - ob.min_m + 1) != stride) X return (copyit()); X X /* X * If the left column bounds match, just move the raster in place. X */ X if (tempb.min_m == ob.min_m) { X p = buildraster; X buildraster = NULL; X buildsize = 0; X return (p); X } X X /* X * The raster must be copied, but only because it is not X * `left justified'. X * X * CONSIDER DEFERRING THIS PHASE UNTIL THE RASTER IS USED X */ X return (copyit()); X} X X/* X * Copy the built raster to newly allocated space. X * We may need to shift all the bits left as well. X */ Xchar * Xcopyit() X{ X register char *o, *p; X register int i, oldoff, newoff; X char *n; X X /* X * Compute the observed minimum stride. If it is zero or negative, X * there is no raster at all, else allocate just enough space X * to hold the new raster. X */ X newoff = btonb(ob.max_m - ob.min_m + 1); X if (newoff <= 0) X return (nullraster); Xif (ob.max_n < ob.min_n) Xpanic("gffont copyit max_n < min_n"); X n = malloc((unsigned) (newoff * (ob.max_n - ob.min_n + 1))); X if ((p = n) == NULL) X return (NULL); X X /* X * Compute the old stride. X */ X oldoff = btonb(tempb.max_m - tempb.min_m + 1); Xif (oldoff < newoff) Xpanic("gffont copyit oldoff < newoff"); X X /* X * Point at the old raster, then add the offset to the first X * written row, and then the offset to the first written column. X */ X o = buildraster; X o += (ob.max_n - tempb.max_n) * oldoff; X i = ob.min_m - tempb.min_m; X o += btoby(i); X X /* X * Now copy each row, doing shifting if required. X */ X if ((i = btobi(i)) != 0) { /* must shift, alas */ X register int r = 8 - i, j, k; X X oldoff -= newoff; X for (k = ob.max_n; k >= ob.min_n; k--) { X for (j = newoff; --j >= 0;) { X *p++ = *o++ << i; X p[-1] |= UnSign8(*o) >> r; X } X o += oldoff; X } X } else if (oldoff > newoff) { /* compressing columns */ X for (i = ob.max_n; i >= ob.min_n; i--) { X bcopy(o, p, newoff); X o += oldoff; X p += newoff; X } X } else /* just squeezing out extra rows */ X bcopy(o, p, newoff * (ob.max_n - ob.min_n + 1)); X X /* finally, return the copy */ X return (n); X} X X/* X * Obtain the specified range of glyphs. X */ Xstatic int Xgf_getgly(f, l, h) X register struct font *f; X int l, h; X{ X register struct glyph *g; X register struct char_loc *cl; X register char *p; X register i32 c; X register int i; X register i32 thisboc; X int abbrev; X struct gf_details *gd = ftogd(f); X X /* X * For each glyph, make sure there exists an instance of that X * character residue. Go find the actual glyph (which may be X * arbitrarily far down a chain of pointers) and get its info. X */ X for (cl = &gd->gd_cl[i = l]; i < h; i++, cl++) { X g = f->f_gly[i]; X thisboc = cl->cl_p; X X /* X * Screw around locating the character for real. X */ X while (thisboc != -1) { X p = gd->gd_base + thisboc; Xskip: X c = pgetbyte(p); X switch (GF_TYPE(c)) { X X case GT_XXX: X switch (GF_OpLen(c)) { X X case GPL_UNS1: X c = pgetbyte(p); X break; X X case GPL_UNS2: X pGetWord(p, c); X break; X X case GPL_UNS3: X pGet3Byte(p, c); X break; X X case GPL_SGN4: X pGetLong(p, c); X break; X X default: X panic("gf_getgly GF_OpLen(%d) = %d", X c, GF_OpLen(c)); X /* NOTREACHED */ X } X p += c; X goto skip; X X case GT_YYY: X p += 4; X goto skip; X X case GT_BOC: X abbrev = 0; X pGetLong(p, c); X break; X X case GT_BOC1: X abbrev = 1; X c = pgetbyte(p); X break; X X default: X error(0, 0, "GF code %d; I expected BOC", c); X error(1, 0, "bad GF file \"%s\"", f->f_path); X /* NOTREACHED */ X } X /* X * Found a BOC. If it is the right character, X * go handle it. X */ X if (c == i) X goto handleit; X if ((c & 255) != i) { X error(0, 0, "%d != %d mod 256", c, i); X error(1, 0, "Bad GF file \"%s\"", f->f_path); X } X /* X * Follow the backpointer. X */ X if (abbrev) X thisboc = -1; X else X pGetLong(p, thisboc); X } X X /* X * If we get here, the glyph is not valid after all. X */ X continue; X X /* X * The glyph is okay. Set it up. X */ Xhandleit: X g->g_flags = GF_VALID; X g->g_xescapement = cl->cl_dx; X g->g_yescapement = cl->cl_dy; X g->g_tfmwidth = cl->cl_w; X g -> g_rawtfmwidth = g -> g_tfmwidth; X if (!abbrev) X p += 4; /* skip backpointer */ X if ((p = drawchar(p, abbrev, gd->gd_gb, f->f_path)) == NULL) X return (-1); /* ??? */ X if (p == nullraster) X p = NULL; X /* set height &c based on observed bounds */ X g->g_height = ob.max_n - ob.min_n + 1; X g->g_width = ob.max_m - ob.min_m + 1; X g->g_yorigin = ob.max_n; X g->g_xorigin = -ob.min_m; X g->g_raster = p; X g->g_rotation = ROT_NORM; X } X return (0); X} X X/* X * Obtain rasters for the specified glyphs. We did this above, while X * adjusting the bounding boxes, so this routine should never get called. X */ Xstatic int Xgf_rasterise(f, l, h) X struct font *f; X int l, h; X{ X X panic("gf_rasterise(%s, %d, %d)", f->f_path, l, h); X} X X/* X * Discard the font details. X */ Xstatic Xgf_freefont(f) X struct font *f; X{ X struct gf_details *gd; X X if ((gd = ftogd(f)) != NULL) { X free(gd->gd_body); gd -> gd_body = 0; X free((char *) gd); gd = 0; X } X} END_OF_lib/gffont.c if test 22029 -ne `wc -c lib/gripes.c <<'END_OF_lib/gripes.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/gripes.c,v 1.3 89/02/13 14:31:11 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Common errors (`gripes'). X */ X X#include X#include "types.h" X Xstatic char areyousure[] = "Are you sure this is a DVI file?"; X Xextern errno; X X/* X * DVI file requests a font it never defined. X */ XGripeNoSuchFont(n) X i32 n; X{ X X error(0, 0, "DVI file wants font %ld, which it never defined", n); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * DVI file redefines a font. X */ XGripeFontAlreadyDefined(n) X i32 n; X{ X X error(0, 0, "DVI file redefines font %ld", n); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * Unexpected DVI opcode. X */ XGripeUnexpectedOp(s) X char *s; X{ X X error(0, 0, "unexpected %s", s); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * Missing DVI opcode. X */ XGripeMissingOp(s) X char *s; X{ X X error(0, 0, "missing %s", s); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * Cannot find DVI postamble. X */ XGripeCannotFindPostamble() X{ X X error(0, 0, "cannot find postamble"); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * Inconsistent DVI value. X */ XGripeMismatchedValue(s) X char *s; X{ X X error(0, 0, "mismatched %s", s); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * Undefined DVI opcode. X */ XGripeUndefinedOp(n) X int n; X{ X X error(0, 0, "undefined DVI opcode %d"); X error(1, 0, areyousure); X /* NOTREACHED */ X} X X/* X * Cannot allocate memory. X */ XGripeOutOfMemory(n, why) X int n; X char *why; X{ X X error(1, errno, "ran out of memory allocating %d bytes for %s", X n, why); X /* NOTREACHED */ X} X X/* X * Cannot get a font. X * RETURNS TO CALLER X */ XGripeCannotGetFont(name, mag, dsz, dev, fullname) X char *name; X i32 mag, dsz; X char *dev, *fullname; X{ X int e = errno; X char scale[40]; X X if (mag == dsz) /* no scaling */ X scale[0] = 0; X else X (void) sprintf(scale, " scaled %d", X (int) ((double) mag / (double) dsz * 1000.0 + .5)); X X error(0, e, "cannot get font %s%s", name, scale); X if (fullname) X error(0, 0, "(wanted, e.g., \"%s\")", fullname); X else { X if (dev) X error(1, 0, "(there are no fonts for the %s engine!)", X dev); X else X error(1, 0, "(I cannot find any fonts!)"); X /* NOTREACHED */ X } X} X X/* X * Font checksums do not match. X * RETURNS TO CALLER X */ XGripeDifferentChecksums(font, tfmsum, fontsum) X char *font; X i32 tfmsum, fontsum; X{ X X error(0, 0, "\ XWARNING: TeX and I have different checksums for font\n\ X\t\"%s\"\n\ X\tPlease notify your TeX maintainer\n\ X\t(TFM checksum = 0%o, my checksum = 0%o)", X font, tfmsum, fontsum); X} X X/* X * A font, or several fonts, are missing, so no output. X */ XGripeMissingFontsPreventOutput(n) X int n; X{ X static char s[2] = {'s', 0}; X X error(1, 0, "%d missing font%s prevent%s output (sorry)", n, X n > 1 ? s : &s[1], n == 1 ? s : &s[1]); X /* NOTREACHED */ X} END_OF_lib/gripes.c if test 3046 -ne `wc -c lib/magfactor.c <<'END_OF_lib/magfactor.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/* X * Convert a magnification factor to floating point. This is used in X * conjunction with the FONT_SLOP stuff to try to get the file names X * right, and may also be used by DVI reading programs to get slightly X * more accurate values for (mag/1000.0). X */ Xdouble XDMagFactor(mag) X int mag; X{ X X switch (mag) { X X case 1095: /* stephalf */ X return (1.095445); X X case 1315: /* stepihalf */ X return (1.314534); X X case 2074: /* stepiv */ X return (2.0736); X X case 2488: /* stepv */ X return (2.48832); X X case 2986: /* stepiv */ X return (2.985984); X X default: /* remaining mags have been ok */ X return ((double) mag / 1000.); X } X /* NOTREACHED */ X} END_OF_lib/magfactor.c if test 869 -ne `wc -c