dviselect (Part 4 of 6)
Skip Montanaro
montnaro at sprite.crd.ge.com
Tue Nov 14 08:22:58 AEST 1989
#! /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 4 (of 6)."
# Contents: lib/getopt.c lib/gfclass.c lib/gffont.c lib/gripes.c
# lib/magfactor.c
# Wrapped by montnaro at sprite on Sat Nov 11 17:13:31 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/getopt.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lib/getopt.c\"
else
echo shar: Extracting \"lib/getopt.c\" \(1380 characters\)
sed "s/^X//" >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 <stdio.h>
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/getopt.c`; then
echo shar: \"lib/getopt.c\" unpacked with wrong size!
fi
chmod +x lib/getopt.c
# end of overwriting check
fi
if test -f lib/gfclass.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lib/gfclass.c\"
else
echo shar: Extracting \"lib/gfclass.c\" \(2408 characters\)
sed "s/^X//" >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/gfclass.c`; then
echo shar: \"lib/gfclass.c\" unpacked with wrong size!
fi
chmod +x lib/gfclass.c
# end of overwriting check
fi
if test -f lib/gffont.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lib/gffont.c\"
else
echo shar: Extracting \"lib/gffont.c\" \(22029 characters\)
sed "s/^X//" >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 <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
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/gffont.c`; then
echo shar: \"lib/gffont.c\" unpacked with wrong size!
fi
chmod +x lib/gffont.c
# end of overwriting check
fi
if test -f lib/gripes.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lib/gripes.c\"
else
echo shar: Extracting \"lib/gripes.c\" \(3046 characters\)
sed "s/^X//" >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 <stdio.h>
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/gripes.c`; then
echo shar: \"lib/gripes.c\" unpacked with wrong size!
fi
chmod +x lib/gripes.c
# end of overwriting check
fi
if test -f lib/magfactor.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"lib/magfactor.c\"
else
echo shar: Extracting \"lib/magfactor.c\" \(869 characters\)
sed "s/^X//" >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 <lib/magfactor.c`; then
echo shar: \"lib/magfactor.c\" unpacked with wrong size!
fi
chmod +x lib/magfactor.c
# end of overwriting check
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 6 archives.
echo "Now do 'make dviselect'"
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
--
Skip Montanaro (montanaro at crdgw1.ge.com)
More information about the Alt.sources
mailing list