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 3 of 6) Message-ID: Date: 13 Nov 89 21:21:32 GMT Sender: news@crdgw1.crd.ge.com Reply-To: (Skip Montanaro) Organization: GE Corporate Research & Development, Schenectady, NY Lines: 1221 #! /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/conv.c <<'END_OF_lib/conv.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/conv.c,v 1.3 89/02/13 14:30:55 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Conversions. X */ X X#include "types.h" X#include "conv.h" X XConv Conversion; X Xdouble DMagFactor(); X X/* X * Set a conversion (possibly the global conversion). X */ Xvoid XCSetConversion(c, dpi, usermag, num, denom, dvimag) X register struct conversion *c; X int dpi, usermag; X i32 num, denom, dvimag; X{ X double ddpi = dpi; X X c->c_mag = DMagFactor((int) dvimag) * DMagFactor(usermag); X c->c_dpi = ddpi; X X /* X * The conversion facture is figured as follows: there are exactly X * num/denom DVI units per decimicron, and 254000 decimicrons per X * inch, and dpi pixels per inch. Then we have to adjust this by X * the stated magnification. X */ X c->c_fromsp = (num / 254000.0) * (ddpi / denom) * c->c_mag; X X /* X * c->c_tosp is 1/c->c_fromsp, but we will invert the expression X * above in the hopes of some extra accuracy. X * X * IS THIS ANY GOOD? I NEED A NUMERICAL ANALYST! X */ X c->c_tosp = (254000.0 / num) * (denom / ddpi) * (1.0 / c->c_mag); X} END_OF_lib/conv.c if test 1325 -ne `wc -c lib/dviclass.c <<'END_OF_lib/dviclass.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/dviclass.c,v 1.3 89/02/13 14:30:57 grunwald Exp Locker: grunwald $"; X#endif X X/* X * dviclass - DVI code classification tables. X */ X X#include "dviclass.h" X X/* shorthand---in lowercase for contrast (read on!) */ X#define four(x) x, x, x, x X#define six(x) four(x), x, x X#define sixteen(x) four(x), four(x), four(x), four(x) X#define sixty_four(x) sixteen(x), sixteen(x), sixteen(x), sixteen(x) X#define one_twenty_eight(x) sixty_four(x), sixty_four(x) X X/* X * This table contains the byte length of the single operand, or DPL_NONE X * if no operand, or if it cannot be decoded this way. X * X * The sequences UNS1, UNS2, UNS3, SGN4 (`SEQ_U') and SGN1, SGN2, SGN3, X * SGN4 (`SEQ_S') are rather common, and so we define macros for these. X */ X#define SEQ_U DPL_UNS1, DPL_UNS2, DPL_UNS3, DPL_SGN4 X#define SEQ_S DPL_SGN1, DPL_SGN2, DPL_SGN3, DPL_SGN4 X Xchar dvi_oplen[256] = { X one_twenty_eight(DPL_NONE), X /* characters 0 through 127 */ X SEQ_U, /* DVI_SET1 through DVI_SET4 */ X DPL_NONE, /* DVI_SETRULE */ X SEQ_U, /* DVI_PUT1 through DVI_PUT4 */ X DPL_NONE, /* DVI_PUTRULE */ X DPL_NONE, /* DVI_NOP */ X DPL_NONE, /* DVI_BOP */ X DPL_NONE, /* DVI_EOP */ X DPL_NONE, /* DVI_PUSH */ X DPL_NONE, /* DVI_POP */ X SEQ_S, /* DVI_RIGHT1 through DVI_RIGHT4 */ X DPL_NONE, /* DVI_W0 */ X SEQ_S, /* DVI_W1 through DVI_W4 */ X DPL_NONE, /* DVI_X0 */ X SEQ_S, /* DVI_X1 through DVI_X4 */ X SEQ_S, /* DVI_DOWN1 through DVI_DOWN4 */ X DPL_NONE, /* DVI_Y0 */ X SEQ_S, /* DVI_Y1 through DVI_Y4 */ X DPL_NONE, /* DVI_Z0 */ X SEQ_S, /* DVI_Z1 through DVI_Z4 */ X sixty_four(DPL_NONE), /* DVI_FNTNUM0 through DVI_FNTNUM63 */ X SEQ_U, /* DVI_FNT1 through DVI_FNT4 */ X SEQ_U, /* DVI_XXX1 through DVI_XXX4 */ X SEQ_U, /* DVI_FNTDEF1 through DVI_FNTDEF4 */ X DPL_NONE, /* DVI_PRE */ X DPL_NONE, /* DVI_POST */ X DPL_NONE, /* DVI_POSTPOST */ X six(DPL_NONE) /* 250 through 255 */ X}; X Xchar dvi_dt[256] = { X one_twenty_eight(DT_CHAR), X /* characters 0 through 127 */ X four(DT_SET), /* DVI_SET1 through DVI_SET4 */ X DT_SETRULE, /* DVI_SETRULE */ X four(DT_PUT), /* DVI_PUT1 through DVI_PUT4 */ X DT_PUTRULE, /* DVI_PUTRULE */ X DT_NOP, /* DVI_NOP */ X DT_BOP, /* DVI_BOP */ X DT_EOP, /* DVI_EOP */ X DT_PUSH, /* DVI_PUSH */ X DT_POP, /* DVI_POP */ X four(DT_RIGHT), /* DVI_RIGHT1 through DVI_RIGHT4 */ X DT_W0, /* DVI_W0 */ X four(DT_W), /* DVI_W1 through DVI_W4 */ X DT_X0, /* DVI_X0 */ X four(DT_X), /* DVI_X1 through DVI_X4 */ X four(DT_DOWN), /* DVI_DOWN1 through DVI_DOWN4 */ X DT_Y0, /* DVI_Y0 */ X four(DT_Y), /* DVI_Y1 through DVI_Y4 */ X DT_Z0, /* DVI_Z0 */ X four(DT_Z), /* DVI_Z1 through DVI_Z4 */ X sixty_four(DT_FNTNUM), /* DVI_FNTNUM0 through DVI_FNTNUM63 */ X four(DT_FNT), /* DVI_FNT1 through DVI_FNT4 */ X four(DT_XXX), /* DVI_XXX1 through DVI_XXX4 */ X four(DT_FNTDEF), /* DVI_FNTDEF1 through DVI_FNTDEF4 */ X DT_PRE, /* DVI_PRE */ X DT_POST, /* DVI_POST */ X DT_POSTPOST, /* DVI_POSTPOST */ X six(DT_UNDEF) /* 250 through 255 */ X}; END_OF_lib/dviclass.c if test 3242 -ne `wc -c lib/error.c <<'END_OF_lib/error.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/error.c,v 1.3 89/02/13 14:30:59 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Print an error message with an optional system error number, and X * optionally quit. X * X * THIS CODE IS SYSTEM DEPENDENT UNLESS varargs WORKS WITH vprintf X * OR _doprnt. It should work properly under System V using vprintf. X * (If you have vprintf, define HAVE_VPRINTF.) X */ X X#include X#include X X#ifdef lint X X/* VARARGS3 ARGSUSED */ Xerror(quit, e, fmt) int quit, e; char *fmt; {;} X X/* VARARGS1 ARGSUSED */ Xpanic(fmt) char *fmt; { exit(1); /* NOTREACHED */ } X X#else lint X Xextern char *ProgName; Xextern int errno; Xextern char *sys_errlist[]; Xextern int sys_nerr; X Xerror(va_alist) X va_dcl X{ X va_list l; X int quit, e; X char *fmt; X X (void) fflush(stdout); /* sync error messages */ X (void) fprintf(stderr, "%s: ", ProgName); X va_start(l); X /* pick up the constant arguments: quit, errno, printf format */ X quit = va_arg(l, int); X e = va_arg(l, int); X if (e < 0) X e = errno; X fmt = va_arg(l, char *); X#if defined(sys5) || defined(HAVE_VPRINTF) X (void) vfprintf(stderr, fmt, l); X#else X _doprnt(fmt, l, stderr); X#endif X va_end(l); X if (e) { X if (e < sys_nerr) X (void) fprintf(stderr, ": %s", sys_errlist[e]); X else X (void) fprintf(stderr, ": Unknown error code %d", e); X } X (void) putc('\n', stderr); X (void) fflush(stderr); /* just in case */ X if (quit) X exit(quit); X} X Xpanic(va_alist) X va_dcl X{ X va_list l; X char *fmt; X X (void) fflush(stdout); X (void) fprintf(stderr, "%s: panic: ", ProgName); X va_start(l); X /* pick up the constant argument: printf format */ X fmt = va_arg(l, char *); X#if defined(sys5) || defined(HAVE_VPRINTF) X (void) vfprintf(stderr, fmt, l); X#else X _doprnt(fmt, l, stderr); X#endif X va_end(l); X (void) putc('\n', stderr); X (void) fflush(stderr); X abort(); X} X X#endif /* lint */ END_OF_lib/error.c if test 2104 -ne `wc -c lib/findpost.c <<'END_OF_lib/findpost.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/findpost.c,v 1.4 89/02/13 14:31:00 grunwald Exp Locker: grunwald $"; X#endif X X/* X * FindPostAmble - Find the postamble of a DVI file. X * X * N.B.: This routine assumes that ftell() returns byte offsets, X * not magic cookies. X */ X X#include X#include "types.h" X#include "dvicodes.h" X#include "fio.h" X X/* X * I am making the assumption that 530 bytes will always be enough X * to find the end of the DVI file. 12 should suffice, as there X * should be at most seven DVI_FILLER bytes, preceded by the version X * number, preceded by the four byte postamble pointer; but at least X * one VMS TeX must pad to a full `sector'. X */ X/* X * The above is not correct. The DVItype program, as authoritative on X * DVI format, states regarding postambles: X * X * The [last] byte is followed by four or more bytes that are all X * equal to the decimal number 223 (i.e., 337 in octal). TeX puts X * out four to seven of these trailing bytes, until the total length X * of the file is a multiple of four bytes, since this works out X * best on machines that pack four bytes per word; but any number X * of 223's is allowed, as long as there are at least four of them. X * X * Thus assuming "at most seven DVI_FILLER bytes" is wrong. In fact, X * PC-TeX seems to put out liberal amounts of DVI_FILLER at the end. X * X * The original code was efficient, but had to assume a certain X * number of bytes. Since the postamble is only read once anyway, X * efficiency is not really a consideration. Plus, like I always X * say, it's better to get the right answer slowly than the wrong X * answer fast.... X * X * Vahe Sarkissian, UCLA Math. Sci., 4/13/88. X */ X X#ifdef ORIGINAL_CODE X#ifdef vms X#define POSTSIZE 530 /* make only VMS pay for its errors; */ X#else X#define POSTSIZE 16 /* others get to use something reasonable */ X#endif X Xlong ftell(); X XFindPostAmble(f) X register FILE *f; 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 fseek'ing beyond beginning of file; it may X * give odd results. X */ X fseek(f, 0L, 2); /* seek to end */ X offset = ftell(f) - POSTSIZE; /* and compute where to go next */ X if (offset < 0L) /* but make sure it is positive */ X offset = 0L; X fseek(f, offset, 0); X p = postbuf; X for (i = 0; i < POSTSIZE; i++) { X *p++ = getc(f); X if (feof(f)) { X p--; X break; X } X } X X /* X * Now search backwards for the VERSION byte. The postamble X * pointer will be four bytes behind that. X */ X while (--i >= 0) { X if (UnSign8(*--p) == DVI_VERSION) X goto foundit; X if (UnSign8(*p) != DVI_FILLER) X break; X } X return (-1); /* cannot find postamble ptr */ X Xfoundit: X /* X * Change offset from the position at the beginning of postbuf X * to the position of the VERSION byte, and seek to four bytes X * before that. Then get a long and use its value to seek to X * the postamble itself. X */ X offset += p - postbuf; X fseek(f, offset - 4L, 0); X fGetLong(f, n); X offset = n; X fseek(f, offset, 0); X return (0); /* success */ X} X X#else !ORIGINAL_CODE X XFindPostAmble(f) X register FILE *f; X{ X register long offset; X register i32 n; X X offset = -4; /* At least four bytes of DVI_FILLER must be present. */ X do { X offset -= 1; X (void) fseek(f, offset, 2); X n = fgetbyte(f); X } while (n == DVI_FILLER); X X if (n != DVI_VERSION) X return (-1); /* Bad version of DVI file */ X X /* X * Position file four bytes before DVI_VERSION byte, X * and read a long. Use that long to seek to the X * beginning of the postamble itself. X */ X offset -= 4; X (void) fseek(f, offset, 2); X fGetLong(f, n); X offset = n; X (void) fseek(f, offset, 0); X return (0); /* success */ X} X#endif ORIGINAL_CODE END_OF_lib/findpost.c if test 3945 -ne `wc -c lib/fio.c <<'END_OF_lib/fio.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/fio.c,v 1.3 89/02/13 14:31:01 grunwald Exp Locker: grunwald $"; X#endif X X/* X * File I/O subroutines for getting bytes, words, 3bytes, and longwords. X */ X X#include X#include "types.h" X#include "fio.h" X Xstatic char eofmsg[] = "unexpected EOF"; X X/* for symmetry: */ X#define fGetByte(fp, r) ((r) = getc(fp)) X#define Sign32(i) (i) X X#define make(name, func, signextend) \ Xi32 \ Xname(fp) \ X register FILE *fp; \ X{ \ X register i32 n; \ X \ X func(fp, n); \ X if (feof(fp)) \ X error(1, 0, eofmsg); \ X return (signextend(n)); \ X} X Xmake(GetByte, fGetByte, Sign8) Xmake(GetWord, fGetWord, Sign16) Xmake(Get3Byte, fGet3Byte, Sign24) Xmake(GetLong, fGetLong, Sign32) END_OF_lib/fio.c if test 965 -ne `wc -c lib/font.c <<'END_OF_lib/font.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/font.c,v 1.6 89/02/13 14:31:02 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Routines for working with fonts. In particular, the configuration X * dependent code is here. X * X * Specific fonts (GF, PXL, etc.) have functions in separate files. X */ X X#include X#include X#include X#include "types.h" X#include "conv.h" X#include "font.h" X X/* X * Define the default configuration file. X * Also define the maximum path name length. X */ X#ifndef FONTDESC X you need to define FONTDESC in the compile line X#endif X X#define PATHLEN 1024 X X/* X * A font configuration. The font list is ordered. X * X * A specifier is typically a particular print engine, since X * different engines need slightly different fonts. X */ Xstruct fontconf { X struct fontconf *fc_next; X struct fontops *fc_ops; X char *fc_path; /* path, with metacharacters */ X char *fc_spec; /* specifier */ X int fc_slop; /* slop value */ X}; X X/* X * EQ is a fast way to check for string equivalence. X */ X#define EQ(a, b) (*(a) == *(b) && strcmp(a, b) == 0) X X/* X * Private variables. X */ Xstatic int didinit; /* true => initialised already */ Xstatic char *cfname; /* config file name, for errors */ Xstatic int cfline; /* config file line, likewise */ Xstatic struct fontops *fontops;/* font operations code: list head */ Xstatic struct fontconf *fonts; /* font list */ Xstatic struct fontconf **nextfc;/* used during initialisation */ Xstatic char spec_any[] = "*"; /* the `anything' specifier */ X X/* X * Imports. X */ Xextern int errno; Xchar *getenv(), *malloc(), *strsave(); X#ifndef sys5 Xchar *sprintf(); X#endif X Xstatic readconf(); Xstatic setfont(); Xstatic badcf(); Xstatic struct font *getafont(); /* get a font and optional rasters */ X X/* X * Here, alas, we know about all the kinds of fonts. X * This also means that every DVI interpreter pulls in X * the full set of font manipulation routines. X * X * PERHAPS THIS SHOULD BE CONFIGURABLE. X */ X#define ADDFONT(x) { \ X extern struct fontops x; \ X x.fo_next = fontops; \ X fontops = &x; \ X} X Xfontinit(file) X char *file; X{ X X if (didinit) { X /* X * Could free the old configuration and fire up X * a new one, but for now . . . X */ X error(1, 0, "attempt to reinit fonts"); X /* NOTREACHED */ X } X didinit++; X ADDFONT(boxops); X ADDFONT(blankops); X ADDFONT(invisops); X ADDFONT(pxlops); X ADDFONT(pkops); X ADDFONT(gfops); X nextfc = &fonts; X if (file == NULL) X if ((file = getenv(CONFENV)) == NULL) X file = FONTDESC; X readconf(file); X} X X/* X * A proto resembles a fontspec (indeed, it is a prototype X * fontspec) but is not quite the same. It is used to gather X * the information needed per fontspec before allocating X * the fontspec itself. X */ Xstruct proto { X char *p_type; X char *p_spec; X char *p_slop; X char *p_path; X}; X X/* X * Read the named configuration file. The file is split into X * lines, and lines are split into words; if the first word is X * "font", this is a fontconf, and we read the remainder of the X * words and make a fontconf entry. X */ Xstatic Xreadconf(name) X char *name; X{ X register FILE *f; /* config file */ X register char **p; /* pointer into word vector */ X register int c; X char line[1024]; /* input line */ X char *v[100]; /* word vector */ X struct proto proto; /* prototype fontconf */ X X#define GETWORD(x, ifnone) \ X if (--c <= 0) \ X badcf(ifnone); \ X else \ X (x) = *p++ X X if ((f = fopen(name, "r")) == NULL) X error(1, errno, "cannot read font configuration file \"%s\"", X name); X cfname = name; X cfline = 0; X while (fgets(line, sizeof (line), f) != NULL) { X cfline++; X if ((c = strlen(line)) > 0) { X if (line[--c] != '\n') X badcf("line too long"); X line[c] = 0; X } X if ((c = split(line, v, sizeof (v) / sizeof (*v))) < 0) X badcf("too many words"); X p = v; X /* skip things that are not fonts */ X if (c == 0 || !EQ(*p, "font")) X continue; X p++; X GETWORD(proto.p_type, "missing font typename"); X GETWORD(proto.p_spec, "missing font spec (engine)"); X GETWORD(proto.p_slop, "missing slop value"); X GETWORD(proto.p_path, "need pathname"); X (void) setfont(&proto); X } X} X X/* X * Find a font's operations, given its name. X */ Xstatic struct fontops * Xfindops(name) X register char *name; X{ X register struct fontops *fo; X X for (fo = fontops; fo != NULL; fo = fo->fo_next) X if (EQ(fo->fo_name, name)) X return (fo); X return (NULL); X} X X/* X * Turn a prototype fontconf into a real one. X */ Xstatic int Xsetfont(p) X register struct proto *p; X{ X register struct fontconf *fc; X struct fontops *ops = findops(p->p_type); X X if (ops == NULL) { X error(0, 0, X "\"%s\", line %d: unknown font type \"%s\" ignored", X cfname, cfline, p->p_type); X return (-1); X } X if ((fc = (struct fontconf *) malloc(sizeof (*fc))) == NULL) X error(1, errno, X "out of memory for font configuration (sorry)"); X fc->fc_ops = ops; X fc->fc_next = NULL; X fc->fc_path = strsave(p->p_path); X fc->fc_spec = EQ(p->p_spec, spec_any) ? NULL : strsave(p->p_spec); X fc->fc_slop = atoi(p->p_slop); X if (fc->fc_slop < 1) /* quietly enforce proper slops */ X fc->fc_slop = 1; X *nextfc = fc; X nextfc = &fc->fc_next; X return (0); X} X X/* X * Complain about a problem in the configuration file. X */ Xstatic Xbadcf(why) X char *why; X{ X X error(1, 0, "\"%s\", line %d: %s", cfname, cfline, why); X /* NOTREACHED */ X} X X/* X * Turn a prototype path, name, and magnification into a full X * path. X */ Xstatic Xpave(result, proto, name, mag) X char *result, *proto, *name; X int mag; X{ X register int c; X register char *s, *d, *p; X char num[30]; X X d = result; X p = proto; X s = NULL; X num[0] = 0; /* will need changing for other bases */ X X while (p != NULL) { X /* X * If sourcing from s, take its next character, and X * insert it directly. Otherwise take the next path X * character and interpret it. X */ X if (s != NULL) { X if ((c = *s++) == 0) { X s = NULL; X continue; X } X goto put; X } X if ((c = *p++) == 0) X p = NULL; X if (c != '%') X goto put; X X switch (c = *p++) { X X case 'f': X case 'n': X case 's': X s = name; X continue; X X case 'd': X case 'm': X if (num[0] == 0) X (void) sprintf(num, "%d", mag); X s = num; X continue; X X case 0: X c = '%'; X p--; X /* FALLTHROUGH */ X } Xput: X if (d - result >= PATHLEN) X error(1, 0, "font path `%s' too long (sorry)", proto); X *d++ = c; X } X} X X X/* X * Given a font name and size, return the first font that fits, along X * with its name (via fname). If we cannot find such a font, we set X * *fname to point to a `canonical' example font name, unless there are X * are no fonts for the device, in which case we set *fname to NULL. X */ Xstruct font * XGetFont(nm, dvimag, dvidsz, dev, fname) X char *nm; X i32 dvimag, dvidsz; X char *dev, **fname; X{ X X return (getafont(nm, dvimag, dvidsz, dev, fname, 1)); X} X X/* X * Same as GetFont, but caller promises never to ask for rasters. X */ Xstruct font * XGetRasterlessFont(nm, dvimag, dvidsz, dev, fname) X char *nm; X i32 dvimag, dvidsz; X char *dev, **fname; X{ X X return (getafont(nm, dvimag, dvidsz, dev, fname, 0)); X} X X/* X * NEED TO THINK ABOUT gf NAMING CONVENTIONS HERE: ARE THEY LIKE pxl? X * WHAT ABOUT OTHERS? X */ Xstatic struct font * Xgetafont(nm, dvimag, dvidsz, dev, fname, wantrast) X char *nm; X i32 dvimag, dvidsz; X char *dev, **fname; X int wantrast; X{ X register int slop, fmag; X register struct font *f; X register struct fontconf *fc; X register char *path; X static char firstpath[PATHLEN], laterpath[PATHLEN]; X double mag; X int scaled; X X extern Conv Conversion; X X if (!didinit) X fontinit((char *) NULL); X X /* X * The equation below means, approximately, `the font is X * magnified by the ratio of the actual size dvimag to the X * design size dvidsz, and then further scaled by the X * global magnification.' We multiply this by the printer's X * resolution in dots per inch, then use the per-font X * conversion factor to convert a dots-per-inch value to X * a font name `%m' magnification (extension). X */ X mag = (double) dvimag / (double) dvidsz; X scaled = mag * 1000.0 + 0.5; X mag *= Conversion.c_mag * Conversion.c_dpi; X X path = firstpath; X for (fc = fonts; fc != NULL; fc = fc->fc_next) { X if (dev != NULL && fc->fc_spec != NULL && X !EQ(dev, fc->fc_spec)) X continue; X fmag = mag * fc->fc_ops->fo_dpitomag + 0.5; X for (slop = 0; slop < fc->fc_slop; slop++) { X pave(path, fc->fc_path, nm, fmag + slop); X if (access(path, R_OK) == 0) X goto found; X X X /* if someone could explain this, I'd appreicate it. X On ultrix 2.2, checking R_OK on a RO filesyste X fails, with the following errno. Why? */ X X if ( errno == EROFS ) { X goto found; X } X X if (slop) { X pave(path, fc->fc_path, nm, fmag - slop); X if (access(path, R_OK) == 0) X goto found; X if ( errno == EROFS ) { X goto found; X } X } X path = laterpath; X } X } X X /* not found */ X if (path == firstpath) { /* never got to try any paths */ X *fname = NULL; X errno = ENXIO; X } else { X *fname = firstpath; X errno = ENOENT; X } X return (NULL); X Xfound: X *fname = path; X X /* allocate space for the per-font info, and read it in */ X f = (struct font *) malloc(sizeof (struct font)); X if (f == NULL) X return (NULL); X f->f_flags = wantrast ? FF_RASTERS : 0; X f->f_ops = fc->fc_ops; X f->f_path = strsave(path); X f->f_font = strsave(nm); X f->f_dvimag = dvimag; X f->f_dvidsz = dvidsz; X f->f_scaled = scaled; X f->f_checksum = 0; /* in case the font reader cannot get one */ X errno = 0; X if ((*f->f_ops->fo_read)(f)) { X int e = errno; /* paranoid */ X X free(f->f_path); f -> f_path = 0; X free(f->f_font); f -> f_font = 0; X free((char *) f); f = 0; X errno = e; X return (NULL); X } X return (f); X} END_OF_lib/font.c if test 9825 -ne `wc -c lib/font_subr.c <<'END_OF_lib/font_subr.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/font_subr.c,v 1.5 89/02/13 14:31:04 grunwald Exp Locker: grunwald $"; X#endif X X/* X * Subroutines common to all fonts. X */ X X#include "font.h" X Xstatic struct glyph *freeglyphs; X Xchar *malloc(); Xextern errno; X X/* X * Set up the font structures to note that a font has glyphs in X * the half-open interval [low, high). X * X * SHOULD I ALLOW ADDITIONS TO THE RANGE VIA SUBSEQUENT CALLS TO X * FontHasGlyphs? X */ XFontHasGlyphs(f, low, high) X register struct font *f; X register int low, high; X{ X register struct glyph **gp; X X /* record bounds */ X f->f_lowch = low; X f->f_highch = high; X X /* X * Allocate space for all the glyph pointers, and set X * them all to NULL. X */ X if (low >= high) /* no glyphs */ X gp = NULL; X else { X gp = (struct glyph **) malloc((unsigned) (high - low) * X sizeof (*gp)); X if (gp == NULL) X return (-1); X } X f->f_glybase = gp; X f->f_gly = gp - low; X while (++low <= high) X *gp++ = NULL; X return (0); X} X X/* X * AllocGlyph allocates a new glyph. ReleaseGlyph puts one onto the free X * list. We maintain a local list of free glyphs. X */ X#define ReleaseGlyph(g) \ X ((g)->g_un.g_next = freeglyphs, freeglyphs = (g)) X Xstatic struct glyph * XAllocGlyph(n) X int n; X{ X register struct glyph *g; X register int i; X X if ((g = freeglyphs) == NULL) { X g = (struct glyph *) malloc((unsigned) (128 * sizeof (*g))); X if (g == NULL) X error(1, errno, "out of glyph memory"); X g += (i = 128); X while (--i >= 0) { X g--; X ReleaseGlyph(g); X } X } X freeglyphs = g->g_un.g_next; X g->g_flags = 0; X g->g_raster = NULL; X g->g_index = n; X return (g); X} X X/* X * Free one glyph. X */ Xvoid XFreeGlyph(f, n) X struct font *f; X register int n; X{ X register struct glyph *g; X X if (n < f->f_lowch || n >= f->f_highch) X return; X#ifdef notdef X (*f->f_ops->fo_freegly)(f, n, n); X#endif X if ((g = f->f_gly[n]) == NULL) X return; X if (g->g_raster != NULL) { X free(g->g_raster); g -> g_raster = 0; X } X ReleaseGlyph(g); X} X X/* X * Free a font. X */ Xvoid XFreeFont(f) X register struct font *f; X{ X register struct glyph *g; X register int i; X X#ifdef notdef X (*f->f_ops->fo_freegly)(f, f->f_lowch, f->f_highch); X#endif X for (i = f->f_lowch; i < f->f_highch; i++) { X if ((g = f->f_gly[i]) == NULL) X continue; X if (g->g_raster != NULL) { X free(g->g_raster); g -> g_raster = 0; X } X ReleaseGlyph(g); X } X if (f->f_glybase != NULL) { X free((char *) f->f_glybase); g -> g_raster = 0; X } X (*f->f_ops->fo_freefont)(f); X free(f->f_path); f -> f_path = 0; X free(f->f_font); f -> f_font = 0; X free((char *) f); f = 0; X} X X/* X * Get glyph `c' in font `f'. We pull in a few adjacent glyphs here X * under the (perhaps naive) assumption that things will go faster X * that way. X * X * TODO: X * try different adjacency values X * make adjacency a font attribute? (or an op) X */ X#define ADJ 8 /* must be a power of 2 */ X#define GET_ADJ(c, l, h) ((h) = ADJ + ((l) = (c) & ~(ADJ - 1))) X Xstruct glyph * XGetGlyph(f, c) X register struct font *f; X int c; X{ X register int i, h, l; X X GET_ADJ(c, l, h); X if (l < f->f_lowch) X l = f->f_lowch; X if (h > f->f_highch) X h = f->f_highch; X if (l >= h) X return (NULL); X for (i = l; i < h; i++) X if (f->f_gly[i] == NULL) X f->f_gly[i] = AllocGlyph(i); X X if ((*f->f_ops->fo_getgly)(f, l, h)) { X /* X * I do not know what to do about this just yet, so: X */ X panic("getgly fails and I am confused ... help!"); X } X X /* X * Apply the appropriate scale factor to the TFM widths. X * This makes them come out in scaled points, instead of FIXes. X */ X ScaleGlyphs(f, l, h); /* ??? */ X X return (f->f_gly[c]); X} X X/* X * Get the raster for glyph g in font f at rotation r. X */ Xchar * XGetRaster(g, f, r) X register struct glyph *g; X register struct font *f; X int r; X{ X int l, h; X X /* abort if caller did not ask for rasters in advance */ X if ((f->f_flags & FF_RASTERS) == 0) X panic("GetRaster(%s)", f->f_path); X X /* X * If there is no raster, get one. Blank characters, X * however, never have rasters. X */ X if (g->g_raster == NULL) { X if (!HASRASTER(g)) X return (NULL); X /* X * THE FOLLOWING DEPENDS ON THE ADJACENCY MATCHING THAT IN X * GetGlyph() ABOVE. X */ X GET_ADJ(g->g_index, l, h); X if (l < f->f_lowch) X l = f->f_lowch; X if (h > f->f_highch) X h = f->f_highch; X if ((*f->f_ops->fo_rasterise)(f, l, h)) X error(1, 0, "rasterise fails (out of memory?)"); X } X if (g->g_rotation != r) X SetRotation(g, r); X return (g->g_raster); X} X X/* X * Return a TeX-style font name, including scale factor. X * SHOULD I BOTHER WITH \magstep STYLE NAMES? X */ Xchar * XFont_TeXName(f) X register struct font *f; X{ X static char result[200]; X X if (f->f_scaled == 1000) X return (f->f_font); X sprintf(result, "%s scaled %d", f->f_font, f->f_scaled); X return (result); X} END_OF_lib/font_subr.c if test 4984 -ne `wc -c