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