home *** CD-ROM | disk | FTP | other *** search
- /*
- * loadfont.c of dvisw software package
- * loads a pk file into memory.
- */
- #include "structures.h"
- #include <strings.h>
- /*
- * These are the external routines we use.
- */
- extern void error() ;
- extern integer scalewidth() ;
- extern void tfmload() ;
- extern FILE *pksearch() ;
- extern void makefont() ;
- extern shalfword dvibyte() ;
- extern halfword twobytes() ;
- extern integer threebytes() ;
- extern integer signedquad() ;
- extern shalfword signedbyte() ;
- extern shalfword signedpair() ;
- extern integer signedtrio() ;
- extern void movmem(), cmpmem() ;
- extern void free() ;
- extern void unpack() ;
- extern void setstatus(), qstatus() ;
- extern void TPSinit(), TPSdf(), TPSdc(), TPSbop(), TPSeop() ;
- extern void texflush() ;
- extern void TPSdfe(), TPSrfe(), TPSdfes() ;
- extern void pswrite() ;
- extern int residentfont(), virtualfont() ;
- extern void add_header() ;
- /*
- * These are the external variables we use.
- */
- static quarterword *svirpos ;
- extern quarterword *virpos ;
- extern char temperrorbuf[] ;
- extern fontdesctype *fontlist, *curfnt ;
- extern integer dvimag ;
- extern FILE *pkfile ;
- extern FILE *dvifile ;
- extern integer curpos ;
- extern char *pkpath ;
- extern real pxlconv ;
- extern real screendpi ;
- #ifdef DEBUG
- extern int debugon ;
- #endif
- extern int *existsize ;
- FILE *readingpk ;
- integer scurpos ;
- integer curid ;
- int lastresortsizes[40] ;
- /*
- * We use mymalloc here.
- */
- void *mymalloc() ;
- void *tempbuf() ;
- char lastfile[200] ;
- extern TeXfontdesctype *TeXfontlist ;
- Boolean pkopen(tft, dpi)
- register TeXfontdesctype *tft ;
- int dpi ;
- {
- register char *d, *n ;
-
- n = tft->name ;
- if (*n==0) {
- n++ ;
- d = pkpath ;
- } else {
- d = n ;
- while (*n) n++ ;
- n++ ;
- }
- sprintf(lastfile, "%s.%dpk", n, dpi) ;
- sprintf(temperrorbuf, "Loading %s", lastfile) ;
- qstatus(temperrorbuf) ;
- {
- int del ;
- for (del=0; del<=1+dpi/500; del=del>0?-del:-del+1) {
- (void)sprintf(lastfile, "%s.%dpk", n, dpi + del) ;
- if (pkfile=pksearch(d, lastfile, n, dpi + del))
- goto fontfound ;
- }
- }
- if (d == pkpath) {
- (void)sprintf(lastfile, "%s.%dpk", n, dpi) ;
- makefont(n, (int)dpi) ;
- if (pkfile = pksearch(d, lastfile, n, dpi))
- goto fontfound ;
- }
- /*
- * If nothing above worked, then we get desparate. We attempt to
- * open the stupid font at one of a small set of predefined sizes,
- * and then use PostScript scaling to generate the correct size.
- *
- * We much prefer scaling up to scaling down, since scaling down
- * can omit character features, so we try the larger sizes first,
- * and then work down.
- */
- {
- int i, j ;
-
- if (lastresortsizes[0] && dpi < 30000) {
- for (i=0; lastresortsizes[i] < dpi; i++) ;
- for (j = i-1; j >= 0; j--) {
- (void)sprintf(lastfile, "%s.%dpk", n, lastresortsizes[j]) ;
- if (pkfile=pksearch(d, lastfile, n, lastresortsizes[j])) {
- dpi = lastresortsizes[j] ;
- tft->loaded->alreadyscaled = 0 ;
- goto sfontfound ;
- }
- }
- for (j = i; lastresortsizes[j] < 30000; j++) {
- (void)sprintf(lastfile, "%s.%dpk", n, lastresortsizes[j]) ;
- if (pkfile=pksearch(d, lastfile, n, lastresortsizes[j])) {
- dpi = lastresortsizes[j] ;
- tft->loaded->alreadyscaled = 0 ;
- goto sfontfound ;
- }
- }
- }
- }
- strcat(temperrorbuf, " [blocks]") ;
- qstatus(temperrorbuf) ;
- return 0 ;
- sfontfound: ;
- #ifdef DEBUG
- strcat(temperrorbuf, " [scaled]") ;
- qstatus(temperrorbuf) ;
- if (debugon > 1)
- printf("Had to scale %d to %d\n", dpi, tft->loaded->dpi) ;
- #endif
- fontfound:
- readingpk = dvifile ;
- scurpos = curpos ;
- svirpos = virpos ;
- virpos = 0 ;
- dvifile = pkfile ;
- tft->loaded->loadeddpi = dpi ;
- return(1) ;
- }
- /*
- * This routine compares two strings in sucession, for font names.
- */
- short str2cmp(a, b)
- register char *a, *b ;
- {
- while (*a!=0 && *a==*b) {
- a++ ; b++ ;
- }
- if (*a!=0 || *b!=0)
- return(0) ;
- a++ ; b++ ;
- while (*a!=0 && *a==*b) {
- a++ ; b++ ;
- }
- return (*a==0 && *b==0) ;
- }
- void bytepack(p, w, h)
- register char *p ;
- register int w, h ;
- {
- register char *q ;
- register int i ;
-
- w = (w + 7) / 8 ;
- if ((w & 1) == 0)
- return ;
- q = p + w ;
- p = q + 1 ;
- while (h > 1) {
- for (i=w; i>0; i--)
- *q++ = *p++ ;
- p++ ;
- h-- ;
- }
- }
- /*
- * Now our loadfont routine.
- */
- void loadfont(tft)
- register TeXfontdesctype *tft ;
- {
- register fontdesctype *cf ;
- register chardesctype *cd ;
- register integer k ;
- register integer length ;
- register integer cmd ;
- register integer i, j ;
- register integer cc ;
- register integer scaledsize = tft->scaledsize ;
- register integer cheight, cwidth ;
- register integer xoffset, yoffset ;
- register integer dpi ;
- register shalfword *p, *q ;
- int fontwidths[256] ;
- /*
- * First, we scan through the linked list of fonts in memory, looking
- * for one that matches ours.
- */
- dpi = pxlconv * (float)scaledsize / tft->designsize + 0.5 ;
- /*
- * Now we check to see if that value is close to some other value.
- * Close is within one. If so, we load that size. There should
- * never be an error of more than one; the only errors are due to
- * floating point and magnifications being only valid to about three
- * sig digits.
- */
- for (i=0; existsize[i] < dpi; i++) ;
- if (existsize[i] == dpi + 1)
- dpi = existsize[i] ;
- else if (existsize[i-1] == dpi - 1)
- dpi = existsize[i-1] ;
- if (debugon > 5)
- printf("Looking for %s %ld %ld\n", tft->name+1, tft->scaledsize, dpi) ;
- for (cf=fontlist; cf!=NULL; cf=cf->next) {
- if (cf->dpi==dpi && str2cmp(cf->name, tft->name))
- break ;
- }
- if (cf!=NULL) {
- if (debugon > 5)
- printf("Found: %s\n", cf->name+1) ;
- tft->loaded = cf ;
- for (i=0; i<cf->maxchars; i++)
- tft->scaledwidth[i] = scalewidth(cf->chardesc[i].TFMwidth,
- tft->scaledsize) ;
- if (cf->virtual) {
- fontmaptype *fm ;
- for (fm = cf->localfonts; fm; fm = fm->next) {
- tft = fm->tdesc ;
- tft->scaledsize = scalewidth(scaledsize, tft->origssize) ;
- }
- }
- return ;
- }
- if (debugon > 5) printf("Not found.\n") ;
- /*
- * Didn't find any, we allocate a new fontdesc.
- */
- i = 0 ;
- while (tft->name[i++]!=0) ;
- while (tft->name[i++]!=0) ;
- cf = mymalloc(sizeof(fontdesctype)+i, MEMF_CLEAR) ;
- curfnt = cf ;
- cf->chardesc = mymalloc(sizeof(chardesctype) * 256, MEMF_CLEAR) ;
- cf->maxchars = 256 ;
- while (i >= 0) {
- cf->name[i] = tft->name[i] ;
- i-- ;
- }
- tft->loaded = cf ;
- cf->next = fontlist ;
- fontlist = cf ;
- cf->dpi = dpi ;
- cf->id = curid++ ;
- cf->resfont = NULL ;
- if (residentfont(tft)) {
- float fontscale ;
- struct resfont *rf = cf->resfont ;
- static int firstPSfont = 1 ;
- char num[50] ;
- char nfn[10] ;
-
- #ifdef POPRESTORE
- TPSeop() ;
- #endif
- if (firstPSfont) {
- add_header("texps.pro") ;
- firstPSfont = 0 ;
- }
- for (i=0; i<256; i++)
- fontwidths[i] = 0 ;
- for (i=0; i<cf->maxchars; i++)
- fontwidths[i] = cf->chardesc[i].pixelwidth ;
- sprintf(nfn, "Q%ld", curid-1) ;
- if (rf->downloadheader) {
- char *cp = rf->downloadheader ;
- char *q ;
-
- while (1) {
- q = cp ;
- while (*cp && *cp != ' ')
- cp++ ;
- if (*cp) {
- *cp = 0 ;
- add_header(q) ;
- *cp++ = ' ' ;
- } else {
- add_header(q) ;
- break ;
- }
- }
- }
- pswrite(" /") ;
- pswrite(nfn) ;
- pswrite(" /") ;
- pswrite(nfn) ;
- for (i=255; i>=0; i--) {
- sprintf(num, " %d", fontwidths[i]) ;
- pswrite(num) ;
- }
- pswrite(" {") ;
- if (rf->specialinstructions)
- pswrite(rf->specialinstructions) ;
- pswrite("} 256 ") ;
- fontscale = tft->scaledsize / 655360.0 ;
- fontscale *= dvimag / 7200.0 ;
- fontscale *= screendpi ;
- sprintf(num, "%f ", fontscale) ;
- pswrite(num) ;
- pswrite("/") ;
- pswrite(rf->PSname) ;
- pswrite(" rf ") ;
- TPSrfe(curid-1) ;
- #ifdef POPRESTORE
- TPSbop() ;
- #else
- texflush() ;
- #endif
- if (debugon > 5) printf("Font was resident.\n") ;
- goto scalethem ;
- } else if (virtualfont(tft)) {
- if (debugon > 5) printf("Font was virtual.\n") ;
- goto scalethem ;
- }
- if (!(i=pkopen(tft, dpi))) {
- tfmload(tft, 1) ;
- scalethem:
- for (i=0; i<cf->maxchars; i++)
- tft->scaledwidth[i] = scalewidth(cf->chardesc[i].TFMwidth, tft->scaledsize) ;
- return ;
- }
- #ifdef POPRESTORE
- TPSeop() ;
- #endif
- TPSdf(cf->id) ;
- if (dvibyte()!=247)
- error("! bad pk file, expected pre") ;
- if (dvibyte()!=89)
- error("! bad version of pk file") ;
- for(i=dvibyte(); i>0; i--)
- j=dvibyte() ;
- k = signedquad() >> 4 ;
- if (k > tft->designsize + 2 || k < tft->designsize - 2)
- error("design size mismatch") ;
- signedquad() ;
- signedquad() ;
- signedquad() ;
- /*
- * Now we get down to the serious business of reading character definitions.
- */
- while ((cmd=dvibyte())!=245) {
- if (cmd < 240) {
- switch (cmd & 7) {
- case 0: case 1: case 2: case 3:
- length = (cmd & 7) * 256 + dvibyte() - 8 ;
- cc = dvibyte() ;
- cd = cf->chardesc+cc ;
- cd->TFMwidth = threebytes() ;
- cd->pixelwidth = dvibyte() ;
- cwidth = dvibyte() ;
- cheight = dvibyte() ;
- xoffset = signedbyte() ;
- yoffset = signedbyte() ;
- break ;
- case 4:
- length = dvibyte() * 256 ;
- length = length + dvibyte() - 13 ;
- cc = dvibyte() ;
- cd = cf->chardesc+cc ;
- cd->TFMwidth = threebytes() ;
- cd->pixelwidth = twobytes() ;
- cwidth = twobytes() ;
- cheight = twobytes() ;
- xoffset = signedpair() ;
- yoffset = signedpair() ;
- break ;
- case 7:
- length = signedquad() - 28 ;
- cc = signedquad() ;
- cd = cf->chardesc+cc ;
- cd->TFMwidth = signedquad() ;
- cd->pixelwidth = (signedquad() + 32768) >> 16 ;
- signedquad() ;
- cwidth = signedquad() ;
- cheight = signedquad() ;
- xoffset = signedquad() ;
- yoffset = signedquad() ;
- break ;
- case 5: case 6: default:
- error("! lost sync in pk file (character too big)") ;
- return ;
- }
- i = cheight * ((cwidth + 15) / 16) ;
- p = tempbuf(length + 2 * i + 10) ;
- if (i > 0) {
- fread(p, 1, length, dvifile) ;
- q = p + (length + 3) / 2 ;
- unpack(p, q, cwidth, cheight, cmd) ;
- } else {
- cwidth = 1 ;
- cheight = 1 ;
- q = p ;
- *q = ~0 ;
- }
- /*
- * It's an ugly, ugly story, but now we need to byte-pack the word-packed
- * data. Of course, we do this only if the data isn't already byte packed.
- */
- bytepack(q, cwidth, cheight) ;
- i = cheight * ((cwidth + 7) / 8) ;
- TPSdc(q, i, cwidth, cheight, xoffset, cheight - yoffset - 1, cd->pixelwidth, cc) ;
- } else {
- k = 0 ;
- switch (cmd) {
- case 243:
- k = dvibyte() ;
- if (k > 127)
- k -= 256 ;
- case 242:
- k = k * 256 + dvibyte() ;
- case 241:
- k = k * 256 + dvibyte() ;
- case 240:
- k = k * 256 + dvibyte() ;
- while (k-- > 0)
- i = dvibyte() ;
- break ;
- case 244:
- k = signedquad() ;
- break ;
- case 246:
- break ;
- default:
- error("! lost sync in pk file") ;
- }
- }
- }
- fclose(dvifile) ;
- dvifile = readingpk ;
- curpos = scurpos ;
- virpos = svirpos ;
- readingpk = NULL ;
- for (i=0; i<cf->maxchars; i++)
- tft->scaledwidth[i] = scalewidth(cf->chardesc[i].TFMwidth,
- tft->scaledsize) ;
- if (cf->dpi == cf->loadeddpi)
- TPSdfe() ;
- else
- TPSdfes(cf->dpi, cf->loadeddpi) ;
- #ifdef POPRESTORE
- TPSbop() ;
- #else
- texflush() ;
- #endif
- }
-