Back to index

tetex-bin  3.0
pkin.c
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
00003 
00004 This file is part of pdfTeX.
00005 
00006 pdfTeX is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 pdfTeX is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with pdfTeX; if not, write to the Free Software
00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/pkin.c#4 $
00021 */
00022 
00023 /*
00024  * NAME
00025  * pkin.c - implementation of readchar()
00026  * DESCRIPTION
00027  * This implementation of readchar() uses parts of the program dvips
00028  * written by Tomas Rokicki--the inventor of the pkformat--(loadfont.c,
00029  * download.c and unpack.c). Dvips in turn is derived from pktype. 
00030  * Pktype(TeX) is described in debt in ``The PKtype processor'', 
00031  * which is available as pktype.weave as part of the METAFONTware.
00032  * What was needed to implement readchar() is rearranged in pkfile.c to 
00033  * get more modularity in the style of MODULA2.
00034  * BUGFIXES
00035  *      May 1997: Eric Delaunay <delaunay@lix.polytechnique.fr> reports a
00036  *      problem with huge fonts (greater than 1008 DPI). The code for
00037  *      handling PK characters in `extended format' was wrongly derived
00038  *      from dvips. Made some minor improvements regarding error handling.
00039  * REDESIGN
00040  * Piet Tutelaers
00041  * rcpt@urc.tue.nl
00042  *
00043  *  Modified for use with pdftex by Han The Thanh <thanh@fi.muni.cz>.
00044  */
00045 
00046 #include "ptexlib.h"
00047 
00048 /*
00049  *   Now we have some routines to get stuff from the pk file.  pkbyte returns
00050  *   the next byte from the pk file.
00051  */
00052 
00053 
00054 /*
00055 static FILE *pkfile ;
00056 */
00057 
00058 extern FILE *t3_file;
00059 #define pkfile t3_file
00060 
00061 static shalfword pkbyte(void)
00062 {
00063    register shalfword i ;
00064 
00065    if ((i=xgetc(pkfile))==EOF)
00066       pdftex_fail("unexpected eof in pk file") ;
00067    return(i) ;
00068 }
00069 
00070 static integer pkduo(void)
00071 {
00072     register integer i ;
00073 
00074     i = pkbyte() ;
00075     if (i > 127)
00076         i -= 256 ;
00077     i = i * 256 + pkbyte() ;
00078     return(i) ;
00079 }
00080 
00081 static integer pktrio(void)
00082 {
00083    register integer i ;
00084 
00085    i = pkbyte() ;
00086    if (i > 127)
00087       i -= 256 ;
00088    i = i * 256 + pkbyte() ;
00089    i = i * 256 + pkbyte() ;
00090    return(i) ;
00091 }
00092 
00093 static integer pkquad(void)
00094 {
00095    register integer i ;
00096 
00097    i = pkbyte() ;
00098    if (i > 127)
00099       i -= 256 ;
00100    i = i * 256 + pkbyte() ;
00101    i = i * 256 + pkbyte() ;
00102    i = i * 256 + pkbyte() ;
00103    return(i) ;
00104 }
00105 
00106 /*
00107  *   The next part is devoted to unpacking the character data.
00108  */
00109 
00110 /*
00111  *   We need procedures to get a nybble, bit, and packed word from the
00112  *   packed data structure.
00113  */
00114 
00115 static halfword inputbyte, flagbyte ; 
00116 static halfword bitweight ; 
00117 static halfword dynf ;
00118 static halfword repeatcount ;
00119 
00120 static shalfword getnyb(void)
00121 {   halfword temp;
00122     if ( bitweight == 0 ) 
00123     { bitweight = 16 ; 
00124       inputbyte = pkbyte();
00125       temp = inputbyte >> 4 ;
00126     } else {
00127       bitweight = 0 ;
00128       temp = inputbyte & 15 ;
00129     }
00130     return(temp);
00131 } 
00132 
00133 static boolean getbit(void)
00134 {
00135     bitweight >>= 1 ; 
00136     if ( bitweight == 0 ) 
00137     { inputbyte = pkbyte();
00138       bitweight = 128 ;
00139     } 
00140     return(inputbyte & bitweight) ;
00141 }
00142 
00143 static halfword (*realfunc)(void) ;
00144 long pk_remainder ;
00145 static halfword handlehuge(halfword i, halfword  k);
00146 
00147 static halfword pkpackednum(void) {
00148 register halfword i, j ; 
00149     i = getnyb () ; 
00150     if ( i == 0 ) 
00151     { do { j = getnyb () ; 
00152         i++ ; 
00153         } while ( ! ( j != 0 ) ) ; 
00154       if ( i > 3 ) {
00155 /*
00156  *   Damn, we got a huge count!  We *fake* it by giving an artificially
00157  *   large repeat count.
00158  */
00159          return(handlehuge(i, j)) ;
00160       } else {
00161          while ( i > 0 ) 
00162            { j = j * 16 + getnyb () ; 
00163              i-- ; 
00164              } 
00165            return ( j - 15 + ( 13 - dynf ) * 16 + dynf ) ; 
00166          } 
00167       }
00168     else if ( i <= dynf ) return ( i ) ; 
00169     else if ( i < 14 ) return ( ( i - dynf - 1 ) * 16 + getnyb () + dynf + 1 
00170     ) ; 
00171     else 
00172     { if ( i == 14 ) repeatcount = pkpackednum () ; 
00173       else repeatcount = 1 ; 
00174 #ifdef DEBUG
00175       printf("[%d]", repeatcount);
00176 #endif
00177       return ( (*realfunc)() ) ;
00178       } 
00179     } 
00180 
00181 static halfword rest(void)
00182 {
00183    halfword i ;
00184 
00185    if (pk_remainder < 0) {
00186       pk_remainder = - pk_remainder ;
00187       return ( 0 ) ;
00188    } else if (pk_remainder > 0) {
00189       if (pk_remainder > 4000) {
00190          pk_remainder = 4000 - pk_remainder ;
00191          return ( 4000 ) ;
00192       } else {
00193          i = pk_remainder ;
00194          pk_remainder = 0 ;
00195          realfunc = pkpackednum ;
00196          return ( i ) ;
00197       }
00198    } else {
00199       pdftex_fail("shouldn't happen") ;
00200       return 0; /*NOTREACHED*/
00201    }
00202 }
00203 
00204 static halfword handlehuge(halfword i, halfword  k)
00205 {
00206    register long j = k ;
00207 
00208    while (i) {
00209       j = (j << 4L) + getnyb() ;
00210       i-- ;
00211    }
00212    pk_remainder = j - 15 + ( 13 - dynf ) * 16 + dynf ;
00213    realfunc = rest ;
00214    return ( rest() ) ;
00215 }
00216 
00217 /*
00218  *   And now we have our unpacking routine.
00219  */
00220 
00221 static halfword gpower[17] = { 0, 1, 3, 7, 15, 31, 63, 127,
00222      255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535 } ; 
00223 
00224 static void unpack(chardesc *cd)
00225 { 
00226   register integer i, j ; 
00227   register halfword word, wordweight ;
00228   halfword *raster;
00229   shalfword rowsleft ; 
00230   boolean turnon ; 
00231   shalfword hbit ; 
00232   halfword count ; 
00233   shalfword  wordwidth ;
00234 
00235       wordwidth = (cd->cwidth + 15) / 16 ;
00236       i = 2 * cd->cheight * (long)wordwidth ;
00237       if (i <= 0)
00238          i = 2 ;
00239       if (i > cd->rastersize) {
00240         xfree(cd->raster);
00241         cd->rastersize = i;
00242         cd->raster = xtalloc(cd->rastersize, halfword);
00243       }
00244       raster = cd->raster;
00245       realfunc = pkpackednum ;
00246       dynf = flagbyte / 16 ; 
00247       turnon = flagbyte & 8 ; 
00248       if ( dynf == 14 ) 
00249       { bitweight = 0 ; 
00250         for ( i = 1 ; i <= cd->cheight ; i ++ ) 
00251           { word = 0 ; 
00252             wordweight = 32768 ; 
00253             for ( j = 1 ; j <= cd->cwidth ; j ++ ) 
00254               { if ( getbit () ) word += wordweight ; 
00255                 wordweight >>= 1 ;
00256                 if ( wordweight == 0 ) 
00257                 { *raster++ = word ; 
00258                   word = 0 ;
00259                   wordweight = 32768 ; 
00260                   } 
00261                 } 
00262               if ( wordweight != 32768 ) 
00263                  *raster++ = word ; 
00264             } 
00265       } else {
00266         rowsleft = cd->cheight ; 
00267         hbit = cd->cwidth ; 
00268         repeatcount = 0 ; 
00269         wordweight = 16 ; 
00270         word = 0 ; 
00271         bitweight = 0 ;
00272         while ( rowsleft > 0 ) 
00273           { count = (*realfunc)() ; 
00274 #ifdef DEBUG
00275             if (turnon) printf("(%d) ",count);
00276             else printf("%d ",count);
00277 #endif
00278             while ( count != 0 ) 
00279               { if ( ( count < wordweight ) && ( count < hbit ) ) 
00280                 { if ( turnon ) word += gpower [ wordweight ] - gpower 
00281                   [ wordweight - count ] ; 
00282                   hbit -= count ; 
00283                   wordweight -= count ; 
00284                   count = 0 ; 
00285                   } 
00286                 else if ( ( count >= hbit ) && ( hbit <= wordweight ) ) 
00287                 { if ( turnon )
00288                      word += gpower [ wordweight ] - gpower 
00289                   [ wordweight - hbit ] ; 
00290                   *raster++ = word ; 
00291                   for ( i = 1 ; i <= repeatcount ; i ++ ) {
00292                     for ( j = 1 ; j <= wordwidth ; j ++ ) {
00293                       *raster = *(raster - wordwidth) ;
00294                       raster++ ;
00295                     }
00296                   }
00297                   rowsleft -= repeatcount + 1 ; 
00298                   repeatcount = 0 ; 
00299                   word = 0 ; 
00300                   wordweight = 16 ; 
00301                   count -= hbit ; 
00302                   hbit = cd->cwidth ; 
00303                   } 
00304                 else 
00305                 { if ( turnon ) word += gpower [ wordweight ] ; 
00306                   *raster++ = word ;
00307                   word = 0 ; 
00308                   count -= wordweight ; 
00309                   hbit -= wordweight ; 
00310                   wordweight = 16 ; 
00311                   } 
00312                 } 
00313               turnon = ! turnon ; 
00314    }
00315           if ( ( rowsleft != 0 ) || ( (integer)hbit != cd->cwidth ) ) 
00316              pdftex_fail("error while unpacking; more bits than required"); 
00317         } 
00318 }
00319 
00320 /*
00321  *   readchar(): the main routine
00322  *   Reads the character definition of character `c' into `cd' if available,
00323  *   return FALSE (0) otherwise.
00324  */
00325 
00326 /*
00327  *   readchar(): the main routine
00328  *   check pk preamble if necessary,
00329  *   read the next character definition into `cd',
00330  *   return EOF if no character definition is available
00331  */
00332 
00333 int readchar(boolean check_preamble, chardesc *cd)
00334 {
00335    register shalfword i ;
00336    register integer k ;
00337    register integer length=0 ;
00338 
00339 /*
00340  *   Check the preamble of the pkfile
00341  */
00342    if (check_preamble) {
00343        if (pkbyte()!=247)
00344           pdftex_fail("bad pk file, expected pre") ;
00345        if (pkbyte()!=89)
00346           pdftex_fail("bad version of pk file") ;
00347        for(i=pkbyte(); i>0; i--) /* creator of pkfile */
00348           (void)pkbyte() ;   
00349        (void)pkquad(); /* design size */
00350        k = pkquad() ;  /* checksum    */
00351        k = pkquad() ;  /* hppp        */
00352        k = pkquad() ;  /* vppp   */
00353    }
00354 /*
00355  *   Now we skip to the desired character definition
00356  */
00357    while ((flagbyte=pkbyte())!=245) {
00358       if (flagbyte < 240) {
00359          switch (flagbyte & 7) {
00360 case 0: case 1: case 2: case 3:
00361             length = (flagbyte & 7) * 256 + pkbyte() - 3;
00362             cd->charcode = pkbyte() ;
00363             (void) pktrio() ;  /* TFMwidth */
00364             cd->xescape = pkbyte() ;      /* pixel width */
00365             cd->cwidth = pkbyte() ;
00366             cd->cheight = pkbyte() ;
00367             cd->xoff = pkbyte() ;
00368             cd->yoff = pkbyte() ;
00369             if (cd->xoff > 127)
00370                cd->xoff -= 256 ;
00371             if (cd->yoff > 127)
00372                cd->yoff -= 256 ;
00373             break ;
00374 case 4: case 5: case 6:
00375             length = (flagbyte & 3) * 65536L + pkbyte() * 256L ;
00376             length = length + pkbyte() - 4L ;
00377             cd->charcode = pkbyte() ;
00378             (void) pktrio() ;           /* TFMwidth */
00379             cd->xescape  = pkduo() ;      /* pixelwidth */
00380             cd->cwidth = pkduo() ;
00381             cd->cheight = pkduo() ;
00382             cd->xoff = pkduo() ;
00383             cd->yoff = pkduo() ;
00384             break ;
00385 case 7:
00386             length = pkquad() - 9L;
00387             cd->charcode = pkquad();
00388             (void) pkquad() ;  /* TFMwidth */
00389             cd->xescape =  pkquad();      /* pixelwidth */
00390             k = pkquad() ;
00391             cd->cwidth = pkquad();
00392             cd->cheight = pkquad();
00393             cd->xoff = pkquad();
00394             cd->yoff = pkquad();
00395          }
00396          if (length <= 0)
00397             pdftex_fail("packet length (%i) too small", (int)length) ;
00398          unpack(cd);
00399          return 1;
00400       } else {
00401          k = 0 ;
00402          switch (flagbyte) {
00403 case 243:
00404             k = pkbyte() ;
00405             if (k > 127)
00406                k -= 256 ;
00407 case 242:
00408             k = k * 256 + pkbyte() ;
00409 case 241:
00410             k = k * 256 + pkbyte() ;
00411 case 240:
00412             k = k * 256 + pkbyte() ;
00413             while (k-- > 0)
00414                i = pkbyte() ;
00415             break ;
00416 case 244:
00417             k = pkquad() ;
00418             break ;
00419 case 246:
00420             break ;
00421 default:
00422             pdftex_fail("unexpected command (%i)", (int)flagbyte) ;
00423          }
00424       }
00425    }
00426    return 0; /* character not found */
00427 }