home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3.4.17 [SPARC, PA-RISC] / nextstep33_risc.iso / NextLibrary / TeX / tex / src / texview / loadfont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-26  |  12.1 KB  |  459 lines

  1. /*
  2.  *   loadfont.c of dvisw software package
  3.  *   loads a pk file into memory.
  4.  */
  5. #include "structures.h"
  6. #include <strings.h>
  7. /*
  8.  *   These are the external routines we use.
  9.  */
  10. extern void error() ;
  11. extern integer scalewidth() ;
  12. extern void tfmload() ;
  13. extern FILE *pksearch() ;
  14. extern void makefont() ;
  15. extern shalfword dvibyte() ;
  16. extern halfword twobytes() ;
  17. extern integer threebytes() ;
  18. extern integer signedquad() ;
  19. extern shalfword signedbyte() ;
  20. extern shalfword signedpair() ;
  21. extern integer signedtrio() ;
  22. extern void movmem(), cmpmem() ;
  23. extern void free() ;
  24. extern void unpack() ;
  25. extern void setstatus(), qstatus() ;
  26. extern void TPSinit(), TPSdf(), TPSdc(), TPSbop(), TPSeop() ;
  27. extern void texflush() ;
  28. extern void TPSdfe(), TPSrfe(), TPSdfes() ;
  29. extern void pswrite() ;
  30. extern int residentfont(), virtualfont() ;
  31. extern void add_header() ;
  32. /*
  33.  *   These are the external variables we use.
  34.  */
  35. static quarterword *svirpos ;
  36. extern quarterword *virpos ;
  37. extern char temperrorbuf[] ;
  38. extern fontdesctype *fontlist, *curfnt ;
  39. extern integer dvimag ;
  40. extern FILE *pkfile ;
  41. extern FILE *dvifile ;
  42. extern integer curpos ;
  43. extern char *pkpath ;
  44. extern real pxlconv ;
  45. extern real screendpi ;
  46. #ifdef DEBUG
  47. extern int debugon ;
  48. #endif
  49. extern int *existsize ;
  50. FILE *readingpk ;
  51. integer scurpos ;
  52. integer curid ;
  53. int lastresortsizes[40] ;
  54. /*
  55.  *   We use mymalloc here.
  56.  */
  57. void *mymalloc() ;
  58. void *tempbuf() ;
  59. char lastfile[200] ;
  60. extern TeXfontdesctype *TeXfontlist ;
  61. Boolean pkopen(tft, dpi)
  62. register TeXfontdesctype *tft ;
  63. int dpi ;
  64. {
  65.    register char *d, *n ;
  66.  
  67.    n = tft->name ;
  68.    if (*n==0) {
  69.       n++ ;
  70.       d = pkpath ;
  71.    } else {
  72.       d = n ;
  73.       while (*n) n++ ;
  74.       n++ ;
  75.    }
  76.    sprintf(lastfile, "%s.%dpk", n, dpi) ;
  77.    sprintf(temperrorbuf, "Loading %s", lastfile) ;
  78.    qstatus(temperrorbuf) ;
  79.    {  
  80.       int del ;
  81.       for (del=0; del<=1+dpi/500; del=del>0?-del:-del+1) {
  82.          (void)sprintf(lastfile, "%s.%dpk", n, dpi + del) ;
  83.          if (pkfile=pksearch(d, lastfile, n, dpi + del))
  84.             goto fontfound ;
  85.       }
  86.    }
  87.    if (d == pkpath) {
  88.       (void)sprintf(lastfile, "%s.%dpk", n, dpi) ;
  89.       makefont(n, (int)dpi) ;
  90.       if (pkfile = pksearch(d, lastfile, n, dpi))
  91.          goto fontfound ;
  92.    }
  93. /*
  94.  *   If nothing above worked, then we get desparate.  We attempt to
  95.  *   open the stupid font at one of a small set of predefined sizes,
  96.  *   and then use PostScript scaling to generate the correct size.
  97.  *
  98.  *   We much prefer scaling up to scaling down, since scaling down
  99.  *   can omit character features, so we try the larger sizes first,
  100.  *   and then work down.
  101.  */
  102.    {
  103.       int i, j ;
  104.  
  105.       if (lastresortsizes[0] && dpi < 30000) {
  106.          for (i=0; lastresortsizes[i] < dpi; i++) ;
  107.          for (j = i-1; j >= 0; j--) {
  108.             (void)sprintf(lastfile, "%s.%dpk", n, lastresortsizes[j]) ;
  109.             if (pkfile=pksearch(d, lastfile, n, lastresortsizes[j])) {
  110.                dpi = lastresortsizes[j] ;
  111.                tft->loaded->alreadyscaled = 0 ;
  112.                goto sfontfound ;
  113.             }
  114.          }
  115.          for (j = i; lastresortsizes[j] < 30000; j++) {
  116.             (void)sprintf(lastfile, "%s.%dpk", n, lastresortsizes[j]) ;
  117.             if (pkfile=pksearch(d, lastfile, n, lastresortsizes[j])) {
  118.                dpi = lastresortsizes[j] ;
  119.                tft->loaded->alreadyscaled = 0 ;
  120.                goto sfontfound ;
  121.             }
  122.          }
  123.       }
  124.    }
  125.    strcat(temperrorbuf, " [blocks]") ;
  126.    qstatus(temperrorbuf) ;
  127.    return 0 ;
  128. sfontfound: ;
  129. #ifdef DEBUG
  130.    strcat(temperrorbuf, " [scaled]") ;
  131.    qstatus(temperrorbuf) ;
  132.    if (debugon > 1)
  133.       printf("Had to scale %d to %d\n", dpi, tft->loaded->dpi) ;
  134. #endif
  135. fontfound:
  136.    readingpk = dvifile ;
  137.    scurpos = curpos ;
  138.    svirpos = virpos ;
  139.    virpos = 0 ;
  140.    dvifile = pkfile ;
  141.    tft->loaded->loadeddpi = dpi ;
  142.    return(1) ;
  143. }
  144. /*
  145.  *   This routine compares two strings in sucession, for font names.
  146.  */
  147. short str2cmp(a, b)
  148. register char *a, *b ;
  149. {
  150.    while (*a!=0 && *a==*b) {
  151.       a++ ; b++ ;
  152.    }
  153.    if (*a!=0 || *b!=0)
  154.       return(0) ;
  155.    a++ ; b++ ;
  156.    while (*a!=0 && *a==*b) {
  157.       a++ ; b++ ;
  158.    }
  159.    return (*a==0 && *b==0) ;
  160. }
  161. void bytepack(p, w, h)
  162. register char *p ;
  163. register int w, h ;
  164. {
  165.    register char *q ;
  166.    register int i ;
  167.  
  168.    w = (w + 7) / 8 ;
  169.    if ((w & 1) == 0)
  170.       return ;
  171.    q = p + w ;
  172.    p = q + 1 ;
  173.    while (h > 1) {
  174.       for (i=w; i>0; i--)
  175.          *q++ = *p++ ;
  176.       p++ ;
  177.       h-- ;
  178.    }
  179. }
  180. /*
  181.  *   Now our loadfont routine.
  182.  */
  183. void loadfont(tft)
  184. register TeXfontdesctype *tft ;
  185. {
  186.    register fontdesctype *cf ;
  187.    register chardesctype *cd ;
  188.    register integer k ;
  189.    register integer length ;
  190.    register integer cmd ;
  191.    register integer i, j ;
  192.    register integer cc ;
  193.    register integer scaledsize = tft->scaledsize ;
  194.    register integer cheight, cwidth ;
  195.    register integer xoffset, yoffset ;
  196.    register integer dpi ;
  197.    register shalfword *p, *q ;
  198.    int fontwidths[256] ;
  199. /*
  200.  *   First, we scan through the linked list of fonts in memory, looking
  201.  *   for one that matches ours.
  202.  */
  203.    dpi = pxlconv * (float)scaledsize / tft->designsize + 0.5 ;
  204. /*
  205.  *   Now we check to see if that value is close to some other value.
  206.  *   Close is within one.  If so, we load that size.  There should
  207.  *   never be an error of more than one; the only errors are due to
  208.  *   floating point and magnifications being only valid to about three
  209.  *   sig digits.
  210.  */
  211.    for (i=0; existsize[i] < dpi; i++) ;
  212.    if (existsize[i] == dpi + 1)
  213.       dpi = existsize[i] ;
  214.    else if (existsize[i-1] == dpi - 1)
  215.       dpi = existsize[i-1] ;
  216.    if (debugon > 5)
  217.       printf("Looking for %s %ld %ld\n", tft->name+1, tft->scaledsize, dpi) ;
  218.    for (cf=fontlist; cf!=NULL; cf=cf->next) {
  219.       if (cf->dpi==dpi && str2cmp(cf->name, tft->name))
  220.          break ;
  221.    }
  222.    if (cf!=NULL) {
  223.       if (debugon > 5)
  224.          printf("Found: %s\n", cf->name+1) ;
  225.       tft->loaded = cf ;
  226.       for (i=0; i<cf->maxchars; i++)
  227.          tft->scaledwidth[i] = scalewidth(cf->chardesc[i].TFMwidth,
  228.                  tft->scaledsize) ;
  229.       if (cf->virtual) {
  230.          fontmaptype *fm ;
  231.          for (fm = cf->localfonts; fm; fm = fm->next) {
  232.             tft = fm->tdesc ;
  233.             tft->scaledsize = scalewidth(scaledsize, tft->origssize) ;
  234.          }
  235.       }
  236.       return ;
  237.    }
  238.    if (debugon > 5) printf("Not found.\n") ;
  239. /*
  240.  *   Didn't find any, we allocate a new fontdesc.
  241.  */
  242.    i = 0 ;
  243.    while (tft->name[i++]!=0) ;
  244.    while (tft->name[i++]!=0) ;
  245.    cf = mymalloc(sizeof(fontdesctype)+i, MEMF_CLEAR) ;
  246.    curfnt = cf ;
  247.    cf->chardesc = mymalloc(sizeof(chardesctype) * 256, MEMF_CLEAR) ;
  248.    cf->maxchars = 256 ;
  249.    while (i >= 0) {
  250.       cf->name[i] = tft->name[i] ;
  251.       i-- ;
  252.    }
  253.    tft->loaded = cf ;
  254.    cf->next = fontlist ;
  255.    fontlist = cf ;
  256.    cf->dpi = dpi ;
  257.    cf->id = curid++ ;
  258.    cf->resfont = NULL ;
  259.    if (residentfont(tft)) {
  260.       float fontscale ;
  261.       struct resfont *rf = cf->resfont ;
  262.       static int firstPSfont = 1 ;
  263.       char num[50] ;
  264.       char nfn[10] ;
  265.  
  266. #ifdef POPRESTORE
  267.       TPSeop() ;
  268. #endif
  269.       if (firstPSfont) {
  270.          add_header("texps.pro") ;
  271.          firstPSfont = 0 ;
  272.       }
  273.       for (i=0; i<256; i++)
  274.          fontwidths[i] = 0 ;
  275.       for (i=0; i<cf->maxchars; i++)
  276.          fontwidths[i] = cf->chardesc[i].pixelwidth ;
  277.       sprintf(nfn, "Q%ld", curid-1) ;
  278.       if (rf->downloadheader) {
  279.          char *cp = rf->downloadheader ;
  280.          char *q ;
  281.  
  282.          while (1) {
  283.             q = cp ;
  284.             while (*cp && *cp != ' ')
  285.                cp++ ;
  286.             if (*cp) {
  287.                *cp = 0 ;
  288.                add_header(q) ;
  289.                *cp++ = ' ' ;
  290.             } else {
  291.                add_header(q) ;
  292.                break ;
  293.             }
  294.          }
  295.       }
  296.       pswrite(" /") ;
  297.       pswrite(nfn) ;
  298.       pswrite(" /") ;
  299.       pswrite(nfn) ;
  300.       for (i=255; i>=0; i--) {
  301.          sprintf(num, " %d", fontwidths[i]) ;
  302.          pswrite(num) ;
  303.       }
  304.       pswrite(" {") ;
  305.       if (rf->specialinstructions)
  306.          pswrite(rf->specialinstructions) ;
  307.       pswrite("} 256 ") ;
  308.       fontscale = tft->scaledsize / 655360.0 ;
  309.       fontscale *= dvimag / 7200.0 ;
  310.       fontscale *= screendpi ;
  311.       sprintf(num, "%f ", fontscale) ;
  312.       pswrite(num) ;
  313.       pswrite("/") ;
  314.       pswrite(rf->PSname) ;
  315.       pswrite(" rf ") ;
  316.       TPSrfe(curid-1) ;
  317. #ifdef POPRESTORE
  318.       TPSbop() ;
  319. #else
  320.       texflush() ;
  321. #endif
  322.       if (debugon > 5) printf("Font was resident.\n") ;
  323.       goto scalethem ;
  324.    } else if (virtualfont(tft)) {
  325.       if (debugon > 5) printf("Font was virtual.\n") ;
  326.       goto scalethem ;
  327.    }
  328.    if (!(i=pkopen(tft, dpi))) { 
  329.       tfmload(tft, 1) ;
  330. scalethem:
  331.       for (i=0; i<cf->maxchars; i++)
  332.          tft->scaledwidth[i] = scalewidth(cf->chardesc[i].TFMwidth, tft->scaledsize) ;
  333.       return ;
  334.    }
  335. #ifdef POPRESTORE
  336.    TPSeop() ;
  337. #endif
  338.    TPSdf(cf->id) ;
  339.    if (dvibyte()!=247)
  340.       error("! bad pk file, expected pre") ;
  341.    if (dvibyte()!=89)
  342.       error("! bad version of pk file") ;
  343.    for(i=dvibyte(); i>0; i--)
  344.       j=dvibyte() ;
  345.    k = signedquad() >> 4 ;
  346.    if (k > tft->designsize + 2 || k < tft->designsize - 2)
  347.       error("design size mismatch") ;
  348.    signedquad() ;
  349.    signedquad() ;
  350.    signedquad() ;
  351. /*
  352.  *   Now we get down to the serious business of reading character definitions.
  353.  */
  354.    while ((cmd=dvibyte())!=245) {
  355.       if (cmd < 240) {
  356.          switch (cmd & 7) {
  357. case 0: case 1: case 2: case 3:
  358.             length = (cmd & 7) * 256 + dvibyte() - 8 ;
  359.             cc = dvibyte() ;
  360.             cd = cf->chardesc+cc ;
  361.             cd->TFMwidth = threebytes() ;
  362.             cd->pixelwidth = dvibyte() ;
  363.             cwidth = dvibyte() ;
  364.             cheight = dvibyte() ;
  365.             xoffset = signedbyte() ;
  366.             yoffset = signedbyte() ;
  367.             break ;
  368. case 4:
  369.             length = dvibyte() * 256 ;
  370.             length = length + dvibyte() - 13 ;
  371.             cc = dvibyte() ;
  372.             cd = cf->chardesc+cc ;
  373.             cd->TFMwidth = threebytes() ;
  374.             cd->pixelwidth = twobytes() ;
  375.             cwidth = twobytes() ;
  376.             cheight = twobytes() ;
  377.             xoffset = signedpair() ;
  378.             yoffset = signedpair() ;
  379.             break ;
  380. case 7:
  381.             length = signedquad() - 28 ;
  382.             cc = signedquad() ;
  383.             cd = cf->chardesc+cc ;
  384.             cd->TFMwidth = signedquad() ;
  385.             cd->pixelwidth = (signedquad() + 32768) >> 16 ;
  386.             signedquad() ;
  387.             cwidth = signedquad() ;
  388.             cheight = signedquad() ;
  389.             xoffset = signedquad() ;
  390.             yoffset = signedquad() ;
  391.             break ;
  392. case 5: case 6: default:
  393.             error("! lost sync in pk file (character too big)") ;
  394.             return ;
  395.          }
  396.          i = cheight * ((cwidth + 15) / 16) ;
  397.          p = tempbuf(length + 2 * i + 10) ;
  398.          if (i > 0) {
  399.             fread(p, 1, length, dvifile) ;
  400.             q = p + (length + 3) / 2 ;
  401.             unpack(p, q, cwidth, cheight, cmd) ;
  402.       } else {
  403.              cwidth = 1 ;
  404.              cheight = 1 ;
  405.              q = p ;
  406.              *q = ~0 ;
  407.           }
  408. /*
  409.  *   It's an ugly, ugly story, but now we need to byte-pack the word-packed
  410.  *   data.  Of course, we do this only if the data isn't already byte packed.
  411.  */
  412.          bytepack(q, cwidth, cheight) ;
  413.          i = cheight * ((cwidth + 7) / 8) ;
  414.          TPSdc(q, i, cwidth, cheight, xoffset, cheight - yoffset - 1, cd->pixelwidth, cc) ;
  415.       } else {
  416.          k = 0 ;
  417.          switch (cmd) {
  418. case 243:
  419.             k = dvibyte() ;
  420.             if (k > 127)
  421.                k -= 256 ;
  422. case 242:
  423.             k = k * 256 + dvibyte() ;
  424. case 241:
  425.             k = k * 256 + dvibyte() ;
  426. case 240:
  427.             k = k * 256 + dvibyte() ;
  428.             while (k-- > 0)
  429.                i = dvibyte() ;
  430.             break ;
  431. case 244:
  432.             k = signedquad() ;
  433.             break ;
  434. case 246:
  435.             break ;
  436. default:
  437.             error("! lost sync in pk file") ;
  438.          }
  439.       }
  440.    }
  441.    fclose(dvifile) ;
  442.    dvifile = readingpk ;
  443.    curpos = scurpos ;
  444.    virpos = svirpos ;
  445.    readingpk = NULL ;
  446.    for (i=0; i<cf->maxchars; i++)
  447.       tft->scaledwidth[i] = scalewidth(cf->chardesc[i].TFMwidth,
  448.               tft->scaledsize) ;
  449.    if (cf->dpi == cf->loadeddpi)
  450.       TPSdfe() ;
  451.    else
  452.       TPSdfes(cf->dpi, cf->loadeddpi) ;
  453. #ifdef POPRESTORE
  454.    TPSbop() ;
  455. #else
  456.    texflush() ;
  457. #endif
  458. }
  459.