Back to index

tetex-bin  3.0
loadfont.c
Go to the documentation of this file.
00001 /*
00002  *   Here's the code to load a PK file into memory.
00003  *   Individual bitmaps won't be unpacked until they prove to be needed.
00004  */
00005 #include "dvips.h" /* The copyright notice in that file is included too! */
00006 #ifdef OS2
00007 #include <stdlib.h>
00008 #endif
00009 #ifdef KPATHSEA
00010 #include <kpathsea/c-pathmx.h>
00011 #include <kpathsea/tex-glyph.h>
00012 #include <kpathsea/tex-make.h>
00013 #include <kpathsea/lib.h>
00014 #ifndef MAXPATHLEN
00015 #define MAXPATHLEN (256)
00016 #endif
00017 #else
00018 #if defined(SYSV) || defined(VMS) || (defined(MSDOS) && !defined(__DJGPP__)) || defined(OS2) || defined(ATARIST)
00019 #define MAXPATHLEN (256)
00020 #else
00021 #include <sys/param.h>          /* for MAXPATHLEN */
00022 #endif
00023 #endif
00024 /*
00025  *   These are the external routines we use.
00026  */
00027 #include "protos.h"
00028 /*
00029  *   These are the external variables we use.
00030  */
00031 #ifdef DEBUG
00032 extern integer debug_flag;
00033 #endif  /* DEBUG */
00034 extern long bytesleft ;
00035 extern quarterword *raster ;
00036 extern real conv ;
00037 extern int actualdpi, vactualdpi ;
00038 extern real alpha ;
00039 #ifndef KPATHSEA
00040 extern char *pkpath ;
00041 #endif
00042 char errbuf[200] ;
00043 int lastresortsizes[40] ;
00044 extern integer fsizetol ;
00045 extern Boolean nosmallchars ;
00046 extern Boolean compressed ;
00047 extern Boolean dopprescan ;
00048 #ifdef FONTLIB
00049 extern Boolean flib ;
00050 #endif
00051 /*
00052  *   Now we have some routines to get stuff from the PK file.
00053  *   Subroutine pkbyte returns the next byte.
00054  */
00055 FILE *pkfile ;
00056 char name[MAXPATHLEN] ;
00057 void
00058 badpk P1C(char *, s)
00059 {
00060    (void)sprintf(errbuf,"! Bad PK file %s: %s",name,s) ;
00061    error(errbuf);
00062 }
00063 
00064 shalfword
00065 pkbyte P1H(void)
00066 {
00067    register shalfword i ;
00068 
00069    if ((i=getc(pkfile))==EOF)
00070       badpk("unexpected eof") ;
00071    return(i) ;
00072 }
00073 
00074 integer
00075 pkquad P1H(void)
00076 {
00077    register integer i ;
00078 
00079    i = pkbyte() ;
00080    if (i > 127)
00081       i -= 256 ;
00082    i = i * 256 + pkbyte() ;
00083    i = i * 256 + pkbyte() ;
00084    i = i * 256 + pkbyte() ;
00085    return(i) ;
00086 }
00087 
00088 integer
00089 pktrio P1H(void)
00090 {
00091    register integer i ;
00092 
00093    i = pkbyte() ;
00094    i = i * 256 + pkbyte() ;
00095    i = i * 256 + pkbyte() ;
00096    return(i) ;
00097 }
00098 
00099 
00100 /*
00101  *   pkopen opens the pk file.  This is system dependent.  We work really
00102  *   hard to open some sort of PK file.
00103  */
00104 #ifdef VMCMS /* IBM: VM/CMS - we let DVIPS EXEC handle this after
00105                              the DVIPS MODULE has finished to avoid
00106                              complications with system calls. */
00107 int dontmakefont = 0 ;
00108 #else
00109 #ifdef MVSXA /* IBM: MVS/XA - we let system administrator handle this on
00110                             MVS/XA since some printers can't get to user
00111                              fonts anyway */
00112 int dontmakefont = 1 ;
00113 #else
00114 int dontmakefont = 0 ; /* if makefont fails once we won't try again */
00115 #endif  /* IBM: VM/CMS */
00116 #endif
00117 
00118 void
00119 lectureuser P1H(void) {
00120    static int userwarned = 0 ;
00121 
00122    if (! userwarned) {
00123       error("Such scaling will generate extremely poor output.") ;
00124       userwarned = 1 ;
00125    }
00126 }
00127 Boolean
00128 pkopen P1C(register fontdesctype *, fd)
00129 {
00130    register char *d, *n ;
00131    char *name_ret ;
00132 #ifdef KPATHSEA
00133    int dpi_ret ;
00134 #else
00135    int vdpi ;
00136 #endif
00137    d = fd->area ;
00138    n = fd->name ;
00139 #ifndef KPATHSEA
00140    if (*d==0)
00141       d = pkpath ;
00142 #endif
00143 #ifdef FONTLIB
00144    if (*(fd->area) == 0) {
00145       int del ;
00146       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
00147         if ((pkfile=flisearch(n, fd->dpi + del)) != (FILE *)NULL )
00148           return(1);
00149       }
00150    }
00151 #endif
00152    {
00153 #ifdef KPATHSEA
00154      char *this_name = concat (d, n);
00155 
00156      pkfile=pksearch(pkpath, this_name, READBIN, fd->dpi, &name_ret, &dpi_ret);
00157 
00158      if (!pkfile || !FILESTRCASEEQ (this_name, name_ret))
00159        {
00160         if (!pkfile)
00161          (void)sprintf(errbuf,
00162             "Font %s%s not found, characters will be left blank.",
00163             fd->area, n) ;
00164         else
00165           sprintf(errbuf, "Font %s%s not found,  using %s instead.",
00166             fd->area, n, name_ret) ;
00167          dontmakefont = 1;
00168          error(errbuf) ;
00169        }
00170      else if (!kpse_bitmap_tolerance ((double) dpi_ret, (double) fd->dpi))
00171        {
00172            fd->loadeddpi = dpi_ret ;
00173            fd->alreadyscaled = 0 ;
00174            (void)sprintf(errbuf,
00175                    "Font %s at %d not found; scaling %d instead.",
00176                                      n, fd->dpi, dpi_ret) ;
00177            error(errbuf) ;
00178            lectureuser() ;
00179        }
00180 
00181      if (this_name != name_ret)
00182        free (this_name);
00183        
00184      return pkfile != NULL;
00185    }
00186 #else
00187       int del ;
00188       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
00189          if (actualdpi == vactualdpi) {
00190             vdpi = 0 ;
00191          } else {
00192             vdpi = (2 * ((long)vactualdpi) * (fd->dpi + del) + actualdpi)
00193                                                        / (2 * actualdpi) ;
00194          }
00195 #ifdef MVSXA
00196          (void)sprintf(name, "pk%d(%s)", fd->dpi + del, n) ;
00197 #else
00198          (void)sprintf(name, "%s.%dpk", n, fd->dpi + del) ;
00199 #endif
00200          if (0 != (pkfile=pksearch(d, name, READBIN, n, fd->dpi + del, vdpi)))
00201             return(1) ;
00202       }
00203    }
00204    if (d == pkpath) {
00205       if (actualdpi == vactualdpi) {
00206          vdpi = 0 ;
00207       } else {
00208          vdpi = (2 * ((long)vactualdpi) * fd->dpi + actualdpi)
00209                                                     / (2 * actualdpi) ;
00210       }
00211 #ifdef MVSXA
00212       (void)sprintf(name, "pk%d(%s)", fd->dpi, n) ;
00213 #else
00214       (void)sprintf(name, "%s.%dpk", n, fd->dpi) ;
00215 #endif
00216       makefont(n, (int)fd->dpi, DPI) ;
00217       if (dontmakefont == 0 &&
00218           (pkfile = pksearch(d, name, READBIN, n, fd->dpi, vdpi)))
00219                return(1) ;
00220 #ifndef MSDOS
00221 #ifdef OS2
00222    if (_osmode == OS2_MODE)
00223       dontmakefont = 1;       /* failed so don't try again under OS/2, 
00224                                  but do try for MSDOS */
00225 #else
00226 #ifndef ATARIST
00227       dontmakefont = 1 ;
00228 #endif
00229 #endif
00230 #endif
00231    }
00232 /*
00233  *   If nothing above worked, then we get desparate.  We attempt to
00234  *   open the stupid font at one of a small set of predefined sizes,
00235  *   and then use PostScript scaling to generate the correct size.
00236  *
00237  *   We much prefer scaling up to scaling down, since scaling down
00238  *   can omit character features, so we try the larger sizes first,
00239  *   and then work down.
00240  */
00241    {
00242       int i, j ;
00243 
00244       if (lastresortsizes[0] && fd->dpi < 30000) {
00245          for (i=0; lastresortsizes[i] < fd->dpi; i++) ;
00246          for (j = i-1; j >= 0; j--) {
00247             if (actualdpi == vactualdpi) {
00248                vdpi = 0 ;
00249             } else {
00250                vdpi = (2 * ((long)vactualdpi) * lastresortsizes[j] + actualdpi)
00251                                                        / (2 * actualdpi) ;
00252             }
00253 #ifdef MVSXA
00254             (void)sprintf(name, "pk%d(%s)", lastresortsizes[j], n) ;
00255 #else
00256             (void)sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
00257 #endif
00258 #ifdef FONTLIB
00259             if (0 != (pkfile=flisearch(n,(halfword)lastresortsizes[j]))
00260              || 0 != (pkfile=pksearch(d, name, READBIN, n,
00261                          (halfword)lastresortsizes[j], vdpi))) {
00262 #else
00263             if (0 != (pkfile=pksearch(d, name, READBIN, n,
00264                          (halfword)lastresortsizes[j], vdpi))) {
00265 #endif
00266                fd->loadeddpi = lastresortsizes[j] ;
00267                fd->alreadyscaled = 0 ;
00268                (void)sprintf(errbuf,
00269                        "Font %s at %d dpi not found; scaling %d instead.",
00270                                          n, fd->dpi, lastresortsizes[j]) ;
00271                error(errbuf) ;
00272                lectureuser() ;
00273                return 1 ;
00274             }
00275          }
00276          for (j = i; lastresortsizes[j] < 30000; j++) {
00277             if (actualdpi == vactualdpi) {
00278                vdpi = 0 ;
00279             } else {
00280                vdpi = (2 * ((long)vactualdpi) * lastresortsizes[j] + actualdpi)
00281                                                        / (2 * actualdpi) ;
00282             }
00283             (void)sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
00284 #ifdef FONTLIB
00285             if (0 != (pkfile=flisearch(n, (halfword)lastresortsizes[j]))
00286                 || 0 != (pkfile=pksearch(d, name, READBIN, n,
00287                              (halfword)lastresortsizes[j], vdpi))) {
00288 #else
00289             if (0 != (pkfile=pksearch(d, name, READBIN, n,
00290                             (halfword)lastresortsizes[j], vdpi))) {
00291 #endif
00292                fd->loadeddpi = lastresortsizes[j] ;
00293                fd->alreadyscaled = 0 ;
00294                (void)sprintf(errbuf,
00295                        "Font %s at %d dpi not found; scaling %d instead.",
00296                                          name, fd->dpi, lastresortsizes[j]) ;
00297                error(errbuf) ;
00298                lectureuser() ;
00299                return 1 ;
00300             }
00301          }
00302       }
00303    }
00304 #ifdef MVSXA
00305    (void)sprintf(name, "%s.pk%d", n, fd->dpi) ;
00306 #else
00307    (void)sprintf(name, "%s.%dpk", n, fd->dpi) ;
00308 #endif
00309    (void)sprintf(errbuf,
00310       "Font %s%s not found, characters will be left blank.",
00311       fd->area, name) ;
00312    error(errbuf) ;
00313    return(0) ;
00314 #endif /* KPATHSEA */
00315 }
00316 
00317 /*
00318  *   Now our loadfont routine.  We return an integer indicating the
00319  *   highest character code in the font, so we know how much space
00320  *   to reserve for the character.  (It's returned in the font
00321  *   structure, along with everything else.)
00322  */
00323 void
00324 loadfont P1C(register fontdesctype *, curfnt)
00325 {
00326    register integer i ;
00327    register shalfword cmd ;
00328    register integer k ;
00329    register integer length = 0 ;
00330    register shalfword cc = 0 ;
00331    register integer scaledsize = curfnt->scaledsize ;
00332    register quarterword *tempr ;
00333    register chardesctype *cd = 0 ;
00334    int maxcc = 0 ;
00335    int munged = 0 ;
00336 /*
00337  *   We clear out some pointers:
00338  */
00339    if (curfnt->loaded == 3) {
00340       for (i=0; i<256; i++) {
00341          curfnt->chardesc[i].TFMwidth = 0 ;
00342          curfnt->chardesc[i].packptr = NULL ;
00343          curfnt->chardesc[i].pixelwidth = 0 ;
00344          curfnt->chardesc[i].flags &= EXISTS ;
00345          curfnt->chardesc[i].flags2 = 0 ;
00346       }
00347    } else {
00348       for (i=0; i<256; i++) {
00349          curfnt->chardesc[i].TFMwidth = 0 ;
00350          curfnt->chardesc[i].packptr = NULL ;
00351          curfnt->chardesc[i].pixelwidth = 0 ;
00352          curfnt->chardesc[i].flags = 0 ;
00353          curfnt->chardesc[i].flags2 = 0 ;
00354       }
00355    }
00356    curfnt->maxchars = 256 ; /* just in case we return before the end */
00357    if (!pkopen(curfnt)) {
00358       tfmload(curfnt) ;
00359       return ;
00360    }
00361 #ifdef DEBUG
00362    if (dd(D_FONTS))
00363       (void)fprintf(stderr,"Loading pk font %s at %.1fpt\n",
00364          curfnt->name, (real)scaledsize/(alpha*0x100000)) ;
00365 #endif /* DEBUG */
00366    if (pkbyte()!=247)
00367       badpk("expected pre") ;
00368    if (pkbyte()!=89)
00369       badpk("wrong id byte") ;
00370    for(i=pkbyte(); i>0; i--)
00371       (void)pkbyte() ;
00372    k = (integer)(alpha * (real)pkquad()) ;
00373    if (k > curfnt->designsize + fsizetol ||
00374        k < curfnt->designsize - fsizetol) {
00375       (void)sprintf(errbuf,"Design size mismatch in font %s", curfnt->name) ;
00376       error(errbuf) ;
00377    }
00378    k = pkquad() ;
00379    if (k && curfnt->checksum)
00380       if (k!=curfnt->checksum) {
00381          (void)sprintf(errbuf,"Checksum mismatch in font %s", curfnt->name) ;
00382          error(errbuf) ;
00383        }
00384    k = pkquad() ; /* assume that hppp is correct in the PK file */
00385    k = pkquad() ; /* assume that vppp is correct in the PK file */
00386 /*
00387  *   Now we get down to the serious business of reading character definitions.
00388  */
00389    while ((cmd=pkbyte())!=245) {
00390       if (cmd < 240) {
00391          switch (cmd & 7) {
00392 case 0: case 1: case 2: case 3:
00393             length = (cmd & 7) * 256 + pkbyte() - 3 ;
00394             cc = pkbyte() ;
00395             cd = curfnt->chardesc+cc ;
00396             if (nosmallchars || curfnt->dpi != curfnt->loadeddpi)
00397                cd->flags |= BIGCHAR ;
00398             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
00399             cd->pixelwidth = pkbyte() ;
00400             break ;
00401 case 4: case 5: case 6:
00402             length = (cmd & 3) * 65536L + pkbyte() * 256L ;
00403             length = length + pkbyte() - 4L ;
00404             cc = pkbyte() ;
00405             cd = curfnt->chardesc+cc ;
00406             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
00407             cd->flags |= BIGCHAR ;
00408             i = pkbyte() ;
00409             cd->pixelwidth = i * 256 + pkbyte() ;
00410             break ;
00411 case 7:
00412             length = pkquad() - 11 ;
00413             cc = pkquad() ;
00414             if (cc<0 || cc>255) badpk("character code out of range") ;
00415             cd = curfnt->chardesc + cc ;
00416             cd->flags |= BIGCHAR ;
00417             cd->TFMwidth = scalewidth(pkquad(), scaledsize) ;
00418             cd->pixelwidth = (pkquad() + 32768) >> 16 ;
00419             k = pkquad() ;
00420          }
00421          if (cd->pixelwidth == 0 && cd->TFMwidth != 0) {
00422             if (cd->TFMwidth > 0)
00423                k = (integer)(cd->TFMwidth * conv + 0.5) ;
00424             else
00425                k = -(integer)(-cd->TFMwidth * conv + 0.5) ;
00426             if (k != 0) {
00427                cd->pixelwidth = k ;
00428                munged++ ;
00429             }
00430          }
00431          if (length <= 0)
00432             badpk("packet length too small") ;
00433          if (dopprescan && ((cd->flags & EXISTS) == 0)) {
00434             for (length--; length>0; length--)
00435                (void)pkbyte() ;
00436          } else {
00437             if (cc > maxcc)
00438                maxcc = cc ;
00439             if (bytesleft < length || (length > MINCHUNK && compressed)) {
00440 #ifdef DEBUG
00441                 if (dd(D_MEM))
00442                    (void)fprintf(stderr,
00443 #ifdef SHORTINT
00444                       "Allocating new raster memory (%ld req, %ld left)\n",
00445                                    length, bytesleft) ;
00446 #else
00447                       "Allocating new raster memory (%d req, %d left)\n",
00448                                    (int)length, (int)bytesleft) ;
00449 #endif
00450 #endif /* DEBUG */
00451                 if (length > MINCHUNK) {
00452                    tempr = (quarterword *)mymalloc((integer)length) ;
00453                 } else {
00454                    raster = (quarterword *)mymalloc((integer)RASTERCHUNK) ;
00455                    tempr = raster ;
00456                    bytesleft = RASTERCHUNK - length ;
00457                    raster += length ;
00458                }
00459             } else {
00460                tempr = raster ;
00461                bytesleft -= length ;
00462                raster += length ;
00463             }
00464             cd->packptr = tempr ;
00465             *tempr++ = cmd ;
00466             for (length--; length>0; length--)
00467                *tempr++ = pkbyte() ;
00468          }
00469          cd->flags2 |= EXISTS ;
00470       } else {
00471          k = 0 ;
00472          switch (cmd) {
00473 case 243:
00474             k = pkbyte() ;
00475             if (k > 127)
00476                k -= 256 ;
00477 case 242:
00478             k = k * 256 + pkbyte() ;
00479 case 241:
00480             k = k * 256 + pkbyte() ;
00481 case 240:
00482             k = k * 256 + pkbyte() ;
00483             while (k-- > 0)
00484                i = pkbyte() ;
00485             break ;
00486 case 244:
00487             k = pkquad() ;
00488             break ;
00489 case 246:
00490             break ;
00491 default:
00492             badpk("! unexpected command") ;
00493          }
00494       }
00495    }
00496 #ifdef FONTLIB
00497    if (flib)
00498       flib = 0 ;
00499    else
00500 #endif
00501    (void)fclose(pkfile) ;
00502    curfnt->loaded = 1 ;
00503    curfnt->maxchars = maxcc + 1 ;
00504    if (munged > 0) {
00505       static int seen = 0 ;
00506       sprintf(errbuf,
00507           "Font %s at %d dpi has most likely been made improperly;",
00508            curfnt->name, curfnt->dpi) ;
00509       error(errbuf) ;
00510       if (seen)
00511          return ;
00512       seen = 1 ;
00513       sprintf(errbuf,
00514      "%d characters have 0 escapements but non-trivial TFM widths.", munged) ;
00515       error(errbuf) ;
00516       error(
00517           "I'm stumbling along as best I can, but I recommend regenerating") ;
00518       error(
00519           "these fonts; the problem is probably that they are non-CM fonts") ;
00520       error(
00521           "(such as circle10 or line10) created with a MF with the CM base") ;
00522       error("preloaded .") ;
00523    }
00524 }