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