home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / xdvik / pk.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  11KB  |  403 lines

  1. /*
  2.  * Copyright (c) 1994 Paul Vojta.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 1. Redistributions of source code must retain the above copyright
  8.  *    notice, this list of conditions and the following disclaimer.
  9.  * 2. Redistributions in binary form must reproduce the above copyright
  10.  *    notice, this list of conditions and the following disclaimer in the
  11.  *    documentation and/or other materials provided with the distribution.
  12.  *
  13.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23.  * SUCH DAMAGE.
  24.  *
  25.  * NOTE:
  26.  *    xdvi is based on prior work as noted in the modification history, below.
  27.  */
  28.  
  29. /*
  30.  * DVI previewer for X.
  31.  *
  32.  * Eric Cooper, CMU, September 1985.
  33.  *
  34.  * Code derived from dvi-imagen.c.
  35.  *
  36.  * Modification history:
  37.  * 1/1986    Modified for X.10    --Bob Scheifler, MIT LCS.
  38.  * 7/1988    Modified for X.11    --Mark Eichin, MIT
  39.  * 12/1988    Added 'R' option, toolkit, magnifying glass
  40.  *                    --Paul Vojta, UC Berkeley.
  41.  * 2/1989    Added tpic support    --Jeffrey Lee, U of Toronto
  42.  * 4/1989    Modified for System V    --Donald Richardson, Clarkson Univ.
  43.  * 3/1990    Added VMS support    --Scott Allendorf, U of Iowa
  44.  * 7/1990    Added reflection mode    --Michael Pak, Hebrew U of Jerusalem
  45.  * 1/1992    Added greyscale code    --Till Brychcy, Techn. Univ. Muenchen
  46.  *                      and Lee Hetherington, MIT
  47.  * 4/1994    Added DPS support, bounding box
  48.  *                    --Ricardo Telichevesky
  49.  *                      and Luis Miguel Silveira, MIT RLE.
  50.  */
  51.  
  52. #include "config.h"
  53.  
  54. /***
  55.  ***    PK font reading routines.
  56.  ***    Public routines are read_PK_index and read_PK_char.
  57.  ***/
  58.  
  59. #define PK_ID      89
  60. #define PK_CMD_START 240
  61. #define PK_X1     240
  62. #define PK_X2     241
  63. #define PK_X3     242
  64. #define PK_X4     243
  65. #define PK_Y      244
  66. #define PK_POST   245
  67. #define PK_NOOP   246
  68. #define PK_PRE    247
  69.  
  70. static    int    PK_flag_byte;
  71. static    unsigned PK_input_byte;
  72. static    int    PK_bitpos;
  73. static    int    PK_dyn_f;
  74. static    int    PK_repeat_count;
  75.  
  76. static    int
  77. PK_get_nyb(fp)
  78.     register FILE *fp;
  79. {
  80.     unsigned temp;
  81.     if (PK_bitpos < 0) {
  82.         PK_input_byte = one(fp);
  83.         PK_bitpos = 4;
  84.     }
  85.     temp = PK_input_byte >> PK_bitpos;
  86.     PK_bitpos -= 4;
  87.     return (temp & 0xf);
  88. }
  89.  
  90.  
  91. static    int
  92. PK_packed_num(fp)
  93.     register FILE *fp;
  94. {
  95.     int    i,j;
  96.  
  97.     if ((i = PK_get_nyb(fp)) == 0) {
  98.         do {
  99.         j = PK_get_nyb(fp);
  100.         ++i;
  101.         }
  102.         while (j == 0);
  103.         while (i > 0) {
  104.         j = (j << 4) | PK_get_nyb(fp);
  105.         --i;
  106.         }
  107.         return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
  108.     }
  109.     else {
  110.         if (i <= PK_dyn_f) return i;
  111.         if (i < 14)
  112.         return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
  113.             + PK_dyn_f + 1);
  114.         if (i == 14) PK_repeat_count = PK_packed_num(fp);
  115.         else PK_repeat_count = 1;
  116.         return PK_packed_num(fp);
  117.     }
  118. }
  119.  
  120.  
  121. static    void
  122. PK_skip_specials(fontp)
  123.     register struct font *fontp;
  124. {
  125.     int i,j;
  126.     register FILE *fp = fontp->file;
  127.  
  128.     do {
  129.         PK_flag_byte = one(fp);
  130.         if (PK_flag_byte >= PK_CMD_START) {
  131.         switch (PK_flag_byte) {
  132.             case PK_X1 :
  133.             case PK_X2 :
  134.             case PK_X3 :
  135.             case PK_X4 :
  136.             i = 0;
  137.             for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
  138.                 i = (i << 8) | one(fp);
  139.             while (i--) (void) one(fp);
  140.             break;
  141.             case PK_Y :
  142.             (void) four(fp);
  143.             case PK_POST :
  144.             case PK_NOOP :
  145.             break;
  146.             default :
  147.             oops("Unexpected %d in PK file %s", PK_flag_byte,
  148.                 fontp->filename);
  149.             break;
  150.         }
  151.         }
  152.     }
  153.     while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
  154. }
  155.  
  156. /*
  157.  *    Public routines
  158.  */
  159.  
  160. static    void
  161. #if    NeedFunctionPrototypes
  162. read_PK_char(register struct font *fontp, wide_ubyte ch)
  163. #else    /* !NeedFunctionPrototypes */
  164. read_PK_char(fontp, ch)
  165.     register struct font *fontp;
  166.     ubyte    ch;
  167. #endif    /* NeedFunctionPrototypes */
  168. {
  169.     int    i, j;
  170.     int    n;
  171.     int    row_bit_pos;
  172.     Boolean    paint_switch;
  173.     BMUNIT    *cp;
  174.     register struct glyph *g;
  175.     register FILE *fp = fontp->file;
  176.     long    fpwidth;
  177.     BMUNIT    word;
  178.     int    word_weight, bytes_wide;
  179.     int    rows_left, h_bit, count;
  180.  
  181.     g = &fontp->glyph[ch];
  182.     PK_flag_byte = g->x2;
  183.     PK_dyn_f = PK_flag_byte >> 4;
  184.     paint_switch = ((PK_flag_byte & 8) != 0);
  185.     PK_flag_byte &= 0x7;
  186.     if (PK_flag_byte == 7) n = 4;
  187.     else if (PK_flag_byte > 3) n = 2;
  188.     else n = 1;
  189.  
  190.     if (debug & DBG_PK) Printf("loading pk char %d, char type %d ", ch, n);
  191.  
  192.     /*
  193.      * now read rest of character preamble
  194.      */
  195.     if (n != 4) fpwidth = num(fp, 3);
  196.     else {
  197.         fpwidth = sfour(fp);
  198.         (void) four(fp);    /* horizontal escapement */
  199.     }
  200.     (void) num(fp, n);    /* vertical escapement */
  201.     {
  202.         unsigned long w, h;
  203.  
  204.         w = num(fp, n);
  205.         h = num(fp, n);
  206.         if (w > 0x7fff || h > 0x7fff)
  207.         oops("Character %d too large in file %s", ch, fontp->fontname);
  208.         g->bitmap.w = w;
  209.         g->bitmap.h = h;
  210.     }
  211.     g->x = snum(fp, n);
  212.     g->y = snum(fp, n);
  213.  
  214.     g->dvi_adv = fontp->dimconv * fpwidth;
  215.  
  216.     if (debug & DBG_PK) {
  217.         if (g->bitmap.w != 0)
  218.         Printf(", size=%dx%d, dvi_adv=%ld", g->bitmap.w, g->bitmap.h,
  219.             g->dvi_adv);
  220.         Putchar('\n');
  221.     }
  222.  
  223.     alloc_bitmap(&g->bitmap);
  224.     cp = (BMUNIT *) g->bitmap.bits;
  225.  
  226.     /*
  227.      * read character data into *cp
  228.      */
  229.     bytes_wide = ROUNDUP((int) g->bitmap.w, BITS_PER_BMUNIT)
  230.         * BYTES_PER_BMUNIT;
  231.     PK_bitpos = -1;
  232.     if (PK_dyn_f == 14) {    /* get raster by bits */
  233.         bzero(g->bitmap.bits, (int) g->bitmap.h * bytes_wide);
  234.         for (i = 0; i < (int) g->bitmap.h; i++) {    /* get all rows */
  235.         cp = ADD(g->bitmap.bits, i * bytes_wide);
  236. #ifndef    MSBITFIRST
  237.         row_bit_pos = -1;
  238. #else
  239.         row_bit_pos = BITS_PER_BMUNIT;
  240. #endif
  241.         for (j = 0; j < (int) g->bitmap.w; j++) {    /* get one row */
  242.             if (--PK_bitpos < 0) {
  243.             word = one(fp);
  244.             PK_bitpos = 7;
  245.             }
  246. #ifndef    MSBITFIRST
  247.             if (++row_bit_pos >= BITS_PER_BMUNIT) {
  248.             cp++;
  249.             row_bit_pos = 0;
  250.             }
  251. #else
  252.             if (--row_bit_pos < 0) {
  253.             cp++;
  254.             row_bit_pos = BITS_PER_BMUNIT - 1;
  255.             }
  256. #endif
  257.             if (word & (1 << PK_bitpos)) *cp |= 1 << row_bit_pos;
  258.         }
  259.         }
  260.     }
  261.     else {        /* get packed raster */
  262.         rows_left = g->bitmap.h;
  263.         h_bit = g->bitmap.w;
  264.         PK_repeat_count = 0;
  265.         word_weight = BITS_PER_BMUNIT;
  266.         word = 0;
  267.         while (rows_left > 0) {
  268.         count = PK_packed_num(fp);
  269.         while (count > 0) {
  270.             if (count < word_weight && count < h_bit) {
  271. #ifndef    MSBITFIRST
  272.             if (paint_switch)
  273.                 word |= bit_masks[count] <<
  274.                 (BITS_PER_BMUNIT - word_weight);
  275. #endif
  276.             h_bit -= count;
  277.             word_weight -= count;
  278. #ifdef    MSBITFIRST
  279.             if (paint_switch)
  280.                 word |= bit_masks[count] << word_weight;
  281. #endif
  282.             count = 0;
  283.             }
  284.             else if (count >= h_bit && h_bit <= word_weight) {
  285.             if (paint_switch)
  286.                 word |= bit_masks[h_bit] <<
  287. #ifndef    MSBITFIRST
  288.                 (BITS_PER_BMUNIT - word_weight);
  289. #else
  290.                 (word_weight - h_bit);
  291. #endif
  292.             *cp++ = word;
  293.             /* "output" row(s) */
  294.             for (i = PK_repeat_count * bytes_wide /
  295.                 BYTES_PER_BMUNIT; i > 0; --i) {
  296.                 *cp = *SUB(cp, bytes_wide);
  297.                 ++cp;
  298.             }
  299.             rows_left -= PK_repeat_count + 1;
  300.             PK_repeat_count = 0;
  301.             word = 0;
  302.             word_weight = BITS_PER_BMUNIT;
  303.             count -= h_bit;
  304.             h_bit = g->bitmap.w;
  305.             }
  306.             else {
  307.             if (paint_switch)
  308. #ifndef    MSBITFIRST
  309.                 word |= bit_masks[word_weight] <<
  310.                 (BITS_PER_BMUNIT - word_weight);
  311. #else
  312.                 word |= bit_masks[word_weight];
  313. #endif
  314.             *cp++ = word;
  315.             word = 0;
  316.             count -= word_weight;
  317.             h_bit -= word_weight;
  318.             word_weight = BITS_PER_BMUNIT;
  319.             }
  320.         }
  321.         paint_switch = 1 - paint_switch;
  322.         }
  323.         if (cp != ((BMUNIT *) (g->bitmap.bits + bytes_wide * g->bitmap.h)))
  324.         oops("Wrong number of bits stored:  char. %d, font %s", ch,
  325.             fontp->fontname);
  326.         if (rows_left != 0 || h_bit != g->bitmap.w)
  327.         oops("Bad pk file (%s), too many bits", fontp->fontname);
  328.     }
  329. }
  330.  
  331. void
  332. read_PK_index(fontp, hushcs)
  333.     register struct font    *fontp;
  334.     wide_bool        hushcs;
  335. {
  336.     int    hppp, vppp;
  337.     long    checksum;
  338.  
  339.     fontp->read_char = read_PK_char;
  340.     if (debug & DBG_PK)
  341.         Printf("Reading PK pixel file %s\n", fontp->filename);
  342.  
  343.     Fseek(fontp->file, (long) one(fontp->file), 1);    /* skip comment */
  344.  
  345.     (void) four(fontp->file);        /* skip design size */
  346.     checksum = four(fontp->file);
  347.     if (!hushcs && checksum && fontp->checksum
  348.         && checksum != fontp->checksum)
  349.         Fprintf(stderr,
  350.         "Checksum mismatch (dvi = %lu, pk = %lu) in font file %s\n",
  351.         fontp->checksum, checksum, fontp->filename);
  352.     hppp = sfour(fontp->file);
  353.     vppp = sfour(fontp->file);
  354.     if (hppp != vppp && (debug & DBG_PK))
  355.         Printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
  356.     /*
  357.      * Prepare glyph array.
  358.      */
  359.     fontp->glyph = (struct glyph *) xmalloc(256 * sizeof(struct glyph),
  360.         "glyph array");
  361.     bzero((char *) fontp->glyph, 256 * sizeof(struct glyph));
  362.     /*
  363.      * Read glyph directory (really a whole pass over the file).
  364.      */
  365.     for (;;) {
  366.         int bytes_left, flag_low_bits;
  367.         unsigned int ch;
  368.  
  369.         PK_skip_specials(fontp);
  370.         if (PK_flag_byte == PK_POST) break;
  371.         flag_low_bits = PK_flag_byte & 0x7;
  372.         if (flag_low_bits == 7) {
  373.         bytes_left = four(fontp->file);
  374.         ch = four(fontp->file);
  375.         } else if (flag_low_bits > 3) {
  376.         bytes_left = ((flag_low_bits - 4) << 16) + two(fontp->file);
  377.         ch = one(fontp->file);
  378.         } else {
  379.         bytes_left = (flag_low_bits << 8) + one(fontp->file);
  380.         ch = one(fontp->file);
  381.         }
  382.         fontp->glyph[ch].addr = ftell(fontp->file);
  383.         fontp->glyph[ch].x2 = PK_flag_byte;
  384. #ifdef linux
  385. #ifndef SHORTSEEK
  386. #define SHORTSEEK 1024
  387. #endif
  388.           /* A bug in Linux libc (as of 18oct94) makes a short read faster
  389.              than a short forward seek. Totally non-intuitive.  */
  390.           if (bytes_left > 0 && bytes_left < SHORTSEEK) {
  391.             char *dummy = xmalloc (bytes_left, "shortseek");
  392.             Fread (dummy, 1, bytes_left, fontp->file);
  393.             free (dummy);
  394.           } else
  395.             /* seek backward, or long forward */
  396. #endif /* linux */
  397.         Fseek(fontp->file, (long) bytes_left, 1);
  398.         if (debug & DBG_PK)
  399.         Printf("Scanning pk char %u, at %ld.\n", ch,
  400.             fontp->glyph[ch].addr);
  401.     }
  402. }
  403.