home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / dvips / loadfont.c < prev    next >
C/C++ Source or Header  |  1994-09-27  |  14KB  |  482 lines

  1. /*
  2.  *   Here's the code to load a PK file into memory.
  3.  *   Individual bitmaps won't be unpacked until they prove to be needed.
  4.  */
  5. #include "dvips.h" /* The copyright notice in that file is included too! */
  6. #ifdef OS2
  7. #include <stdlib.h>
  8. #endif
  9. /*
  10.  *   These are the external routines we use.
  11.  */
  12. #ifdef AMIGA
  13. #include "loadfont_protos.h"
  14. #include "dvips_protos.h"
  15. #include "search_protos.h"
  16. #include "makefont_protos.h"
  17. #include "scalewidth_protos.h"
  18. #include "tfmload_protos.h"
  19. #include "flib_protos.h"
  20. #else
  21. extern void makefont() ;
  22. extern void error() ;
  23. extern integer scalewidth() ;
  24. extern int tfmload() ;
  25. extern FILE *pksearch() ;
  26. #endif
  27. /*
  28.  *   These are the external variables we use.
  29.  */
  30. #ifdef DEBUG
  31. extern integer debug_flag;
  32. #endif  /* DEBUG */
  33. extern long bytesleft ;
  34. extern quarterword *raster ;
  35. extern real conv ;
  36. extern int actualdpi, vactualdpi ;
  37. extern real alpha ;
  38. extern char *pkpath ;
  39. char errbuf[200] ;
  40. int lastresortsizes[40] ;
  41. extern integer fsizetol ;
  42. extern Boolean nosmallchars ;
  43. extern Boolean compressed ;
  44. extern Boolean dopprescan ;
  45. #ifdef FONTLIB
  46. extern Boolean flib ;
  47. extern FILE *flisearch() ;
  48. #endif
  49. /*
  50.  *   Now we have some routines to get stuff from the PK file.
  51.  *   Subroutine pkbyte returns the next byte.
  52.  */
  53. FILE *pkfile ;
  54. char name[50] ;
  55. void
  56. badpk(s)
  57.    char *s ;
  58. {
  59.    (void)sprintf(errbuf,"! Bad PK file %s: %s",name,s) ;
  60.    error(errbuf);
  61. }
  62.  
  63. shalfword
  64. pkbyte()
  65. {
  66.    register shalfword i ;
  67.  
  68.    if ((i=getc(pkfile))==EOF)
  69.       badpk("unexpected eof") ;
  70.    return(i) ;
  71. }
  72.  
  73. integer
  74. pkquad()
  75. {
  76.    register integer i ;
  77.  
  78.    i = pkbyte() ;
  79.    if (i > 127)
  80.       i -= 256 ;
  81.    i = i * 256 + pkbyte() ;
  82.    i = i * 256 + pkbyte() ;
  83.    i = i * 256 + pkbyte() ;
  84.    return(i) ;
  85. }
  86.  
  87. integer
  88. pktrio()
  89. {
  90.    register integer i ;
  91.  
  92.    i = pkbyte() ;
  93.    i = i * 256 + pkbyte() ;
  94.    i = i * 256 + pkbyte() ;
  95.    return(i) ;
  96. }
  97.  
  98.  
  99. /*
  100.  *   pkopen opens the pk file.  This is system dependent.  We work really
  101.  *   hard to open some sort of PK file.
  102.  */
  103. #ifdef VMCMS /* IBM: VM/CMS - we let DVIPS EXEC handle this after
  104.                              the DVIPS MODULE has finished to avoid
  105.                              complications with system calls. */
  106. int dontmakefont = 0 ;
  107. #else
  108. #ifdef MVSXA /* IBM: MVS/XA - we let system administrator handle this on
  109.                             MVS/XA since some printers can't get to user
  110.                              fonts anyway */
  111. int dontmakefont = 1 ;
  112. #else
  113. int dontmakefont = 0 ; /* if makefont fails once we won't try again */
  114. #endif  /* IBM: VM/CMS */
  115. #endif
  116.  
  117. void
  118. lectureuser() {
  119.    static int userwarned = 0 ;
  120.  
  121.    if (! userwarned) {
  122.       error("Such scaling will generate extremely poor output.") ;
  123.       userwarned = 1 ;
  124.    }
  125. }
  126. Boolean
  127. pkopen(fd)
  128.         register fontdesctype *fd ;
  129. {
  130.    register char *d, *n ;
  131.    int vdpi ;
  132.  
  133.    d = fd->area ;
  134.    n = fd->name ;
  135.    if (*d==0)
  136.       d = pkpath ;
  137. #ifdef FONTLIB
  138.    if (*(fd->area) == 0) {
  139.       int del ;
  140.       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
  141.         if ((pkfile=flisearch(n, fd->dpi + del)) != (FILE *)NULL )
  142.           return(1);
  143.       }
  144.    }
  145. #endif
  146.    {
  147.       int del ;
  148.       for (del=0; del<=RES_TOLERANCE(fd->dpi); del=del>0?-del:-del+1) {
  149.          if (actualdpi == vactualdpi) {
  150.             vdpi = 0 ;
  151.          } else {
  152.             vdpi = (2 * ((long)vactualdpi) * (fd->dpi + del) + actualdpi)
  153.                                                        / (2 * actualdpi) ;
  154.          }
  155. #ifdef MVSXA
  156.          (void)sprintf(name, "pk%d(%s)", fd->dpi + del, n) ;
  157. #else
  158.          (void)sprintf(name, "%s.%dpk", n, fd->dpi + del) ;
  159. #endif
  160.          if (0 != (pkfile=pksearch(d, name, READBIN, n, fd->dpi + del, vdpi)))
  161.             return(1) ;
  162.       }
  163.    }
  164.    if (d == pkpath) {
  165.       if (actualdpi == vactualdpi) {
  166.          vdpi = 0 ;
  167.       } else {
  168.          vdpi = (2 * ((long)vactualdpi) * fd->dpi + actualdpi)
  169.                                                     / (2 * actualdpi) ;
  170.       }
  171. #ifdef MVSXA
  172.       (void)sprintf(name, "pk%d(%s)", fd->dpi, n) ;
  173. #else
  174.       (void)sprintf(name, "%s.%dpk", n, fd->dpi) ;
  175. #endif
  176.       makefont(n, (int)fd->dpi, DPI) ;
  177.       if (dontmakefont == 0 &&
  178.           (pkfile = pksearch(d, name, READBIN, n, fd->dpi, vdpi)))
  179.                return(1) ;
  180. #ifndef MSDOS
  181. #ifdef OS2
  182.    if (_osmode == OS2_MODE)
  183.       dontmakefont = 1;       /* failed so don't try again under OS/2, 
  184.                                  but do try for MSDOS */
  185. #else
  186. #ifndef ATARIST
  187.       dontmakefont = 1 ;
  188. #endif
  189. #endif
  190. #endif
  191.    }
  192. /*
  193.  *   If nothing above worked, then we get desparate.  We attempt to
  194.  *   open the stupid font at one of a small set of predefined sizes,
  195.  *   and then use PostScript scaling to generate the correct size.
  196.  *
  197.  *   We much prefer scaling up to scaling down, since scaling down
  198.  *   can omit character features, so we try the larger sizes first,
  199.  *   and then work down.
  200.  */
  201.    {
  202.       int i, j ;
  203.  
  204.       if (lastresortsizes[0] && fd->dpi < 30000) {
  205.          for (i=0; lastresortsizes[i] < fd->dpi; i++) ;
  206.          for (j = i-1; j >= 0; j--) {
  207.             if (actualdpi == vactualdpi) {
  208.                vdpi = 0 ;
  209.             } else {
  210.                vdpi = (2 * ((long)vactualdpi) * lastresortsizes[j] + actualdpi)
  211.                                                        / (2 * actualdpi) ;
  212.             }
  213. #ifdef MVSXA
  214.             (void)sprintf(name, "pk%d(%s)", lastresortsizes[j], n) ;
  215. #else
  216.             (void)sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
  217. #endif
  218. #ifdef FONTLIB
  219.             if (0 != (pkfile=flisearch(n,(halfword)lastresortsizes[j]))
  220.              || 0 != (pkfile=pksearch(d, name, READBIN, n,
  221.                          (halfword)lastresortsizes[j], vdpi))) {
  222. #else
  223.             if (0 != (pkfile=pksearch(d, name, READBIN, n,
  224.                          (halfword)lastresortsizes[j], vdpi))) {
  225. #endif
  226.                fd->loadeddpi = lastresortsizes[j] ;
  227.                fd->alreadyscaled = 0 ;
  228.                (void)sprintf(errbuf,
  229.                        "Font %s at %d dpi not found; scaling %d instead.",
  230.                                          name, fd->dpi, lastresortsizes[j]) ;
  231.                error(errbuf) ;
  232.                lectureuser() ;
  233.                return 1 ;
  234.             }
  235.          }
  236.          for (j = i; lastresortsizes[j] < 30000; j++) {
  237.             if (actualdpi == vactualdpi) {
  238.                vdpi = 0 ;
  239.             } else {
  240.                vdpi = (2 * ((long)vactualdpi) * lastresortsizes[j] + actualdpi)
  241.                                                        / (2 * actualdpi) ;
  242.             }
  243.             (void)sprintf(name, "%s.%dpk", n, lastresortsizes[j]) ;
  244. #ifdef FONTLIB
  245.             if (0 != (pkfile=flisearch(n, (halfword)lastresortsizes[j]))
  246.                 || 0 != (pkfile=pksearch(d, name, READBIN, n,
  247.                              (halfword)lastresortsizes[j], vdpi))) {
  248. #else
  249.             if (0 != (pkfile=pksearch(d, name, READBIN, n,
  250.                             (halfword)lastresortsizes[j], vdpi))) {
  251. #endif
  252.                fd->loadeddpi = lastresortsizes[j] ;
  253.                fd->alreadyscaled = 0 ;
  254.                (void)sprintf(errbuf,
  255.                        "Font %s at %d dpi not found; scaling %d instead.",
  256.                                          name, fd->dpi, lastresortsizes[j]) ;
  257.                error(errbuf) ;
  258.                lectureuser() ;
  259.                return 1 ;
  260.             }
  261.          }
  262.       }
  263.    }
  264. #ifdef MVSXA
  265.    (void)sprintf(name, "%s.pk%d", n, fd->dpi) ;
  266. #else
  267.    (void)sprintf(name, "%s.%dpk", n, fd->dpi) ;
  268. #endif
  269.    (void)sprintf(errbuf,
  270.       "Font %s%s not found, characters will be left blank.",
  271.       fd->area, name) ;
  272.    error(errbuf) ;
  273.    return(0) ;
  274. }
  275.  
  276. /*
  277.  *   Now our loadfont routine.  We return an integer indicating the
  278.  *   highest character code in the font, so we know how much space
  279.  *   to reserve for the character.  (It's returned in the font
  280.  *   structure, along with everything else.)
  281.  */
  282. void
  283. loadfont(curfnt)
  284.         register fontdesctype *curfnt ;
  285. {
  286.    register shalfword i ;
  287.    register shalfword cmd ;
  288.    register integer k ;
  289.    register integer length = 0 ;
  290.    register shalfword cc = 0 ;
  291.    register integer scaledsize = curfnt->scaledsize ;
  292.    register quarterword *tempr ;
  293.    register chardesctype *cd = 0 ;
  294.    int maxcc = 0 ;
  295.    int munged = 0 ;
  296. /*
  297.  *   We clear out some pointers:
  298.  */
  299.    if (curfnt->loaded == 3) {
  300.       for (i=0; i<256; i++) {
  301.          curfnt->chardesc[i].TFMwidth = 0 ;
  302.          curfnt->chardesc[i].packptr = NULL ;
  303.          curfnt->chardesc[i].pixelwidth = 0 ;
  304.          curfnt->chardesc[i].flags &= EXISTS ;
  305.       }
  306.    } else {
  307.       for (i=0; i<256; i++) {
  308.          curfnt->chardesc[i].TFMwidth = 0 ;
  309.          curfnt->chardesc[i].packptr = NULL ;
  310.          curfnt->chardesc[i].pixelwidth = 0 ;
  311.          curfnt->chardesc[i].flags = 0 ;
  312.       }
  313.    }
  314.    curfnt->maxchars = 256 ; /* just in case we return before the end */
  315.    if (!pkopen(curfnt)) {
  316.       tfmload(curfnt) ;
  317.       return ;
  318.    }
  319. #ifdef DEBUG
  320.    if (dd(D_FONTS))
  321.       (void)fprintf(stderr,"Loading pk font %s at %.1fpt\n",
  322.          name, (real)scaledsize/(alpha*0x100000)) ;
  323. #endif /* DEBUG */
  324.    if (pkbyte()!=247)
  325.       badpk("expected pre") ;
  326.    if (pkbyte()!=89)
  327.       badpk("wrong id byte") ;
  328.    for(i=pkbyte(); i>0; i--)
  329.       (void)pkbyte() ;
  330.    k = (integer)(alpha * (real)pkquad()) ;
  331.    if (k > curfnt->designsize + fsizetol ||
  332.        k < curfnt->designsize - fsizetol) {
  333.       (void)sprintf(errbuf,"Design size mismatch in font %s", name) ;
  334.       error(errbuf) ;
  335.    }
  336.    k = pkquad() ;
  337.    if (k && curfnt->checksum)
  338.       if (k!=curfnt->checksum) {
  339.          (void)sprintf(errbuf,"Checksum mismatch in font %s", name) ;
  340.          error(errbuf) ;
  341.        }
  342.    k = pkquad() ; /* assume that hppp is correct in the PK file */
  343.    k = pkquad() ; /* assume that vppp is correct in the PK file */
  344. /*
  345.  *   Now we get down to the serious business of reading character definitions.
  346.  */
  347.    while ((cmd=pkbyte())!=245) {
  348.       if (cmd < 240) {
  349.          switch (cmd & 7) {
  350. case 0: case 1: case 2: case 3:
  351.             length = (cmd & 7) * 256 + pkbyte() - 3 ;
  352.             cc = pkbyte() ;
  353.             cd = curfnt->chardesc+cc ;
  354.             if (nosmallchars || curfnt->dpi != curfnt->loadeddpi)
  355.                cd->flags |= BIGCHAR ;
  356.             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
  357.             cd->pixelwidth = pkbyte() ;
  358.             break ;
  359. case 4: case 5: case 6:
  360.             length = (cmd & 3) * 65536L + pkbyte() * 256L ;
  361.             length = length + pkbyte() - 4L ;
  362.             cc = pkbyte() ;
  363.             cd = curfnt->chardesc+cc ;
  364.             cd->TFMwidth = scalewidth(pktrio(), scaledsize) ;
  365.             cd->flags |= BIGCHAR ;
  366.             i = pkbyte() ;
  367.             cd->pixelwidth = i * 256 + pkbyte() ;
  368.             break ;
  369. case 7:
  370.             length = pkquad() - 11 ;
  371.             cc = pkquad() ;
  372.             if (cc<0 || cc>255) badpk("character code out of range") ;
  373.             cd = curfnt->chardesc + cc ;
  374.             cd->flags |= BIGCHAR ;
  375.             cd->TFMwidth = scalewidth(pkquad(), scaledsize) ;
  376.             cd->pixelwidth = (pkquad() + 32768) >> 16 ;
  377.             k = pkquad() ;
  378.          }
  379.          if (cd->pixelwidth == 0 && cd->TFMwidth != 0) {
  380.             if (cd->TFMwidth > 0)
  381.                k = (integer)(cd->TFMwidth * conv + 0.5) ;
  382.             else
  383.                k = -(integer)(-cd->TFMwidth * conv + 0.5) ;
  384.             if (k != 0) {
  385.                cd->pixelwidth = k ;
  386.                munged++ ;
  387.             }
  388.          }
  389.          if (length <= 0)
  390.             badpk("packet length too small") ;
  391.          if (dopprescan && ((cd->flags & EXISTS) == 0)) {
  392.             for (length--; length>0; length--)
  393.                (void)pkbyte() ;
  394.          } else {
  395.             if (cc > maxcc)
  396.                maxcc = cc ;
  397.             if (bytesleft < length || (length > MINCHUNK && compressed)) {
  398. #ifdef DEBUG
  399.                 if (dd(D_MEM))
  400.                    (void)fprintf(stderr,
  401. #ifdef SHORTINT
  402.                       "Allocating new raster memory (%ld req, %ld left)\n",
  403.                                    length, bytesleft) ;
  404. #else
  405.                       "Allocating new raster memory (%d req, %d left)\n",
  406.                                    (int)length, (int)bytesleft) ;
  407. #endif
  408. #endif /* DEBUG */
  409.                 if (length > MINCHUNK) {
  410.                    tempr = (quarterword *)mymalloc((integer)length) ;
  411.                 } else {
  412.                    raster = (quarterword *)mymalloc((integer)RASTERCHUNK) ;
  413.                    tempr = raster ;
  414.                    bytesleft = RASTERCHUNK - length ;
  415.                    raster += length ;
  416.                }
  417.             } else {
  418.                tempr = raster ;
  419.                bytesleft -= length ;
  420.                raster += length ;
  421.             }
  422.             cd->packptr = tempr ;
  423.             *tempr++ = cmd ;
  424.             for (length--; length>0; length--)
  425.                *tempr++ = pkbyte() ;
  426.          }
  427.       } else {
  428.          k = 0 ;
  429.          switch (cmd) {
  430. case 243:
  431.             k = pkbyte() ;
  432.             if (k > 127)
  433.                k -= 256 ;
  434. case 242:
  435.             k = k * 256 + pkbyte() ;
  436. case 241:
  437.             k = k * 256 + pkbyte() ;
  438. case 240:
  439.             k = k * 256 + pkbyte() ;
  440.             while (k-- > 0)
  441.                i = pkbyte() ;
  442.             break ;
  443. case 244:
  444.             k = pkquad() ;
  445.             break ;
  446. case 246:
  447.             break ;
  448. default:
  449.             badpk("! unexpected command") ;
  450.          }
  451.       }
  452.    }
  453. #ifdef FONTLIB
  454.    if (flib)
  455.       flib = 0 ;
  456.    else
  457. #endif
  458.    (void)fclose(pkfile) ;
  459.    curfnt->loaded = 1 ;
  460.    curfnt->maxchars = maxcc + 1 ;
  461.    if (munged > 0) {
  462.       static int seen = 0 ;
  463.       sprintf(errbuf,
  464.           "Font %s at %d dpi has most likely been made improperly;",
  465.            curfnt->name, curfnt->dpi) ;
  466.       error(errbuf) ;
  467.       if (seen)
  468.          return ;
  469.       seen = 1 ;
  470.       sprintf(errbuf,
  471.      "%d characters have 0 escapements but non-trivial TFM widths.", munged) ;
  472.       error(errbuf) ;
  473.       error(
  474.           "I'm stumbling along as best I can, but I recommend regenerating") ;
  475.       error(
  476.           "these fonts; the problem is probably that they are non-CM fonts") ;
  477.       error(
  478.           "(such as circle10 or line10) created with a MF with the CM base") ;
  479.       error("preloaded .") ;
  480.    }
  481. }
  482.