diff options
Diffstat (limited to 'dviware/dvgtk/fontreader.c')
-rw-r--r-- | dviware/dvgtk/fontreader.c | 1079 |
1 files changed, 1079 insertions, 0 deletions
diff --git a/dviware/dvgtk/fontreader.c b/dviware/dvgtk/fontreader.c new file mode 100644 index 0000000000..3976e00281 --- /dev/null +++ b/dviware/dvgtk/fontreader.c @@ -0,0 +1,1079 @@ +/* fontreader.c - functions for reading PK fonts + $Id: fontreader.c,v 0.2 1997/03/28 03:16:59 tjchol01 Exp $ + Authors: Andrew Trevorrow, Ian Dall, Geoffrey Tobin, Tomasz J. Cholewo + */ + +#include "dvgt.h" +#include <kpathsea/tex-file.h> +#include <kpathsea/tex-glyph.h> + +#include "screenio.h" +#include "vdu.h" +#include "options.h" +#include "dvireader.h" +#include "fontreader.h" + +typedef struct _REC_TFMinfo + { + int wdindex, htindex, dpindex; + } +_REC_TFMinfo; + +typedef struct _REC_charmetrics + { + int width[4], height[4], depth[4]; + } +_REC_charmetrics; + + +static int PTfile; /* PK/TFM file descriptor */ +static int PToffset; /* current byte offset in PTfile */ +static int currPTbuff; /* starting byte offset in buffer */ +static buffer PTbuffer; /* input buffer */ +static int gpower[33]; /* 0,1,11,111,1111,... */ +static boolean turnon; /* is current run black? */ +static int dynf; /* dynamic packing variable */ +static int repeatcount; /* times to repeat the next row */ +static int bitweight; /* for bits or nybbles from inputbyte */ +static int inputbyte; /* the current input byte */ +static int lf, lh, bc, ec, nw, nh; /* TFM file data; lf unused */ +static _REC_TFMinfo TFMinfo[maxTeXchar + 1]; +static _REC_charmetrics charmetrics[maxTeXchar + 1]; + +/*--------------------------------------------------------------------*/ +boolean +CheckFontPtr (fontinfo * fontptr) +{ + boolean check = false; + if (fontptr == (fontinfo *) NULL) + { + MesgString ("NULL font info passed to CheckFontPtr!"); + MesgLine (); + check = false; + } + else if (fontptr->fontnamelen == 0) + { + MesgString ("Zero length font name in font info passed to CheckFontPtr!"); + MesgLine (); + check = false; + } + else if (!strcmp (fontptr->fontname, "")) + { + MesgString ("Empty font name in font info passed to CheckFontPtr!"); + MesgLine (); + check = false; + } + else + { + check = true; + } + return check; +} +/* CheckFontPtr */ + +/*--------------------------------------------------------------------*/ + +boolean +BuildFontSpec (fontinfo * fontptr) +{ + /* Build a complete PK or TFM font file specification in fontptr->fontspec. + (May end up with a dummy PK font's or TFM metric's file spec. + ShowStatistics() in "dvitovdu.c" will show any font substitutions.) + This will be done at most once per font. + Test for valid fontptr->fontname. + ASSUMPTIONS: + fontptr->fontname contains the basename of the font. + SIDE EFFECTS on success: + fontptr->fontspec will be set. + fontptr->fontspeclen will no longer be 0. + fontptr->fontexists becomes TRUE if the real or dummy PK or TFM + file can be opened, FALSE, otherwise. + fontptr->pkfont becomes TRUE if the real or dummy PK file + can be opened, FALSE, otherwise. + fontptr->honest becomes TRUE if the true font is used, FALSE otherwise. + SIDE EFFECTS on failure: + EITHER: + fontptr is NULL. + OR: + fontptr->fontspec will be unset (holds empty string ""). + fontptr->fontspeclen will be 0. + fontptr->fontexists becomes FALSE. + fontptr->pkfont becomes FALSE. + fontptr->honest becomes FALSE. + */ + + kpse_glyph_file_type font_ret; + string name; + unsigned dpi; + + if (!CheckFontPtr (fontptr)) + return false; + + /* Initialise correctly */ + strncpy (fontptr->fontspec, "", maxfontspec); + fontptr->fontspeclen = 0; + fontptr->fontexists = false; + fontptr->pkfont = false; + fontptr->honest = false; + +#if 0 + dpi = kpse_magstep_fix ((unsigned) (mag / 5.0 + .5), + xres, NULL); + tfontptr->font_mag = dpi * 5; /* save correct dpi */ +#endif + dpi = (int) (mag / 1000.0 * + (double) fontptr->scaledsize / fontptr->designsize * xres + 0.5); + + if (dpi == 0) /* allow for subtracting 1 */ + ++dpi; + + name = kpse_find_pk (fontptr->fontname, dpi, &font_ret); + if (name) + { + if (!STREQ (fontptr->fontname, font_ret.name)) + { +#if 0 + WARNING3 ("dvgt: Font %s not found, using %s at %d instead.\n", + fontptr->fontname, font_ret.name, font_ret.dpi); +#endif + } + else if (!kpse_bitmap_tolerance ((double) font_ret.dpi, (double) dpi)) + { +#if 0 + WARNING3 ("dvilj: Font %s at %d not found, using %d instead.\n", + fontptr->fontname, dpi, font_ret.dpi); +#endif + } + else + fontptr->honest = true; + + fontptr->fontspeclen = strlen (name); + strcpy (fontptr->fontspec, name); + free (name); + fontptr->fontexists = true; /* specified PK file exists */ + fontptr->pkfont = true; + + return true; + } + else + { + /* PK font file doesn't exist. */ + name = kpse_find_tfm (fontptr->fontname); + if (name) + { + fontptr->fontspeclen = strlen (name); + strcpy (fontptr->fontspec, name); + free (name); + + fontptr->fontexists = true; + fontptr->honest = true; + } + else + { + name = kpse_find_tfm (dummy_tfm); + if (name) + { + fontptr->fontspeclen = strlen (name); + strcpy (fontptr->fontspec, name); + free (name); + fontptr->fontexists = true; + } + } + } + + return true; +} +/* BuildFontSpec */ + +/*--------------------------------------------------------------------*/ + +boolean +OpenFontFile (char *name) +{ + /* Return TRUE if given file can be (unix-specifically) open-ed. + Only one font file will be open at any given time. + */ + + extern int currPTbuff; + extern int PTfile; + + currPTbuff = -1; /* impossible value for first GetPTByte */ + PTfile = open (name, O_RDONLY, 0); /* unix "open" returns -1 if fails */ + return (PTfile >= 0); +} +/* OpenFontFile */ + +/*--------------------------------------------------------------------*/ + +void +CloseFontFile () +{ + /* If there is a currently open font file, then close it. */ + + if (PTfile >= 0) + { + close (PTfile); + /* Be cautious: ensure PTfile is negative, after this function. */ + if (PTfile >= 0) + PTfile = -1; + } +} +/* CloseFontFile */ + +/*--------------------------------------------------------------------*/ + +static int +GetPTByte () +{ + /* Returns the value (unsigned) of the byte at PToffset and + advances PToffset for the next GetPTByte. + */ + + int Result, buffstart, result; + + buffstart = PToffset / bufflen * bufflen; /* 0, bufflen, 2*bufflen... */ + if (buffstart != currPTbuff) + { + currPTbuff = buffstart; + + if (PTfile < 0) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL ("PTfile not open in GetPTByte!"); + } + result = lseek (PTfile, buffstart, 0); + if (result != buffstart) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL ("lseek failed in GetPTByte!"); + } + result = read (PTfile, PTbuffer, bufflen); + if (result == -1) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL ("Read failed in GetPTByte!"); + } + } + Result = PTbuffer[PToffset - buffstart]; + PToffset++; + return Result; +} +/* GetPTByte */ + +/*--------------------------------------------------------------------*/ + +static int +SignedPTByte () +{ + /* the next byte, signed */ + int b; + + b = GetPTByte (); + if (b < 128) + return b; + else + return (b - 256); +} +/* SignedPTByte */ + +/*--------------------------------------------------------------------*/ + +static int +GetTwoPTBytes () +{ + /* the next 2 bytes, unsigned */ + int a, b; + + a = GetPTByte (); + b = GetPTByte (); + return (a * 256 + b); +} +/* GetTwoPTBytes */ + +/*--------------------------------------------------------------------*/ + +static int +SignedPTPair () +{ + /* the next 2 bytes, signed */ + int a, b; + + a = GetPTByte (); + b = GetPTByte (); + if (a < 128) + return (a * 256 + b); + else + return ((a - 256) * 256 + b); +} +/* SignedPTPair */ + +/*--------------------------------------------------------------------*/ + +/* UNUSED: */ +#ifdef GET_THREE_PT_BYTES +static int +GetThreePTBytes () +{ + /* the next 3 bytes, unsigned */ + int a, b, c; + + a = GetPTByte (); + b = GetPTByte (); + c = GetPTByte (); + return ((a * 256 + b) * 256 + c); +} +/* GetThreePTBytes */ +#endif /* GET_THREE_PT_BYTES */ + +/*--------------------------------------------------------------------*/ + +typedef struct int_or_bytes +{ + boolean b; + union + { + int int_; + char byt[4]; + } + UU; +} +int_or_bytes; + +/*--------------------------------------------------------------------*/ + +static int +SignedPTQuad () +{ + /* the next 4 bytes, signed */ + int w; + + byte3 (w) = GetPTByte (); + byte2 (w) = GetPTByte (); + byte1 (w) = GetPTByte (); + byte0 (w) = GetPTByte (); + return (w); +} +/* SignedPTQuad */ + +/*--------------------------------------------------------------------*/ + +static int +GetNyb () +{ + /* Return next nybble in PK file. */ + + if (bitweight == 0) + { + inputbyte = GetPTByte (); + bitweight = 16; /* for next call of GetNyb */ + return (inputbyte / 16); /* high nybble */ + } + else + { + bitweight = 0; /* for next call of GetNyb */ + return (inputbyte & 15); /* low nybble */ + } +} +/* GetNyb */ + +/*--------------------------------------------------------------------*/ + +static int +PackedNum () +{ + /* Return next run count using algorithm given in section 23 of PKtype. + A possible side-effect is to set the global repeatcount value used + to duplicate the current row. + */ + + int i, j; + + i = GetNyb (); + if (i == 0) + { + do + { + j = GetNyb (); + i++; + } + while (j == 0); + while (i > 0) + { + j = j * 16 + GetNyb (); + i--; + } + return (j + (13 - dynf) * 16 + dynf - 15); + } + else if (i <= dynf) + return i; + else if (i < 14) + return ((i - dynf - 1) * 16 + GetNyb () + dynf + 1); + else + { + if (i == 14) /* nybble = 15 */ + repeatcount = PackedNum (); /* recursive */ + else + repeatcount = 1; + return (PackedNum ()); /* recursive */ + } +} +/* PackedNum */ + +/*--------------------------------------------------------------------*/ + +boolean +GetBitmap (int ht, int wd, int mapadr, int_or_mptr * bitmap) +{ + /* Allocate space for bitmap and fill it in using information from + character definition starting at mapadr in currently open PK + file. Note that the memory used by a loaded bitmap is never + deallocated. Each bitmap row uses an integral number of words + (each 32 bits). Byte-aligned rows would use about 35% less + memory but would increase the processing time needed to display + each bitmap. It was felt that speed is more important than + memory. Return true if the bitmap is obtained, false if function + fails. + */ + + extern int bitweight; /* local to "fontreader.c" */ + + int_or_bptr wordptr, rowptr; + int i, j, flagbyte, wordwidth, wordweight, rowsleft, hbit, count, bitmapwords; + int word; + Word *bitmapptr = (Word *) NULL; + + wordwidth = (wd + 31) / 32; /* words in one row of bitmap */ + bitmapwords = ht * wordwidth; /* memory required by bitmap */ + + bitmapptr = (Word *) calloc (bitmapwords, sizeof (Word)); + if (bitmapptr == (Word *) NULL) + { + StartText (); + ResetVDU (); /* do before message since it might erase screen! */ + FATAL1 ("Out of memory. Character too big! size = %d", bitmapwords); + return false; /* Not Reached */ + } + bitmap->UU.mptr = bitmapptr; /* return start of bitmap */ + wordptr.UU.int_ = bitmap->UU.int_; + PToffset = mapadr; /* mapadr = flagbyte offset in PK file */ + + flagbyte = GetPTByte (); /* assume < 240 */ + dynf = flagbyte / 16; /* dynamic packing variable */ + turnon = ((flagbyte & 15) >= 8); /* is 1st pixel black? */ + flagbyte &= 7; /* value of bottom 3 bits */ + if (flagbyte < 4) /* skip short char preamble */ + PToffset += 10; + else if (flagbyte < 7) + PToffset += 16; + else + PToffset += 36; + + bitweight = 0; /* to get 1st inputbyte */ + if (dynf == 14) + { + /* raster info is a string of bits in the next (wd * ht + 7) DIV 8 bytes */ + + for (i = 1; i <= ht; i++) + { + word = 0; /* set all bits to 0 */ + wordweight = 31; /* leftmost bit */ + for (j = 1; j <= wd; j++) + { + if (bitweight == 0) + { + inputbyte = GetPTByte (); + bitweight = 8; + } + bitweight--; /* 7..0 */ + if ((unsigned) bitweight < 32 && ((1 << bitweight) & inputbyte)) + /* set bit */ + word |= 1 << wordweight; + if (wordweight > 0) + wordweight--; + else + { + *wordptr.UU.bptr = word; + wordptr.UU.int_ += 4; + word = 0; + wordweight = 31; + } + } + if (wordweight < 31) + { + *wordptr.UU.bptr = word; + wordptr.UU.int_ += 4; /* start of next word */ + } + } + } + else + { + /* raster info is encoded as run and repeat counts */ + + rowsleft = ht; + hbit = wd; + repeatcount = 0; + wordweight = 32; + word = 0; + rowptr = wordptr; /* remember start of row */ + while (rowsleft > 0) + { + count = PackedNum (); + while (count > 0) + { + if (count < wordweight && count < hbit) + { + if (turnon) + word = (word | gpower[wordweight]) & (~gpower[wordweight - count]); + hbit -= count; + wordweight -= count; + count = 0; + continue; + } + if (count >= hbit && hbit <= wordweight) + { + if (turnon) + word = (word | gpower[wordweight]) & (~gpower[wordweight - hbit]); + *wordptr.UU.bptr = word; + /* end of current row, so duplicate repeatcount times */ + for (i = 1; i <= repeatcount; i++) + { + for (j = 1; j <= wordwidth; j++) + { + wordptr.UU.int_ += 4; + *wordptr.UU.bptr = *rowptr.UU.bptr; + rowptr.UU.int_ += 4; + } + } + rowsleft += -repeatcount - 1; + repeatcount = 0; + word = 0; + wordptr.UU.int_ += 4; + rowptr = wordptr; /* remember start of next row */ + wordweight = 32; + count -= hbit; + hbit = wd; + } + else + { + if (turnon) + word |= gpower[wordweight]; + *wordptr.UU.bptr = word; + wordptr.UU.int_ += 4; + word = 0; + count -= wordweight; + hbit -= wordweight; + wordweight = 32; + } + } + turnon = !turnon; + } + } + return true; +} +/* GetBitmap */ + +/*--------------------------------------------------------------------*/ + +static int +FixToDVI (int scale, int b0, int b1, int b2, int b3) +/* scale = currfont->scaledsize; */ +/* fix width: 4 bytes */ +{ + /* Convert the given fix width (made up of 4 bytes) into DVI units + using the method recommended in DVITYPE. + Added local scale to avoid changing scaledsize; thanks to Niel Kempson + for reporting this bug. + */ + + int dviwidth = 0; + int alpha, beta, temp; + + alpha = scale * 16; + beta = 16; + while (scale >= 0x800000) + { /* 2^23sp = 128pt */ + scale /= 2; + beta /= 2; + } + temp = ((b3 * scale / 0x100 + b2 * scale) / 0x100 + b1 * scale) / beta; + + if (b0 <= 0) + dviwidth = temp; + else if (b0 == 255) + dviwidth = (temp - alpha); + else + { + dviwidth = 0; /* keep compiler happy, if necessary */ + + StartText (); + ResetVDU (); /* let message stay */ + + FATAL1 ("Bad TFM width! 1st byte = %d.", b0); + } + + return dviwidth; +} +/* FixToDVI */ + +/*--------------------------------------------------------------------*/ + +#define pkid 89 +#define pkpost 245 +#define pknoop 246 +#define pkpre 247 + +static void +PKFillPixelTable (fontinfo * currfont) +{ + /* Fill the pixeltable for currfont^ using the font directory info + in the currently open PK file. + */ + + int i, j, flagbyte, flagpos; + int chcode; /* char. code, assumed to be <= maxTeXchar */ + int packetlen, endofpacket, b0, b1, b2, b3; /* 4 bytes in TFM width */ + _REC_pixeltable *pix_tab; + + PToffset = 0; /* move to first byte */ + + if (GetPTByte () != pkpre) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL1 ("Bad PK pre command in `%s'.", currfont->fontspec); + } + if (GetPTByte () != pkid) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL1 ("Bad PK id byte in `%s'.", currfont->fontspec); + } + j = GetPTByte (); /* length of comment */ + PToffset += j + 16; /* skip rest of preamble */ + + for (i = 0; i <= maxTeXchar; i++) + { + pix_tab = &currfont->pixelptr[i]; + pix_tab->mapadr = 0; /* all chars absent initially */ + pix_tab->bitmap.UU.mptr = (Word *) NULL; + } + + while (true) + { + flagpos = PToffset; /* remember position of flagbyte */ + flagbyte = GetPTByte (); + if (flagbyte < 240) + { /* read character definition */ + + int scale = currfont->scaledsize; /* For FixToDVI */ + + flagbyte &= 7; /* value of bottom 3 bits */ + if (flagbyte < 4) + { /* short char preamble */ + packetlen = flagbyte * 256 + GetPTByte (); + chcode = GetPTByte (); + endofpacket = packetlen + PToffset; + pix_tab = &currfont->pixelptr[chcode]; + b1 = GetPTByte (); + b2 = GetPTByte (); + b3 = GetPTByte (); + pix_tab->dwidth = FixToDVI (scale, 0, b1, b2, b3); /* b0 = 0 */ + pix_tab->pwidth = GetPTByte (); + pix_tab->wd = GetPTByte (); + pix_tab->ht = GetPTByte (); + pix_tab->xo = SignedPTByte (); + pix_tab->yo = SignedPTByte (); + } + else if (flagbyte < 7) + { + packetlen = (flagbyte - 4) * 65536 + GetTwoPTBytes (); + chcode = GetPTByte (); + endofpacket = packetlen + PToffset; + pix_tab = &currfont->pixelptr[chcode]; + b1 = GetPTByte (); + b2 = GetPTByte (); + b3 = GetPTByte (); + pix_tab->dwidth = FixToDVI (scale, 0, b1, b2, b3); /* b0 = 0 */ + pix_tab->pwidth = GetTwoPTBytes (); + pix_tab->wd = GetTwoPTBytes (); + pix_tab->ht = GetTwoPTBytes (); + pix_tab->xo = SignedPTPair (); + pix_tab->yo = SignedPTPair (); + } + else + { + packetlen = SignedPTQuad (); + chcode = SignedPTQuad (); + endofpacket = packetlen + PToffset; + pix_tab = &currfont->pixelptr[chcode]; + b0 = GetPTByte (); + b1 = GetPTByte (); + b2 = GetPTByte (); + b3 = GetPTByte (); + pix_tab->dwidth = FixToDVI (scale, b0, b1, b2, b3); + pix_tab->pwidth = SignedPTQuad () / 65536; /* dx in pixels */ + PToffset += 4; /* skip dy */ + pix_tab->wd = SignedPTQuad (); + pix_tab->ht = SignedPTQuad (); + pix_tab->xo = SignedPTQuad (); + pix_tab->yo = SignedPTQuad (); + } + pix_tab = &currfont->pixelptr[chcode]; /* position of flagbyte */ + if (pix_tab->wd == 0 || pix_tab->ht == 0) + pix_tab->mapadr = 0; /* no bitmap */ + else + pix_tab->mapadr = flagpos; + PToffset = endofpacket; /* skip raster info */ + continue; + } + switch (flagbyte) + { + case 240: + case 241: + case 242: + case 243: + i = 0; + for (j = 240; j <= flagbyte; j++) + i = i * 256 + GetPTByte (); + PToffset += i; /* skip special parameter */ + break; + case 244: /* skip numspecial param */ + PToffset += 4; + break; + case pknoop: /* do nothing */ + break; + case pkpost: /* no more char defs */ + goto _L888; + break; + + default: + StartText (); + ResetVDU (); /* let message stay */ + + FATAL1 ("Bad PK flag byte in `%s'.", currfont->fontspec); + } + } /* of LOOP; flagbyte = pkpost */ +_L888:; + + /* extended short char preamble */ + /* long char preamble */ +} +/* PKFillPixelTable */ + +#undef pkid +#undef pkpost +#undef pknoop +#undef pkpre + +/*--------------------------------------------------------------------*/ + +static void +ReadTFMIntegers () +{ + /* Read the first 6 (six) 16-bit integers in the TFM file. */ + /* These give the dimensions of the arrays that constitute the rest */ + /* of the TFM file. */ + /* See TFtoPL section 8. */ + + PToffset = 0; /* start reading at 1st byte in TFM file */ + lf = GetTwoPTBytes (); /* length of TFM file, in words: 0 <= lf < 2^15. */ + lh = GetTwoPTBytes (); /* length of header, in words: 2 <= lh. */ + bc = GetTwoPTBytes (); /* smallest character code in font */ + ec = GetTwoPTBytes (); /* largest character code in font */ + nw = GetTwoPTBytes (); /* number of words in width table */ + nh = GetTwoPTBytes (); /* number of words in height table */ + + /* sanity check of lf */ + if (!(0 <= lf && lf < 1 << 15)) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL2 ("TFM file length given as: lf = %d words. Should have 0 <= lf < %d words.", lf, 1 << 15); + } + /* sanity check of lh */ + if (!(2 <= lh)) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL1 ("TFM's Header length given as: lh = %d words. Should have lh >= 2 (two) words.", lh); + } + /* sanity check of bc and ec */ + if (!(0 <= bc && bc - 1 <= ec && ec <= maxTeXchar)) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL2 ("First & last char codes = (bc, ec) = (%d, %d). Should have 0 <= bc <= ec <= maxTeXchar = 255.", bc, ec); + } + /* sanity check of nw */ + if (!(0 <= nw && nw < 1 << 15)) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL2 ("Number of Width Table words given as: nw = %d. Should have 0 <= nw < %d words.", nw, 1 << 15); + } + /* sanity check of nh */ + if (!(0 <= nh && nh < 1 << 15)) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL2 ("Number of Height Table words given as: nh = %d. Should have 0 <= nh < %d.", nh, 1 << 15); + } +} +/* ReadTFMIntegers */ + +/*--------------------------------------------------------------------*/ + +static void +ReadTFMCharInfo () +{ + /* Read the TFMinfo array. See TFtoPL section 11. */ + + int c, i; + _REC_TFMinfo *tfm_inf; + + PToffset = (6 + lh) * 4; /* offset of TFMinfo array (in bytes) */ + /* 6 words of dimension info, plus header */ + for (c = bc; c <= ec; c++) + { + tfm_inf = &TFMinfo[c]; + tfm_inf->wdindex = GetPTByte () * 4; /* offset from start of width array */ + i = GetPTByte (); /* 2nd byte contains htindex and dpindex */ + tfm_inf->htindex = i / 16 * 4; /* offset from start of height array */ + tfm_inf->dpindex = (i & 15) * 4; /* offset from start of depth array */ + PToffset += 2; /* skip itindex and remainder bytes */ + } +} +/* ReadTFMCharInfo */ + +/*--------------------------------------------------------------------*/ + +static void +ReadTFMCharMetrics () +{ + /* Read the charmetrics array using the indices in TFMinfo. */ + + int wdbase = lh * 4 + (ec - bc + 1) * 4 + 24; /* offset of width array */ + int htbase = wdbase + nw * 4; /* offset of height array */ + int dpbase = htbase + nh * 4; /* offset of depth array */ + int c; + + for (c = bc; c <= ec; c++) + { + _REC_TFMinfo *tfm_inf = &TFMinfo[c]; + _REC_charmetrics *char_met = &charmetrics[c]; + int b; + + PToffset = wdbase + tfm_inf->wdindex; + for (b = 0; b <= 3; b++) + char_met->width[b] = GetPTByte (); + PToffset = htbase + tfm_inf->htindex; + for (b = 0; b <= 3; b++) + char_met->height[b] = GetPTByte (); + PToffset = dpbase + tfm_inf->dpindex; + for (b = 0; b <= 3; b++) + char_met->depth[b] = GetPTByte (); + } +} +/* ReadTFMCharMetrics */ + +/*--------------------------------------------------------------------*/ + +static void +TFMFillPixelTable (fontinfo * currfont) +{ + /* Fill the pixeltable for * currfont + (a PostScript or other font for which the PK file is missing), + using information in the currently open TFM file. + */ + + int c; + + ReadTFMIntegers (); /* read lf..nh */ + ReadTFMCharInfo (); /* fill TFMinfo array */ + ReadTFMCharMetrics (); /* fill charmetrics array */ + + for (c = 0; c < bc; c++) /* chars < bc don't exist */ + currfont->pixelptr[c].mapadr = 0; + + for (c = ec + 1; c <= maxTeXchar; c++) /* chars > ec don't exist */ + currfont->pixelptr[c].mapadr = 0; + + for (c = bc; c <= ec; c++) + { + _REC_pixeltable *pix_tab = &currfont->pixelptr[c]; + _REC_charmetrics *char_met = &charmetrics[c]; + int scale = currfont->scaledsize; /* For FixToDVI */ + int dheight, pheight, ddepth, pdepth; + + pix_tab->dwidth = FixToDVI (scale, + char_met->width[0], char_met->width[1], + char_met->width[2], char_met->width[3]); + + dheight = FixToDVI (scale, + char_met->height[0], char_met->height[1], + char_met->height[2], char_met->height[3]); + + ddepth = FixToDVI (scale, + char_met->depth[0], char_met->depth[1], + char_met->depth[2], char_met->depth[3]); + + /* convert DVI units to pixels */ + + pix_tab->pwidth = XPixelRound (pix_tab->dwidth); + pheight = YPixelRound (dheight); + pdepth = YPixelRound (ddepth); + + /* Since we don't have access to PK bitmap info, + we will have to use the TFM width/height/depth info + to approximate wd, ht, xo, yo. + */ + + pix_tab->wd = pix_tab->pwidth; + pix_tab->wd -= pix_tab->wd / 8; /* better approximation */ + pix_tab->ht = pheight + pdepth; + pix_tab->xo = 0; + pix_tab->yo = pheight - 1; + if (pix_tab->wd == 0 || pix_tab->ht == 0) /* anything but 0 */ + pix_tab->mapadr = 0; /* char blank or not in font */ + else + pix_tab->mapadr = 1; + pix_tab->bitmap.UU.mptr = (Word *) NULL; + } +} +/* TFMFillPixelTable */ + +/*--------------------------------------------------------------------*/ + + +static void +AbsentFillPixelTable (fontinfo * currfont) +{ + /* Fill the pixeltable for *currfont + * (a PostScript or other font that is missing and cannot be replaced), + * using information in the DVI file, since we have nothing else. + * + * Updated (Wed 9 June 1993) to use cmr10 info., as that is the most + * common font in most present-day documents. + */ + + int c; + + for (c = 0; c <= maxTeXchar; c++) + { + _REC_pixeltable *pix_tab = &currfont->pixelptr[c]; + + /* scaled size of font in DVI units */ + int scale = currfont->scaledsize; /* For character size estimate */ + int dheight, ddepth; /* estimated height and depth, in DVI units */ + int pheight, pdepth; /* same, in pixels */ + + /* Let character be a square, scaledsize high and wide, zero depth. */ + /* For "example.tex", this width and height are not too bad. */ + pix_tab->dwidth = scale / 2; /* wild, hazardous guess */ + dheight = scale; + ddepth = 0; + + /* convert DVI units to pixels */ + pix_tab->pwidth = XPixelRound (pix_tab->dwidth); + pheight = YPixelRound (dheight); + pdepth = YPixelRound (ddepth); + + /* Since we don't have access to PK bitmap or to TFM metric info, + we will have to use the guessed (DVI) width/height/depth info + to approximate wd, ht, xo, yo. + */ + + pix_tab->wd = pix_tab->pwidth; + pix_tab->wd -= pix_tab->wd / 8; /* better approximation */ + pix_tab->ht = pheight + pdepth; + pix_tab->xo = 0; + pix_tab->yo = pheight - 1; + if (pix_tab->wd == 0 || pix_tab->ht == 0) /* anything but 0 */ + pix_tab->mapadr = 0; /* char blank or not in font */ + else + pix_tab->mapadr = 1; + pix_tab->bitmap.UU.mptr = (Word *) NULL; + } +} +/* AbsentFillPixelTable */ + +/*--------------------------------------------------------------------*/ + +void +PixelTableRoutine (fontinfo * currfont) +{ + /* DVIReader has just allocated a new pixeltable for currfont, and + calls this routine from InterpretPage only ONCE per font + (the first time the font is used). + If this is the first time we've seen the font, + then we build fontspec first. + (Note that ShowStatistics, in the main program, may call BuildFontSpec + first.) + If we can't open the font file, we return dummy_pk or dummy_tfm values, + but using the current font's scaledsize. + */ + + if (!CheckFontPtr (currfont)) + return; + + /* Try to find and fopen (& fclose) PK file; if that fails, try TFM file. */ + if (currfont->fontspeclen == 0) + BuildFontSpec (currfont); + + if (currfont->fontexists && !OpenFontFile (currfont->fontspec)) + { + StartText (); + ResetVDU (); /* let message stay */ + + FATAL2 ("fopen-ed but couldn't open file `%s' for font `%s'", + currfont->fontspec, currfont->fontname); + } + /* gt - is this right when a dummy font is used? */ + + if (currfont->fontexists) + { + if (currfont->pkfont) + PKFillPixelTable (currfont); + else + TFMFillPixelTable (currfont); + + CloseFontFile (); + } + else + { + AbsentFillPixelTable (currfont); + } +} +/* PixelTableRoutine */ + +/*--------------------------------------------------------------------*/ + +void +InitFontReader () +{ + /* This routine initializes some global variables. */ + + int i; + + gpower[0] = 0; + for (i = 1; i <= 32; i++) /* used in GetBitmap */ + gpower[i] = gpower[i - 1] | (1 << (i - 1)); +} +/* InitFontReader */ + +/*--------------------------------------------------------------------*/ + +/* end fontreader.c */ |