Back to index

texmacs  1.0.7.15
load_pk.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : load_pk.cpp
00004 * DESCRIPTION: load pk files
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 *******************************************************************************
00011 * This program is a modified version of the program 'pk2bm' by Piet Tutelaers.
00012 * It also uses parts of 'dvips' by Tomas Rokicki
00013 ******************************************************************************/
00014 
00015 #include "load_tex.hpp"
00016 #include "timer.hpp"
00017 
00018 typedef short HI;
00019 #define PIXEL 256
00020 
00021 /******************************************************************************
00022 * Initialize the pk_loader
00023 ******************************************************************************/
00024 
00025 pk_loader::pk_loader (url pk_file_name, tex_font_metric tfm2, int dpi2):
00026   file_name (pk_file_name), tfm (tfm2), dpi (dpi2),
00027   inputbyte (0), flagbyte (0), bitweight (0), dynf (0),
00028   repeatcount (0), remainder (0), real_func_flag (true),
00029   bc (tfm->bc), ec (tfm->ec),
00030   char_pos(0), char_flag(0), unpacked(0)
00031 {
00032   (void) load_string (pk_file_name, input_s, true);
00033   input_pos= 0;
00034 }
00035 
00036 /******************************************************************************
00037 * File handling
00038 ******************************************************************************/
00039 
00040 HI
00041 pk_loader::pkbyte () {
00042   if (input_pos == N(input_s)) {
00043     cerr << "\npk file= " << file_name << "\n";
00044     FAILED ("unexpected eof in pk file");
00045   }
00046   return (HI) ((QN) input_s [input_pos++]);
00047 }
00048 
00049 SI
00050 pk_loader::pkduo () {
00051   register SI i;
00052 
00053   i = pkbyte ();
00054   if (i > 127) i -= 256;
00055   i = i * 256 + pkbyte ();
00056   return i;
00057 }
00058 
00059 SI
00060 pk_loader::pktrio () {
00061   register SI i;
00062 
00063   i = pkbyte ();
00064   i = i * 256 + pkbyte ();
00065   i = i * 256 + pkbyte ();
00066   return i;
00067 }
00068 
00069 SI
00070 pk_loader::pkquad () {
00071   register SI i;
00072 
00073   i = pkbyte ();
00074   if (i > 127) i -= 256;
00075   i = i * 256 + pkbyte ();
00076   i = i * 256 + pkbyte ();
00077   i = i * 256 + pkbyte ();
00078   return i;
00079 }
00080 
00081 /******************************************************************************
00082 * Get a nybble, bit, and packed word from the packed data structure.
00083 ******************************************************************************/
00084 
00085 HI
00086 pk_loader::getnyb () {
00087   HN temp;
00088   if (bitweight == 0) {
00089     bitweight = 16; 
00090     inputbyte = pkbyte ();
00091     temp = inputbyte >> 4;
00092   } else {
00093     bitweight = 0;
00094     temp = inputbyte & 15;
00095   }
00096   return temp;
00097 } 
00098 
00099 bool
00100 pk_loader::getbit ()
00101 {
00102   bitweight >>= 1; 
00103   if (bitweight == 0) {
00104     inputbyte = pkbyte ();
00105     bitweight = 128;
00106   } 
00107   return (inputbyte & bitweight);
00108 }
00109 
00110 HN
00111 pk_loader::pkpackednum () {
00112   register HN i, j; 
00113   i = getnyb (); 
00114   if (i == 0) {
00115     do { j = getnyb (); i++; } while (! (j != 0)); 
00116     if (i > 3) return handlehuge (i, j);
00117     while (i > 0) {
00118       j= j*16 + getnyb (); 
00119       i--; 
00120     } 
00121     return (j-15 + (13-dynf)*16 + dynf); 
00122   }
00123   else if (i <= dynf) return i; 
00124   else if (i < 14) return ((i-dynf-1)*16+ getnyb()+ dynf+ 1); 
00125   else {
00126     if (i == 14) repeatcount = pkpackednum (); 
00127     else repeatcount = 1; 
00128     return realfunc ();
00129   } 
00130 } 
00131 
00132 HN
00133 pk_loader::rest () {
00134   HN i;
00135 
00136   if (remainder < 0) {
00137     remainder = - remainder;
00138     return 0;
00139   } else if (remainder > 0) {
00140     if (remainder > 4000) {
00141       remainder = 4000 - remainder;
00142       return (4000);
00143     }
00144     i = remainder;
00145     remainder = 0;
00146     real_func_flag = true;
00147     return i;
00148   }
00149   cerr << "\npk file= " << file_name << "\n";
00150   FAILED ("unexpected situation");
00151   return 0;
00152 }
00153 
00154 HN
00155 pk_loader::handlehuge (HN i , HN k) {
00156   register long j = k;
00157   
00158   while (i) {
00159     j = (j << 4L) + getnyb();
00160     i--;
00161   }
00162   remainder = j - 15 + (13 - dynf) * 16 + dynf;
00163   real_func_flag = false;
00164   return (rest ());
00165 }
00166 
00167 HN
00168 pk_loader::realfunc () {
00169   if (real_func_flag) return pkpackednum ();
00170   else return rest ();
00171 }
00172 
00173 /******************************************************************************
00174 * Writing to a character
00175 ******************************************************************************/
00176 
00177 struct char_bitstream {
00178   glyph& gl;
00179   int x, y;
00180   QN* pos;
00181   int bit;
00182 
00183   char_bitstream (glyph& gl2):
00184     gl (gl2), x(0), y(0), pos (gl->raster), bit (0) {}
00185   void write (int num, int times=1, int repeat=0) {
00186     int i, j;
00187     for (i=0; i<times; i++) {
00188       (*pos) += (num<<bit);
00189       bit= (bit+1)&7;
00190       if (bit==0) pos++;
00191       x++;
00192       if (x==gl->width) {
00193        x=0; y++;
00194        while (repeat>0) {
00195          for (j=0; j<gl->width; j++) {
00196            (*pos) += ((gl->get_1 (j, y-1))<<bit);
00197            bit= (bit+1)&7;
00198            if (bit==0) pos++;
00199          }
00200          y++;
00201          repeat--;
00202        }
00203       }
00204     }
00205   }
00206 };
00207 
00208 /******************************************************************************
00209 * Unpacking a character bitmap
00210 ******************************************************************************/
00211 
00212 void
00213 pk_loader::unpack (glyph& gl) { 
00214   register SI i, j;
00215   register HN wordweight;
00216   HI rowsleft; 
00217   bool turnon;
00218   HI hbit;
00219   HN count; 
00220   char_bitstream bit_out (gl);
00221 
00222   real_func_flag = true;
00223   dynf = flagbyte / 16; 
00224   turnon = flagbyte & 8; 
00225 
00226   if (dynf == 14) {
00227     bitweight = 0 ; 
00228     for (j=0; j<gl->height; j++)
00229       for (i=0; i<gl->width; i++)
00230        bit_out.write (getbit ()? 1: 0);
00231   }
00232 
00233   else {
00234     rowsleft = gl->height; 
00235     hbit = gl->width; 
00236     repeatcount = 0; 
00237     wordweight = 16;
00238     bitweight = 0;
00239     while (rowsleft > 0) {
00240       count = realfunc (); 
00241       bit_out.write (turnon? 1: 0, count, repeatcount);
00242 
00243       while (count != 0) {
00244        if ((count < wordweight) && (count < hbit)) {
00245          hbit -= count;
00246          wordweight -= count; 
00247          count = 0; 
00248        } 
00249        else if ((count >= hbit) && (hbit <= wordweight)) {
00250          rowsleft -= repeatcount + 1; 
00251          repeatcount = 0; 
00252          count -= hbit; 
00253          hbit = gl->width; 
00254          wordweight = 16; 
00255        } 
00256        else {
00257          count -= wordweight; 
00258          hbit -= wordweight; 
00259          wordweight = 16; 
00260        } 
00261       }
00262       turnon = ! turnon; 
00263     }
00264     if ((rowsleft != 0) || (hbit != gl->width)) {
00265       cerr << "\npk file= " << file_name << "\n";
00266       FAILED ("more bits than required while unpacking");
00267     }
00268   }
00269 }
00270 
00271 /******************************************************************************
00272 * Reading the font
00273 ******************************************************************************/
00274 
00275 glyph*
00276 pk_loader::load_pk () {
00277   register HI i;
00278   register SI k;
00279   register SI length = 0, startpos = 0;
00280 
00281   register HI charcode= 0;
00282   register SI cwidth;
00283   register SI cheight;
00284   register SI xoff;
00285   register SI yoff;
00286   
00287   bench_start ("decode pk");
00288   glyph* fng= tm_new_array<glyph> (ec+1-bc);
00289   char_pos = tm_new_array<int> (ec+1-bc);
00290   unpacked = tm_new_array<bool> (ec+1-bc);
00291   char_flag = tm_new_array<HN> (ec+1-bc);
00292   for(i=0;i<ec+1-bc;i++) {
00293     char_pos[i] = 0;
00294     char_flag[i] = 0;
00295     unpacked[i] = true; // set to false for still unpacked glyphs
00296   }
00297 
00298   // Preamble
00299   if (pkbyte ()!=247) {
00300     cerr << "\npk file= " << file_name << "\n";
00301     FAILED ("bad pk file");
00302   }
00303   if (pkbyte ()!=89) {
00304     cerr << "\npk file= " << file_name << "\n";
00305     FAILED ("bad version of pk file");
00306   }
00307   for(i=pkbyte (); i>0; i--) (void) pkbyte (); /* creator of pkfile */
00308   (void) pkquad (); /* design size */
00309   k = pkquad ();    /* checksum    */
00310   k = pkquad ();    /* hppp        */
00311   k = pkquad ();    /* vppp   */
00312 
00313   // The character definition
00314   while ((flagbyte=pkbyte ())!=245) {
00315     if (flagbyte < 240) {
00316       switch (flagbyte & 7) {
00317       case 0:
00318       case 1:
00319       case 2:
00320       case 3:
00321        length = (flagbyte & 7) * 256 + pkbyte ();
00322        charcode = pkbyte ();
00323        startpos = input_pos;
00324        i = pktrio ();  /* TFM width */
00325        i = pkbyte ();       /* pixel width */
00326        break;
00327       case 4:
00328        length = pkbyte () * 256;
00329        length = length + pkbyte ();
00330        charcode = pkbyte ();
00331        startpos = input_pos;
00332        i = pktrio ();                  /* TFM width */
00333        i = pkbyte ();
00334        i = i * 256 + pkbyte ();        /* pixelwidth */
00335        break;
00336       case 5:
00337        cerr << "\npk file= " << file_name << "\n";
00338        cerr << "last charcode= " << charcode << "\n";
00339        FAILED ("lost sync in pk file (character too big / status = 5)");
00340        break;
00341       case 6:
00342        cerr << "\npk file= " << file_name << "\n";
00343        cerr << "last charcode= " << charcode << "\n";
00344        FAILED ("lost sync in pk file (character too big / status = 6)");
00345        break;
00346       case 7:
00347        length = pkquad ();
00348        charcode = pkquad ();
00349        startpos = input_pos;
00350        (void) pkquad ();           /* TFMwidth */
00351                           /* pixelwidth = (pkquad () + 32768) >> 16; */
00352        (void) pkquad ();           /* pixelwidth */
00353        k = pkquad ();
00354       }
00355       /*
00356       cout << "---------------------------------------------------------------------------\n";
00357       cout << "Reading character " << charcode << "\n";
00358       cout << "---------------------------------------------------------------------------\n";
00359       */
00360       if (flagbyte & 4) { // the long and extended formats are bugged !
00361        if ((flagbyte & 7) == 7) { // extended format
00362          cwidth = pkquad ();;
00363          cheight = pkquad ();
00364          xoff = pkquad ();
00365          yoff = pkquad ();
00366        } else { // long format
00367          cwidth = pkduo ();
00368          cheight = pkduo ();
00369          xoff = pkduo ();
00370          yoff = pkduo ();
00371        }
00372       } else { // short format
00373        cwidth = pkbyte ();
00374        cheight = pkbyte ();
00375        xoff = pkbyte ();
00376        yoff = pkbyte ();
00377        if (xoff > 127) xoff -= 256;
00378        if (yoff > 127) yoff -= 256;
00379       }
00380       if ((cwidth > 0) && (cheight > 0) &&
00381          (((QN) charcode) >= bc) && (((QN) charcode) <= ec)) {
00382        // cout << "---> unpacking " << charcode
00383        //     << " at " << input_pos 
00384        //     << " (start " << startpos << ", length " << length << ")!\n";
00385        glyph gl (cwidth, cheight, xoff, yoff);
00386 
00387        /* needed for lazy unpacking */
00388        char_pos[((QN) charcode)- bc] = input_pos;
00389        char_flag[((QN) charcode)- bc] = flagbyte;
00390        unpacked[((QN) charcode)- bc] = false;
00391        /* skip packed bitmap */
00392        input_pos = startpos + length;
00393 
00394        fng [((QN) charcode)- bc]= gl;
00395        // cout << "---> " << charcode << " done !\n";
00396        // cout << fng [((QN) charcode)- bc] << "\n";
00397       }
00398     }
00399 
00400     else {
00401       k = 0;
00402       switch (flagbyte) {
00403       case 243: k = pkbyte (); if (k > 127) k -= 256;
00404       case 242: k = k * 256 + pkbyte ();
00405       case 241: k = k * 256 + pkbyte ();
00406       case 240: k = k * 256 + pkbyte ();
00407        while (k-- > 0) i = pkbyte ();
00408        break;
00409       case 244: k = pkquad (); break;
00410       case 246: break;
00411       default :
00412        cerr << "\npk file= " << file_name << "\n";
00413        cerr << "last charcode= " << charcode << "\n";
00414        cerr << "flagbyte= " << flagbyte << "\n";
00415        FAILED ("lost sync in pk file");
00416       }
00417     }
00418   }
00419 
00420   register int c;
00421   for (c=0; c<=ec-bc; c++)
00422     if (!is_nil (fng[c])) {
00423       SI design_size = tfm->design_size () >> 12;
00424       SI display_size= (((design_size*dpi)/72)*PIXEL) >> 8;
00425       double unit    = ((double) display_size) / ((double) (1<<20));
00426       SI lwidth= (SI) (((double) (tfm->w(c+bc))) * unit);
00427       fng[c]->lwidth= ((lwidth+(PIXEL>>1)) / PIXEL);
00428     }
00429 
00430   bench_cumul ("decode pk");
00431   return fng;
00432 }