This is loadfont.c in view mode; [Download] [Up]
/*
* loadfont.c of dvisw software package
* loads a pk file into memory.
*/
#include "structures.h"
#include <kpathsea/tex-file.h>
#include <kpathsea/tex-glyph.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 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[400] ;
extern TeXfontdesctype *TeXfontlist ;
Boolean pkopen(tft, dpi)
register TeXfontdesctype *tft ;
int dpi ;
{
register char *d, *n ;
char *name_ret ;
int dpi_ret ;
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) ;
#if 0
{
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 ;
}
}
#else
{
// char *this_name = concat (d, n);
char *this_name = xstrdup(n);
pkfile=pksearch(pkpath, this_name, &name_ret, dpi, &dpi_ret);
if (!pkfile || !(strcmp(this_name, name_ret) == 0))
{
(void)sprintf(temperrorbuf,
"Font %s%s not found, characters will be left blank.",
tft->name, n) ;
// dontmakefont = 1;
setstatus(temperrorbuf) ;
strcat(temperrorbuf, " [blocks]") ;
qstatus(temperrorbuf) ;
return 0 ;
}
else if (!kpse_bitmap_tolerance ((double) dpi_ret, (double) dpi))
{
(void)sprintf(temperrorbuf,
"Font %s at %d not found; scaling %d instead.",
n, dpi, dpi_ret) ;
dpi = dpi_ret ;
tft->loaded->alreadyscaled = 0 ;
setstatus(temperrorbuf) ;
}
if (this_name != name_ret)
free (this_name);
if (pkfile != NULL) goto fontfound;
goto fontfound;
}
#endif
/* Nothing below this gets executed. */
#if 0
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 ;
#endif /* 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
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.