summaryrefslogtreecommitdiff
path: root/dviware/dvgtk/fontreader.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvgtk/fontreader.c')
-rw-r--r--dviware/dvgtk/fontreader.c1079
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 */