Back to index

tetex-bin  3.0
gf.c
Go to the documentation of this file.
00001 /*========================================================================*\
00002 
00003 Copyright (c) 1990-2004  Paul Vojta
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to
00007 deal in the Software without restriction, including without limitation the
00008 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00009 sell copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018 PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
00019 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00020 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00021 OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 \*========================================================================*/
00024 
00025 /*
00026  *     GF font reading routines.
00027  *     Public routines are read_GF_index and read_GF_char.
00028  */
00029 
00030 #include "xdvi-config.h"
00031 #include "xdvi.h"
00032 #include "dvi-init.h"
00033 #include "util.h"
00034 
00035 #define       PAINT_0              0
00036 #define       PAINT1        64
00037 #define       PAINT2        65
00038 #define       PAINT3        66
00039 #define       BOC           67
00040 #define       BOC1          68
00041 #define       EOC           69
00042 #define       SKIP0         70
00043 #define       SKIP1         71
00044 #define       SKIP2         72
00045 #define       SKIP3         73
00046 #define       NEW_ROW_0     74
00047 #define       NEW_ROW_MAX   238
00048 #define       XXX1          239
00049 #define       XXX2          240
00050 #define       XXX3          241
00051 #define       XXX4          242
00052 #define       YYY           243
00053 #define       NO_OP         244
00054 #define       CHAR_LOC      245
00055 #define       CHAR_LOC0     246
00056 #define       PRE           247
00057 #define       POST          248
00058 #define       POST_POST     249
00059 
00060 #define       GF_ID_BYTE    131
00061 #define       TRAILER              223    /* Trailing bytes at end of file */
00062 
00063 static FILE *GF_file;
00064 
00065 static void
00066 expect(ubyte ch)
00067 {
00068     ubyte ch1 = get_byte(GF_file);
00069 
00070     if (ch1 != ch)
00071        XDVI_FATAL((stderr, "Bad GF file:  %d expected, %d received.", ch, ch1));
00072 }
00073 
00074 static void
00075 too_many_bits(ubyte ch)
00076 {
00077     XDVI_FATAL((stderr, "Too many bits found when loading character %d", ch));
00078 }
00079 
00080 /*
00081  *     Public routines
00082  */
00083 
00084 
00085 static void
00086 read_GF_char(struct font *fontp,
00087             wide_ubyte ch)
00088 {
00089     struct glyph *g;
00090     ubyte cmnd;
00091     int min_m, max_m, min_n, max_n;
00092     bmUnitT *cp, *basep, *maxp;
00093     int bytes_wide;
00094     Boolean paint_switch;
00095 #define       White  False
00096 #define       Black  True
00097     Boolean new_row;
00098     int count;
00099     int word_weight;
00100 
00101     g = &fontp->glyph[ch];
00102     GF_file = fontp->file;
00103 
00104     if (globals.debug & DBG_PK)
00105        printf("Loading gf char %d", ch);
00106 
00107     for (;;) {
00108        switch (cmnd = get_byte(GF_file)) {
00109        case XXX1:
00110        case XXX2:
00111        case XXX3:
00112        case XXX4:
00113            fseek(GF_file, (long)get_bytes(GF_file, (int)(cmnd - XXX1 + 1)), SEEK_CUR);
00114            continue;
00115        case YYY:
00116            (void)get_bytes(GF_file, 4);
00117            continue;
00118        case BOC:
00119            (void)get_bytes(GF_file, 4);   /* skip character code */
00120            (void)get_bytes(GF_file, 4);   /* skip pointer to prev char */
00121            min_m = get_lbytes(GF_file, 4);
00122            max_m = get_lbytes(GF_file, 4);
00123            g->x = -min_m;
00124            min_n = get_lbytes(GF_file, 4);
00125            g->y = max_n = get_lbytes(GF_file, 4);
00126            g->bitmap.w = max_m - min_m + 1;
00127            g->bitmap.h = max_n - min_n + 1;
00128            break;
00129        case BOC1:
00130            (void)get_byte(GF_file);       /* skip character code */
00131            g->bitmap.w = get_byte(GF_file);      /* max_m - min_m */
00132            g->x = g->bitmap.w - get_byte(GF_file);      /* ditto - max_m */
00133            ++g->bitmap.w;
00134            g->bitmap.h = get_byte(GF_file) + 1;
00135            g->y = get_byte(GF_file);
00136            break;
00137        default:
00138            XDVI_FATAL((stderr, "Bad BOC code:  %d", cmnd));
00139        }
00140        break;
00141     }
00142     paint_switch = White;
00143 
00144     if (globals.debug & DBG_PK)
00145        printf(", size=%dx%d, dvi_adv=%ld\n", g->bitmap.w, g->bitmap.h,
00146               g->dvi_adv);
00147 
00148     alloc_bitmap(&g->bitmap);
00149     cp = basep = (bmUnitT *) g->bitmap.bits;
00150     /*
00151      * Read character data into *basep
00152      */
00153     bytes_wide = ROUNDUP((int)g->bitmap.w, BMBITS) * BMBYTES;
00154     maxp = ADD(basep, g->bitmap.h * bytes_wide);
00155     memset(g->bitmap.bits, 0, g->bitmap.h * bytes_wide);
00156     new_row = False;
00157     word_weight = BMBITS;
00158     for (;;) {
00159        count = -1;
00160        cmnd = get_byte(GF_file);
00161        if (cmnd < 64)
00162            count = cmnd;
00163        else if (cmnd >= NEW_ROW_0 && cmnd <= NEW_ROW_MAX) {
00164            count = cmnd - NEW_ROW_0;
00165            paint_switch = White;   /* it'll be complemented later */
00166            new_row = True;
00167        }
00168        else
00169            switch (cmnd) {
00170            case PAINT1:
00171            case PAINT2:
00172            case PAINT3:
00173               count = get_bytes(GF_file, (int)(cmnd - PAINT1 + 1));
00174               break;
00175            case EOC:
00176               if (cp >= ADD(basep, bytes_wide))
00177                   too_many_bits(ch);
00178               return;
00179            case SKIP1:
00180            case SKIP2:
00181            case SKIP3:
00182               basep += get_bytes(GF_file, (int)(cmnd - SKIP0)) * bytes_wide / sizeof(bmUnitT);
00183 /*            *((char **)&basep) += get_bytes(GF_file, WIDENINT cmnd - SKIP0) * bytes_wide; */
00184            case SKIP0:
00185               new_row = True;
00186               paint_switch = White;
00187               break;
00188            case XXX1:
00189            case XXX2:
00190            case XXX3:
00191            case XXX4:
00192               fseek(GF_file, (long)get_bytes(GF_file, (int)(cmnd - XXX1 + 1)), SEEK_CUR);
00193               break;
00194            case YYY:
00195               (void)get_bytes(GF_file, 4);
00196               break;
00197            case NO_OP:
00198               break;
00199            default:
00200               XDVI_FATAL((stderr, "Bad command in GF file:  %d", cmnd));
00201            }  /* end switch */
00202        if (new_row) {
00203            basep += bytes_wide / sizeof(bmUnitT);
00204 /*         *((char **)&basep) += bytes_wide; */
00205            if (basep >= maxp || cp >= basep)
00206               too_many_bits(ch);
00207            cp = basep;
00208            word_weight = BMBITS;
00209            new_row = False;
00210        }
00211        if (count >= 0) {
00212            while (count)
00213               if (count <= word_weight) {
00214 #ifndef       WORDS_BIGENDIAN
00215                   if (paint_switch)
00216                      *cp |= bit_masks[count] << (BMBITS - word_weight);
00217 #endif
00218                   word_weight -= count;
00219 #ifdef WORDS_BIGENDIAN
00220                   if (paint_switch)
00221                      *cp |= bit_masks[count] << word_weight;
00222 #endif
00223                   break;
00224               }
00225               else {
00226                   if (paint_switch)
00227 #ifndef       WORDS_BIGENDIAN
00228                      *cp |= bit_masks[word_weight] << (BMBITS - word_weight);
00229 #else
00230                   *cp |= bit_masks[word_weight];
00231 #endif
00232                   cp++;
00233                   count -= word_weight;
00234                   word_weight = BMBITS;
00235               }
00236            paint_switch = 1 - paint_switch;
00237        }
00238     }  /* end for */
00239 }
00240 
00241 
00242 void
00243 read_GF_index(struct font *fontp, wide_bool hushcs)
00244 {
00245     int hppp, vppp;
00246     ubyte ch, cmnd;
00247     struct glyph *g;
00248     long checksum;
00249 
00250     fontp->read_char = read_GF_char;
00251     GF_file = fontp->file;
00252     if (globals.debug & DBG_PK)
00253        printf("Reading GF pixel file %s\n", fontp->filename);
00254     /*
00255      * Find postamble.
00256      */
00257     fseek(GF_file, (long)-4, SEEK_END);
00258     while (get_bytes(GF_file, 4) != ((unsigned long)TRAILER << 24 | TRAILER << 16
00259                           | TRAILER << 8 | TRAILER))
00260        fseek(GF_file, (long)-5, SEEK_CUR);
00261     fseek(GF_file, (long)-5, SEEK_CUR);
00262     for (;;) {
00263        ch = get_byte(GF_file);
00264        if (ch != TRAILER)
00265            break;
00266        fseek(GF_file, (long)-2, SEEK_CUR);
00267     }
00268     if (ch != GF_ID_BYTE)
00269        XDVI_FATAL((stderr, "Bad end of font file %s", fontp->fontname));
00270     fseek(GF_file, (long)-6, SEEK_CUR);
00271     expect(POST_POST);
00272     fseek(GF_file, get_lbytes(GF_file, 4), SEEK_SET);   /* move to postamble */
00273     /*
00274      * Read postamble.
00275      */
00276     expect(POST);
00277     (void)get_bytes(GF_file, 4);   /* pointer to last eoc + 1 */
00278     (void)get_bytes(GF_file, 4);   /* skip design size */
00279     checksum = get_bytes(GF_file, 4);
00280     if (checksum != fontp->checksum && checksum != 0 && fontp->checksum != 0
00281        && !hushcs)
00282        XDVI_WARNING((stderr, "Checksum mismatch (dvi = %lu, gf = %lu) in font file %s",
00283                     fontp->checksum, checksum, fontp->filename));
00284     hppp = get_lbytes(GF_file, 4);
00285     vppp = get_lbytes(GF_file, 4);
00286     if (hppp != vppp && (globals.debug & DBG_PK))
00287        printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
00288     (void)get_bytes(GF_file, 4);   /* skip min_m */
00289     (void)get_bytes(GF_file, 4);   /* skip max_m */
00290     (void)get_bytes(GF_file, 4);   /* skip min_n */
00291     (void)get_bytes(GF_file, 4);   /* skip max_n */
00292     /*
00293      * Prepare glyph array.
00294      */
00295     fontp->glyph = xmalloc(256 * sizeof(struct glyph));
00296     memset((char *)fontp->glyph, 0, 256 * sizeof(struct glyph));
00297     /*
00298      * Read glyph directory.
00299      */
00300     while ((cmnd = get_byte(GF_file)) != POST_POST) {
00301        int addr;
00302 
00303        ch = get_byte(GF_file);     /* character code */
00304        g = &fontp->glyph[ch];
00305        switch (cmnd) {
00306        case CHAR_LOC:
00307            /* g->pxl_adv = get_lbytes(GF_file, 4); */
00308            (void)get_bytes(GF_file, 4);
00309            (void)get_bytes(GF_file, 4);   /* skip dy */
00310            break;
00311        case CHAR_LOC0:
00312            /* g->pxl_adv = get_byte(GF_file) << 16; */
00313            (void)get_byte(GF_file);
00314            break;
00315        default:
00316            XDVI_FATAL((stderr, "Non-char_loc command found in GF preamble:  %d", cmnd));
00317        }
00318        g->dvi_adv = fontp->dimconv * get_lbytes(GF_file, 4);
00319        addr = get_bytes(GF_file, 4);
00320        if (addr != -1)
00321            g->addr = addr;
00322        if (globals.debug & DBG_PK)
00323            printf("Read GF glyph for character %d; dy = %ld, addr = %x\n",
00324                  ch, g->dvi_adv, addr);
00325     }
00326 }