/* * File: dvifonts.c * Purpose: provides functions for handling DVI fonts. * Version: 1.2 (Dec 1995) * Version: 1.0 (Nov 1993) * Author: Piet Tutelaers */ #include /* fseek(), ftell(), fread(), fopen(), fclose() */ #include "basics.h" /* fatal() */ #include "filenames.h" /* newname() */ #include "psearch.h" /* search_file() */ #include "texfiles.h" /* four(), num(), one(), sfour(), sone(), two() */ /** ** DVI handling functions (derived from xdvi) **/ /* * Mnemonics for bytes in dvi file. */ #define SETCHAR0 0 #define SET1 128 #define SETRULE 132 #define PUT1 133 #define PUTRULE 137 #define NOP 138 #define BOP 139 #define EOP 140 #define PUSH 141 #define POP 142 #define RIGHT1 143 #define RIGHT2 144 #define RIGHT3 145 #define RIGHT4 146 #define W0 147 #define W1 148 #define W2 149 #define W3 150 #define W4 151 #define X0 152 #define X1 153 #define X2 154 #define X3 155 #define X4 156 #define DOWN1 157 #define DOWN2 158 #define DOWN3 159 #define DOWN4 160 #define Y0 161 #define Y1 162 #define Y2 163 #define Y3 164 #define Y4 165 #define Z0 166 #define Z1 167 #define Z2 168 #define Z3 169 #define Z4 170 #define FNTNUM0 171 #define FNT1 235 #define FNT2 236 #define FNT3 237 #define FNT4 238 #define XXX1 239 #define XXX2 240 #define XXX3 241 #define XXX4 242 #define FNTDEF1 243 #define FNTDEF2 244 #define FNTDEF3 245 #define FNTDEF4 246 #define PRE 247 #define POST 248 #define POSTPOST 249 #define SREFL 250 #define EREFL 251 #define TRAILER 223 /* Trailing bytes at end of file */ static long numerator, denominator, magnification; void virtualfonts(char *, float, void (*font)(char *, int)); extern char *vfpath; /* * Read font definition from DVI file. The rounding to DPI sizes can * give some unwanted behaviour. The formula to compute the integer DPI * size of a font is * truncate(scale / design * (MAG/1000.0) * DPI + 0.5) * For a 11pt font in the basic resolution of DPI = 300 dpi and * MAG = 1000 (scale = 717619, design = 655360) this would result in 328 * (328.499 + 0.5) while the nearest half magstep (328.633 + 0.5) would * be 329 dpi. To avoid this kind of round-off mismatches I round the DPI * value to its nearest half magstep if the difference is within 0.5 dpi. */ static void define_font(FILE *file, int DPI, int MAG, unsigned char cmnd, void (*font)(char *, int)) { float dpi; unsigned long scale, design; int len; char fontname[128], *vfname; float closehalf(float dpi, int bdpi, float tolerance); (void) num(file, (int) cmnd - FNTDEF1 + 1); (void) four(file); /* checksum */ scale = four(file); design = four(file); len = one(file); len += one(file); /* sequence point in the middle */ fread(fontname, sizeof(char), len, file); fontname[len] = '\0'; dpi = closehalf(.001 * scale / design * MAG * DPI, DPI, 0.5); vfname = search_file(vfpath, newname(fontname, ".vf"), NONFATAL); if (vfname != NULL) { virtualfonts(vfname, dpi, (void (*)(char *, int)) font); } else font(fontname, dpi+0.5); } /* * DVI preamble and postamble information. */ static char job_id[300]; static FILE *dvi_file; /* * process_preamble reads the information in the preamble and stores * it into global variables for later use. */ static void process_preamble() { unsigned char k; if (one(dvi_file) != PRE) fatal("DVI file doesn't start with preamble"); if (one(dvi_file) != 2) fatal("Wrong version of DVI output for this program"); numerator = four(dvi_file); denominator = four(dvi_file); magnification = four(dvi_file); k = one(dvi_file); fread(job_id, sizeof(char), (int) k, dvi_file); job_id[k] = '\0'; } /* * find_postamble locates the beginning of the postamble * and leaves the file ready to start reading at that location. */ #define TMPSIZ 516 /* 4 trailer bytes + 512 junk bytes allowed */ static void find_postamble() { long pos; unsigned char temp[TMPSIZ]; unsigned char *p; unsigned char *p1; unsigned char byte; fseek(dvi_file, (long) 0, 2); pos = ftell(dvi_file) - TMPSIZ; if (pos < 0) pos = 0; fseek(dvi_file, pos, 0); p = temp + fread((char *) temp, sizeof(char), TMPSIZ, dvi_file); for (;;) { p1 = p; while (p1 > temp && *(--p1) != TRAILER) ; p = p1; while (p > temp && *(--p) == TRAILER) ; if (p <= p1 - 4) break; /* found 4 TRAILER bytes */ if (p <= temp) fatal("DVI file corrupted\n"); } pos += p - temp; byte = *p; while (byte == TRAILER) { fseek(dvi_file, --pos, 0); byte = one(dvi_file); } if (byte != 2) fatal("Wrong version of DVI output for this program\n"); fseek(dvi_file, pos - 4, 0); fseek(dvi_file, sfour(dvi_file), 0); } /* * read_postamble reads the information in the postamble, * storing it into local variables. */ static void read_postamble(int DPI, int MAG, void (*font)(char *, int)) { unsigned char cmnd; int maxpages; if (one(dvi_file) != POST) fatal("Postamble doesn't begin with POST"); (void) four(dvi_file); /* last_page_offset */ if (numerator != four(dvi_file) || denominator != four(dvi_file) || magnification != four(dvi_file)) fatal("Postamble doesn't match preamble\n"); /* read largest box height and width */ (void) sfour(dvi_file); (void) sfour(dvi_file); (void) two(dvi_file); /* max stack size */ maxpages = two(dvi_file); while ((cmnd = one(dvi_file)) >= FNTDEF1 && cmnd <= FNTDEF4) define_font(dvi_file, DPI, MAG, cmnd, (void (*)(char *, int)) font); if (cmnd != POSTPOST) fatal("Non-fntdef command found in postamble\n"); } /* * the function we really need */ int pk_fonts(char *dvi_name, int BDPI, int MAG, void (*font)(char *name, int DPI)) { dvi_file = fopen(dvi_name, RB); if (dvi_file == NULL) fatal("%s: no such file\n", dvi_name); process_preamble(); find_postamble(); read_postamble(BDPI, MAG, (void (*) (char *, int)) font); fclose(dvi_file); } /* * determine fonts from VF font (a mix of xdvi and dvips) */ void virtualfonts(char *vfname, float dpi, void (*font)(char *, int)) { FILE *VF; unsigned char cmnd; int i; int scale; int design; int len; char fontname[128], *vfontname; VF = fopen(vfname, RB); if (VF == NULL) fatal("%s: can not open\n", vfname); /*Read preamble */ if (sone(VF)!=247) fatal("%s: expected pre", vfname) ; if (sone(VF)!=202) fatal("%s: wrong id byte", vfname) ; for(i=sone(VF); i>0; i--) (void)sone(VF) ; (void) four(VF); /* skip checksum */ (void) four(VF); /* skip design size */ /* Read the fonts */ while ((cmnd = one(VF)) >= FNTDEF1) { if (cmnd > FNTDEF4) fatal("%s: unexpected command in preamble\n", vfname); /* read font definition from VF file */ (void) num(VF, (int) cmnd - FNTDEF1 + 1); (void) four(VF); /* checksum */ scale = four(VF); design = four(VF); len = one(VF); len += one(VF); fread(fontname, sizeof(char), len, VF); fontname[len] = '\0'; vfontname = search_file(vfpath, newname(fontname, ".vf"), NONFATAL); if (vfontname != NULL) virtualfonts(vfontname, dpi, font); else font(fontname, dpi * scale / 1048576.0 + 0.5); } fclose(VF); } /* * Round to a whole or half magstep if the difference is within * a small from it. Return float so we can postpone rounding off * errors till later. */ float closehalf(float dpi, int bdpi, float tolerance) { double near = bdpi, half = 1.095445115; if (tolerance == 0.0) return dpi; if (dpi > near+tolerance) while (dpi > near+tolerance) near*=half; else if (dpi < near-tolerance) while (dpi < near-tolerance) near/=half; if (dpi >= near-tolerance && dpi <= near+tolerance) return near; return dpi; }