summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/xdvik/pk.c')
-rw-r--r--Build/source/texk/xdvik/pk.c387
1 files changed, 387 insertions, 0 deletions
diff --git a/Build/source/texk/xdvik/pk.c b/Build/source/texk/xdvik/pk.c
new file mode 100644
index 00000000000..4ef0170ae48
--- /dev/null
+++ b/Build/source/texk/xdvik/pk.c
@@ -0,0 +1,387 @@
+/*========================================================================*\
+
+Copyright (c) 1990-2004 Paul Vojta
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+NOTE:
+ xdvi is based on prior work, as noted in the modification history
+ in xdvi.c.
+
+\*========================================================================*/
+
+/*
+ * PK font reading routines.
+ * Public routines are read_PK_index and read_PK_char.
+ */
+
+#include "xdvi-config.h"
+#include "xdvi.h"
+#include "dvi-init.h"
+#include "util.h"
+
+#define PK_ID 89
+#define PK_CMD_START 240
+#define PK_X1 240
+#define PK_X2 241
+#define PK_X3 242
+#define PK_X4 243
+#define PK_Y 244
+#define PK_POST 245
+#define PK_NOOP 246
+#define PK_PRE 247
+
+static int PK_flag_byte;
+static unsigned PK_input_byte;
+static int PK_bitpos;
+static int PK_dyn_f;
+static int PK_repeat_count;
+
+static int
+PK_get_nyb(FILE *fp)
+{
+ unsigned temp;
+ if (PK_bitpos < 0) {
+ PK_input_byte = get_byte(fp);
+ PK_bitpos = 4;
+ }
+ temp = PK_input_byte >> PK_bitpos;
+ PK_bitpos -= 4;
+ return (temp & 0xf);
+}
+
+
+static int
+PK_packed_num(FILE *fp)
+{
+ int i, j;
+
+ if ((i = PK_get_nyb(fp)) == 0) {
+ do {
+ j = PK_get_nyb(fp);
+ ++i;
+ }
+ while (j == 0);
+ while (i > 0) {
+ j = (j << 4) | PK_get_nyb(fp);
+ --i;
+ }
+ return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
+ }
+ else {
+ if (i <= PK_dyn_f)
+ return i;
+ if (i < 14)
+ return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
+ + PK_dyn_f + 1);
+ if (i == 14)
+ PK_repeat_count = PK_packed_num(fp);
+ else
+ PK_repeat_count = 1;
+ return PK_packed_num(fp);
+ }
+}
+
+
+static void
+PK_skip_specials(struct font *fontp)
+{
+ int i, j;
+ FILE *fp = fontp->file;
+
+ do {
+ PK_flag_byte = get_byte(fp);
+ if (PK_flag_byte >= PK_CMD_START) {
+ switch (PK_flag_byte) {
+ case PK_X1:
+ case PK_X2:
+ case PK_X3:
+ case PK_X4:
+ i = 0;
+ for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
+ i = (i << 8) | get_byte(fp);
+ while (i--)
+ (void)get_byte(fp);
+ break;
+ case PK_Y:
+ (void)get_bytes(fp, 4);
+ case PK_POST:
+ case PK_NOOP:
+ break;
+ default:
+ XDVI_FATAL((stderr, "Unexpected %d in PK file %s", PK_flag_byte,
+ fontp->filename));
+ break;
+ }
+ }
+ }
+ while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
+}
+
+/*
+ * Public routines
+ */
+
+static void
+read_PK_char(struct font *fontp,
+ wide_ubyte ch)
+{
+ int i, j;
+ int n;
+ int row_bit_pos;
+ Boolean paint_switch;
+ bmUnitT *cp;
+ struct glyph *g;
+ FILE *fp = fontp->file;
+ long fpwidth;
+ bmUnitT word = 0;
+ int word_weight, bytes_wide;
+ int rows_left, h_bit, count;
+
+ g = &fontp->glyph[ch];
+ PK_flag_byte = g->x2;
+ PK_dyn_f = PK_flag_byte >> 4;
+ paint_switch = ((PK_flag_byte & 8) != 0);
+ PK_flag_byte &= 0x7;
+ if (PK_flag_byte == 7)
+ n = 4;
+ else if (PK_flag_byte > 3)
+ n = 2;
+ else
+ n = 1;
+
+ if (globals.debug & DBG_PK)
+ printf("loading pk char %d, char type %d ", ch, n);
+
+ /*
+ * now read rest of character preamble
+ */
+ if (n != 4)
+ fpwidth = get_bytes(fp, 3);
+ else {
+ fpwidth = get_lbytes(fp, 4);
+ (void)get_bytes(fp, 4); /* horizontal escapement */
+ }
+ (void)get_bytes(fp, n); /* vertical escapement */
+ {
+ unsigned long w, h;
+
+ w = get_bytes(fp, n);
+ h = get_bytes(fp, n);
+ /* bitmap.w and bitmap.h are of type `unsigned short', so check for possible
+ overflow here. USHRT_MAX should be sufficient, since a character of
+ 30pt at 1200dpi requires about 560 x 560 pixels; and the maximum
+ bitmap of size USHRT_MAX * USHRT_MAX would consume USHRT_MAX * USHRT_MAX / 8
+ bytes ~= 530MB of RAM (per character/font!)
+ */
+ if (w > USHRT_MAX || h > USHRT_MAX)
+ XDVI_FATAL((stderr, "Character %d too large (%ld x %ld, max is %d x %d) in file %s",
+ ch, w, h, USHRT_MAX, USHRT_MAX, fontp->fontname));
+ g->bitmap.w = w;
+ g->bitmap.h = h;
+ }
+ g->x = get_lbytes(fp, n);
+ g->y = get_lbytes(fp, n);
+
+ g->dvi_adv = fontp->dimconv * fpwidth;
+
+ if (globals.debug & DBG_PK) {
+ if (g->bitmap.w != 0)
+ printf(", size=%dx%d, dvi_adv=%ld", g->bitmap.w, g->bitmap.h,
+ g->dvi_adv);
+ putchar('\n');
+ }
+
+ alloc_bitmap(&g->bitmap);
+ cp = (bmUnitT *) g->bitmap.bits;
+
+ /*
+ * read character data into *cp
+ */
+ bytes_wide = ROUNDUP((int)g->bitmap.w, BMBITS) * BMBYTES;
+ PK_bitpos = -1;
+ if (PK_dyn_f == 14) { /* get raster by bits */
+ memset(g->bitmap.bits, 0, (int)g->bitmap.h * bytes_wide);
+ for (i = 0; i < (int)g->bitmap.h; i++) { /* get all rows */
+ cp = ADD(g->bitmap.bits, i * bytes_wide);
+#ifndef WORDS_BIGENDIAN
+ row_bit_pos = -1;
+#else
+ row_bit_pos = BMBITS;
+#endif
+ for (j = 0; j < (int)g->bitmap.w; j++) { /* get one row */
+ if (--PK_bitpos < 0) {
+ word = get_byte(fp);
+ PK_bitpos = 7;
+ }
+#ifndef WORDS_BIGENDIAN
+ if (++row_bit_pos >= BMBITS) {
+ cp++;
+ row_bit_pos = 0;
+ }
+#else
+ if (--row_bit_pos < 0) {
+ cp++;
+ row_bit_pos = BMBITS - 1;
+ }
+#endif
+ if (word & (1 << PK_bitpos))
+ *cp |= 1 << row_bit_pos;
+ }
+ }
+ }
+ else { /* get packed raster */
+ rows_left = g->bitmap.h;
+ h_bit = g->bitmap.w;
+ PK_repeat_count = 0;
+ word_weight = BMBITS;
+ word = 0;
+ while (rows_left > 0) {
+ count = PK_packed_num(fp);
+ while (count > 0) {
+ if (count < word_weight && count < h_bit) {
+#ifndef WORDS_BIGENDIAN
+ if (paint_switch)
+ word |= bit_masks[count] << (BMBITS - word_weight);
+#endif
+ h_bit -= count;
+ word_weight -= count;
+#ifdef WORDS_BIGENDIAN
+ if (paint_switch)
+ word |= bit_masks[count] << word_weight;
+#endif
+ count = 0;
+ }
+ else if (count >= h_bit && h_bit <= word_weight) {
+ if (paint_switch)
+ word |= bit_masks[h_bit] <<
+#ifndef WORDS_BIGENDIAN
+ (BMBITS - word_weight);
+#else
+ (word_weight - h_bit);
+#endif
+ *cp++ = word;
+ /* "output" row(s) */
+ for (i = PK_repeat_count * bytes_wide / BMBYTES; i > 0; --i) {
+ *cp = *SUB(cp, bytes_wide);
+ ++cp;
+ }
+ rows_left -= PK_repeat_count + 1;
+ PK_repeat_count = 0;
+ word = 0;
+ word_weight = BMBITS;
+ count -= h_bit;
+ h_bit = g->bitmap.w;
+ }
+ else {
+ if (paint_switch)
+#ifndef WORDS_BIGENDIAN
+ word |= bit_masks[word_weight] <<
+ (BMBITS - word_weight);
+#else
+ word |= bit_masks[word_weight];
+#endif
+ *cp++ = word;
+ word = 0;
+ count -= word_weight;
+ h_bit -= word_weight;
+ word_weight = BMBITS;
+ }
+ }
+ paint_switch = 1 - paint_switch;
+ }
+ if (cp != ((bmUnitT *) (g->bitmap.bits + bytes_wide * g->bitmap.h)))
+ XDVI_FATAL((stderr, "Wrong number of bits stored: char. %d, font %s", ch,
+ fontp->fontname));
+ if (rows_left != 0 || h_bit != g->bitmap.w)
+ XDVI_FATAL((stderr, "Bad pk file (%s), too many bits", fontp->fontname));
+ }
+}
+
+void
+read_PK_index(struct font *fontp, wide_bool hushcs)
+{
+ int hppp, vppp;
+ long checksum;
+
+ fontp->read_char = read_PK_char;
+ if (globals.debug & DBG_PK)
+ printf("Reading PK pixel file %s\n", fontp->filename);
+
+ fseek(fontp->file, (long)get_byte(fontp->file), SEEK_CUR); /* skip comment */
+
+ (void)get_bytes(fontp->file, 4); /* skip design size */
+ checksum = get_bytes(fontp->file, 4);
+ if (checksum != fontp->checksum && checksum != 0 && fontp->checksum != 0
+ && !hushcs)
+ XDVI_WARNING((stderr, "Checksum mismatch (dvi = %lu, pk = %lu) in font file %s",
+ fontp->checksum, checksum, fontp->filename));
+ hppp = get_lbytes(fontp->file, 4);
+ vppp = get_lbytes(fontp->file, 4);
+ if (hppp != vppp && (globals.debug & DBG_PK))
+ printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
+ /*
+ * Prepare glyph array.
+ */
+ fontp->glyph = xmalloc(256 * sizeof(struct glyph));
+ memset((char *)fontp->glyph, 0, 256 * sizeof(struct glyph));
+ /*
+ * Read glyph directory (really a whole pass over the file).
+ */
+ for (;;) {
+ int bytes_left, flag_low_bits;
+ unsigned int ch;
+
+ PK_skip_specials(fontp);
+ if (PK_flag_byte == PK_POST)
+ break;
+ flag_low_bits = PK_flag_byte & 0x7;
+ if (flag_low_bits == 7) {
+ bytes_left = get_bytes(fontp->file, 4);
+ ch = get_bytes(fontp->file, 4);
+ }
+ else if (flag_low_bits > 3) {
+ bytes_left = ((flag_low_bits - 4) << 16) + get_bytes(fontp->file, 2);
+ ch = get_byte(fontp->file);
+ }
+ else {
+ bytes_left = (flag_low_bits << 8) + get_byte(fontp->file);
+ ch = get_byte(fontp->file);
+ }
+ fontp->glyph[ch].addr = ftell(fontp->file);
+ fontp->glyph[ch].x2 = PK_flag_byte;
+#ifdef linux
+# ifndef SHORTSEEK
+# define SHORTSEEK 2048
+# endif
+ /* A bug in Linux libc (as of 18oct94) makes a short read faster
+ than a short forward seek. Totally non-intuitive. */
+ if (bytes_left > 0 && bytes_left < SHORTSEEK) {
+ char *dummy = xmalloc(bytes_left);
+ fread(dummy, 1, bytes_left, fontp->file);
+ free(dummy);
+ }
+ else
+ /* seek backward, or long forward */
+#endif /* linux */
+ fseek(fontp->file, (long)bytes_left, SEEK_CUR);
+ if (globals.debug & DBG_PK)
+ printf("Scanning pk char %u, at %ld.\n", ch, fontp->glyph[ch].addr);
+ }
+}