home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
prog
/
c
/
post17s.lha
/
postfont.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-07
|
54KB
|
1,622 lines
/* PostScript interpreter file "postfont.c" - type 1 font routines
* (C) Adrian Aylward 1989, 1992
* V1.6 First source release
* V1.7 Rewrite hinting to interpolate between stems
* V1.7 Allow real values of blueshift and bluefuzz
*/
# include "post.h"
/* # define FONTDEBUG Enable font debugging (make file does this) */
/* Character string execution data */
# define charmaxdepth 10
# define charstacksize 24
static int charnest, charargn, charend, charaflag;
static float charstack[charstacksize], charargs[charstacksize];
static int charsbwlength, chardotsection, charflexn;
static float charsbw[4], charfptx[7], charfpty[7];
static float charssx, charssy, charsdx, charsdy, charadx, charady;
static float charcpx, charcpy;
static struct point lastpoint;
/* Default overshoot suppression */
# define defbluescale 0.05
/* Blues and Stems */
# define maxstem 20
struct stem
{ int type;
float s1, s2;
float z1, z2;
};
struct stform
{ int flag;
float scale;
int stemc;
struct stem stemv[maxstem];
};
static struct stform hstform, vstform;
# define maxblue 12
static int bluec;
static struct stem bluev[maxblue];
static float bluescale, blueshift, bluefuzz;
/* Routines */
extern void buildachar(int schar);
extern void charstring(struct object *token1, int depth);
extern void charpoint(struct point *ppoint);
extern void hintpoint(struct point *cpoint, struct point *ppoint);
extern void hintadjust(float *ps, float *pz, struct stform *pstform);
extern void setstems(struct stform *pstform, int num);
extern void setblues(void);
extern void charfill(void);
extern void charline(struct point *ppoint);
extern void setxbuf(int size);
/* Debugging procedures */
# ifdef FONTDEBUG
# define FDEBUGN(s, n) fdebugn(depth, s, n)
# else
# define FDEBUGN(s, n)
# endif
# ifdef FONTDEBUG
/* On the Amiga we can't redirect stderr, so use stdout instead */
# ifdef AMIGA
# ifdef stderr
# undef stderr
# endif
# define stderr stdout
# endif
/* Debug mode values (bits)
* 1 Trace charstring commands
* 2 Trace path points
* 4 Trace hints
* 8 Display blues
*/
int fontdebug;
/* setfontdebug */
void opsetfontdebug(void)
{ struct object *token1;
if (opernest < 1) error(errstackunderflow);
token1 = &operstack[opernest - 1];
if (token1->type != typeint) error(errtypecheck);
fontdebug = token1->value.ival;
opernest--;
}
/* Operator trace */
void fdebugn(int depth, char *sptr, int n)
{ int i;
if (fontdebug & 1)
{ if (depth == 0)
fprintf(stderr, ">>");
else
fprintf(stderr, "%d>", depth);
fprintf(stderr, " (%4.0f,%4.0f) %2d %-13s ",
charcpx, charcpy, charnest, sptr);
for (i = 0; i < n; i++)
fprintf(stderr, " %4.4g", charstack[i]);
fprintf(stderr, "\n");
}
}
# endif
/* Initialise type 1 fonts */
void initfont(void)
{ xbsize = 0;
# ifdef FONTDEBUG
systemop(opsetfontdebug, "setfontdebug");
# endif
}
/* Initialise type 1 font build data */
void initbuild(vmref fdref)
{ struct object token, *aptr;
struct stem blue;
int i;
/* Extract the build data */
fontmetrics = NULL;
if (dictget(fdref, &charname[charmetrics], &token, 0))
{ if (token.type != typedict) error(errinvalidfont);
fontmetrics = token.value.vref;
}
if (!dictget(fdref, &charname[charpainttype], &token, 0) ||
token.type != typeint ||
(token.value.ival != 0 && token.value.ival != 2))
error(errinvalidfont);
fontpainttype = token.value.ival;
if (fontpainttype != 0)
{ if (!dictget(fdref, &charname[charstrokewidth], &token, 0))
error(errinvalidfont);
if (token.type == typeint)
fontstrokewidth = token.value.ival;
else if (token.type == typereal)
fontstrokewidth = token.value.rval;
else
error(errinvalidfont);
}
if (!dictget(fdref, &charname[charcharstrings], &token, 0) ||
token.type != typedict)
error(errinvalidfont);
fontcharstrings = token.value.vref;
if (!dictget(fdref, &charname[charprivate], &token, 0) ||
token.type != typedict)
error(errinvalidfont);
fontprivate = token.value.vref;
if (dictget(fontprivate, &charname[charsubrs], &fontsubrs, 0))
{ if (fontsubrs.type != typearray) error(errinvalidfont);
}
else
fontsubrs.length = 0;
if (dictget(fontprivate, &charname[charleniv], &token, 0))
{ if (token.type != typeint || token.value.ival < 0)
error(errinvalidfont);
fontleniv = token.value.ival;
}
else
fontleniv = 4;
/* Extract the blues */
bluec = 0;
if (dictget(fontprivate, &charname[charbluevalues], &token, 0))
{ if (token.type != typearray ||
token.length > maxblue + 2 || (token.length & 1))
error(errinvalidfont);
i = token.length >> 1;
aptr = vmaptr(token.value.vref);
blue.type = -1;
while (i--)
{ token = *aptr++;
if (token.type != typeint) error(errinvalidfont);
blue.s1 = token.value.ival;
token = *aptr++;
if (token.type != typeint) error(errinvalidfont);
blue.s2 = token.value.ival;
bluev[bluec++] = blue;
blue.type = 1;
}
}
if (dictget(fontprivate, &charname[charotherblues], &token, 0))
{ if (token.type != typearray ||
token.length > maxblue - 2 || (token.length & 1))
error(errinvalidfont);
i = token.length >> 1;
aptr = vmaptr(token.value.vref);
blue.type = -1;
while (i--)
{ token = *aptr++;
if (token.type != typeint) error(errinvalidfont);
blue.s1 = token.value.ival;
token = *aptr++;
if (token.type != typeint) error(errinvalidfont);
blue.s2 = token.value.ival;
bluev[bluec++] = blue;
}
}
bluescale = defbluescale;
if (dictget(fontprivate, &charname[charbluescale], &token, 0))
{ if (token.type == typeint)
bluescale = token.value.ival;
else if (token.type == typereal)
bluescale = token.value.rval;
else
error(errinvalidfont);
}
blueshift = 7.0;
if (dictget(fontprivate, &charname[charblueshift], &token, 0))
{ if (token.type == typeint)
blueshift = token.value.ival;
else if (token.type == typereal)
blueshift = token.value.rval;
else
error(errinvalidfont);
}
bluefuzz = 1.0;
if (dictget(fontprivate, &charname[charbluefuzz], &token, 0))
{ if (token.type == typeint)
bluefuzz = token.value.ival;
else if (token.type == typereal)
bluefuzz = token.value.rval;
else
error(errinvalidfont);
}
# ifdef FONTDEBUG
if (fontdebug & 8)
fprintf(stderr, "-> BlueScale %6.4f BlueShift %6.4f BlueFuzz %6.4f\n",
bluescale, blueshift, bluefuzz);
# endif
}
/* Build a character */
void buildchar(int schar)
{ struct object token1, token, *aptr;
struct point width, ll, ur, *ppoint;
float fdx, fdy;
int i;
/* If the matrix is not rotated we can apply the hints */
for (i = 0; i < 4; i++)
if (fabs(gstate.ctm[i]) < .0001) gstate.ctm[i] = 0.0;
hstform.flag = 0;
if (gstate.ctm[0] != 0.0 && gstate.ctm[2] == 0.0)
{ hstform.flag = -1;
hstform.scale = gstate.ctm[0];
}
else if (gstate.ctm[1] != 0.0 && gstate.ctm[3] == 0.0)
{ hstform.flag = 1;
hstform.scale = gstate.ctm[1];
}
vstform.flag = 0;
if (gstate.ctm[0] == 0.0 && gstate.ctm[2] != 0.0)
{ vstform.flag = -1;
vstform.scale = gstate.ctm[2];
}
else if (gstate.ctm[1] == 0.0 && gstate.ctm[3] != 0.0)
{ vstform.flag = 1;
vstform.scale = gstate.ctm[3];
}
setblues();
/* Look up the name in the encoding vector */
if (schar < fontencodlen)
{ token1 = vmaptr(fontencoding)[schar];
if (token1.type != typename) error(errinvalidfont);
}
else
token1 = charname[charnotdef];
/* See if there is a metrics entry for this character */
charsbwlength = 0;
charsbw[0] = charsbw[1] = charsbw[2] = charsbw[3] = 0.0;
if (fontmetrics != NULL && dictget(fontmetrics, &token1, &token, 0))
{ if (token.type == typearray)
{ if (token.length != 2 && token.length != 4)
error(errinvalidfont);
i = token.length;
aptr = vmaptr(token.value.vref);
}
else
{ i = 1;
aptr = &token;
}
charsbwlength = i;
for (i = 0; i < charsbwlength; i++)
{ token = *aptr++;
if (token.type == typeint)
charsbw[i] = token.value.ival;
else if (token.type == typereal)
charsbw[i] = token.value.rval;
else
error(errinvalidfont);
}
if (charsbwlength == 1)
{ charsbw[2] = charsbw[0];
charsbw[0] = 0.0;
}
else if (charsbwlength == 2)
{ charsbw[2] = charsbw[1];
charsbw[1] = 0.0;
}
}
/* Execute the character string */
charnest = charargn = 0;
charend = charaflag = chardotsection = 0;
charsdx = charsdy = 0.0;
charssx = charcpx = 0.0;
charssy = charcpy = 0.0;
fdx = gstate.ctm[4];
fdy = gstate.ctm[5];
gstate.ctm[4] = 0.0;
gstate.ctm[5] = 0.0;
charflexn = -1;
lastpoint.type = 0;
hstform.stemc = vstform.stemc = 0;
# ifdef FONTDEBUG
if (fontdebug & 1)
fprintf(stderr, "/>%.*s\n",
vmnptr(token1.value.vref)->length,
vmnptr(token1.value.vref)->string);
# endif
if (dictget(fontcharstrings, &token1, &token, 0) ||
dictget(fontcharstrings, &charname[charnotdef], &token, 0))
charstring(&token, 0);
/* Set the character width */
width.type = 0;
width.x = charsbw[2];
width.y = charsbw[3];
dtransform(&width, gstate.ctm);
istate.pfcrec->width = width;
/* For outlined fonts find the stroke path */
gstate.flatness = 0.2;
if (fontpainttype != 0)
{ gstate.linewidth = fontstrokewidth;
if (istate.type == 1 ||
istate.type == 2 && gstate.cacheflag ||
istate.type == 3)
{ flattenpath();
strokepath(0);
}
}
/* Calculate the bounding box and see if we can use the cache */
if (istate.type >= 2)
{ i = gstate.pathend - gstate.pathbeg;
ppoint = &patharray[gstate.pathbeg];
if (i != 0)
{ ll = ur = *ppoint;
while (--i)
{ ppoint++;
if (ppoint->x < ll.x) ll.x = ppoint->x;
if (ppoint->x > ur.x) ur.x = ppoint->x;
if (ppoint->y < ll.y) ll.y = ppoint->y;
if (ppoint->y > ur.y) ur.y = ppoint->y;
}
}
else
{ ll.type = 0;
ll.x = 0.0;
ll.y = 0.0;
ur = ll;
}
setcachedevice(&ll, &ur, 1);
if (gstate.cacheflag)
{ fdx = gstate.ctm[4];
fdy = gstate.ctm[5];
}
}
/* Adjust all the path coordinates */
i = gstate.pathend - gstate.pathbeg;
ppoint = &patharray[gstate.pathbeg];
while (i--)
{ ppoint->x += fdx;
ppoint->y += fdy;
ppoint++;
}
/* Fill the path */
if (istate.type < 2)
charpath();
else if (istate.type == 2 && !gstate.cacheflag)
gstate.pathend = gstate.pathbeg;
else
{ closepath(ptclosei);
if (fontpainttype == 0) flattenpath();
if (gstate.cacheflag)
charfill();
else
{ setupfill();
fill(gstate.pathbeg, gstate.pathend, -1);
}
gstate.pathend = gstate.pathbeg;
}
}
/* Build an accent or character */
void buildachar(int schar)
{ struct object token1, token;
/* Look up the name in the standard encoding vector */
token1 = stdencoding[schar];
if (token1.type != typename) error(errinvalidfont);
/* Execute the character string */
charnest = 0;
charend = 0;
chardotsection = 0;
charssx = charcpx;
charssy = charcpy;
lastpoint.type = 0;
hstform.stemc = vstform.stemc = 0;
# ifdef FONTDEBUG
if (fontdebug & 1)
fprintf(stderr, "/>%.*s\n",
vmnptr(token1.value.vref)->length,
vmnptr(token1.value.vref)->string);
# endif
if (dictget(fontcharstrings, &token1, &token, 0)) charstring(&token, 0);
}
/* Interpret a character string */
void charstring(struct object *token1, int depth)
{ struct object token;
struct point point;
char *sptr;
float dx1, dy1, dx2, dy2, dx3, dy3, dmin;
int length, erand, cx, ch, num, i;
int achar, bchar;
if (token1->type != typestring) error(errinvalidfont);
length = token1->length;
if (length == 0) return;
sptr = vmsptr(token1->value.vref);
/* Skip leading random bytes */
i = fontleniv;
if (length < i) error(errinvalidfont);
length -= i;
erand = einitchar;
while (i--)
{ cx = *((unsigned char *) (sptr++));
erand = ((erand + cx) * ec1 + ec2) & emask;
}
/* Interpret */
while (length--)
{ cx = *((unsigned char *) (sptr++));
ch = cx ^ (erand >> eshift);
erand = ((erand + cx) * ec1 + ec2) & emask;
/* Operator */
if (ch < 32)
{ switch (ch)
{ case 21: /* rmoveto */
FDEBUGN("rmoveto", 2);
if (charnest < 2) error(errinvalidfont);
dx1 = charstack[0];
dy1 = charstack[1];
rmoveto: point.type = ptmove;
movline: point.x = charcpx = charcpx + dx1;
point.y = charcpy = charcpy + dy1;
if (charflexn < 0) charpoint(&point);
charnest = 0;
break;
case 22: /* hmoveto */
FDEBUGN("hmoveto", 1);
if (charnest < 1) error(errinvalidfont);
dx1 = charstack[0];
dy1 = 0.0;
goto rmoveto;
case 4: /* vmoveto */
FDEBUGN("vmoveto", 1);
if (charnest < 1) error(errinvalidfont);
dx1 = 0.0;
dy1 = charstack[0];
goto rmoveto;
case 5: /* rlineto */
FDEBUGN("rlineto", 2);
if (charnest < 2) error(errinvalidfont);
dx1 = charstack[0];
dy1 = charstack[1];
rlineto: point.type = ptline;
if (gstate.pathbeg == gstate.pathend)
error(errinvalidfont);
goto movline;
case 6: /* hlineto */
FDEBUGN("hlineto", 1);
if (charnest < 1) error(errinvalidfont);
dx1 = charstack[0];
dy1 = 0.0;
goto rlineto;
case 7: /* vlineto */
FDEBUGN("vlineto", 1);
if (charnest < 1) error(errinvalidfont);
dx1 = 0.0;
dy1 = charstack[0];
goto rlineto;
case 8: /* rrcurveto */
FDEBUGN("rrcurveto", 6);
if (charnest < 6) error(errinvalidfont);
dx1 = charstack[0];
dy1 = charstack[1];
dx2 = charstack[2];
dy2 = charstack[3];
dx3 = charstack[4];
dy3 = charstack[5];
rrcurveto: point.type = ptcurve;
if (gstate.pathbeg == gstate.pathend)
error(errinvalidfont);
point.x = charcpx + dx1;
point.y = charcpy + dy1;
charpoint(&point);
point.x += dx2;
point.y += dy2;
charpoint(&point);
charcpx = point.x = point.x + dx3;
charcpy = point.y = point.y + dy3;
charpoint(&point);
charnest = 0;
break;
case 30: /* vhcurveto */
FDEBUGN("vhcurveto", 4);
if (charnest < 4) error(errinvalidfont);
dx1 = 0.0;
dy1 = charstack[0];
dx2 = charstack[1];
dy2 = charstack[2];
dx3 = charstack[3];
dy3 = 0.0;
goto rrcurveto;
case 31: /* hvcurveto */
FDEBUGN("hvcurveto", 4);
if (charnest < 4) error(errinvalidfont);
dx1 = charstack[0];
dy1 = 0.0;
dx2 = charstack[1];
dy2 = charstack[2];
dx3 = 0.0;
dy3 = charstack[3];
goto rrcurveto;
case 9: /* closepath */
FDEBUGN("closepath", 0);
closepath(ptclosex);
charnest = 0;
break;
case 10: /* callsubr */
FDEBUGN("callsubr", charnest);
if (charnest < 1) error(errinvalidfont);
i = itrunc(charstack[charnest - 1]);
if (i < 0 || i > fontsubrs.length) error(errinvalidfont);
charnest--;
token = vmaptr(fontsubrs.value.vref)[i];
if (depth + 1 == charmaxdepth) error(errinvalidfont);
charstring(&token, depth + 1);
break;
case 11: /* return */
FDEBUGN("return", 0);
if (depth == 0) error(errinvalidfont);
return;
case 14: /* endchar */
FDEBUGN("endchar", 0);
charnest = 0;
charend = 1;
break;
case 13: /* hsbw */
FDEBUGN("hsbw", 2);
if (charnest < 2) error(errinvalidfont);
dx1 = charstack[0];
dy1 = 0.0;
dx2 = charstack[1];
dy2 = 0.0;
sbw: if (charaflag == 1)
{ charcpx = dx1 + charsdx;
charcpy = dy1 + charsdy;
charadx += charcpx;
charady += charcpy;
}
else if (charaflag == 2)
{ charcpx = charadx;
charcpy = charady;
}
else
{ if (charsbwlength == 0)
{ charsbw[0] = dx1;
charsbw[1] = dy1;
charsbw[2] = dx2;
charsbw[3] = dy2;
}
else if (charsbwlength == 1)
{ charsbw[0] = dx1;
charsbw[1] = dy1;
}
charcpx = charsbw[0];
charcpy = charsbw[1];
charsdx = charcpx - dx1;
charsdy = charcpy - dy1;
}
charssx = charcpx;
charssy = charcpy;
charnest = 0;
break;
case 1: /* hstem */
FDEBUGN("hstem", 2);
if (charnest < 2) error(errinvalidfont);
dy1 = charssy + charstack[0];
dy2 = dy1 + charstack[1];
if (dy1 > dy2)
{ dy3 = dy1;
dy1 = dy2;
dy2 = dy3;
}
if (vstform.stemc < maxstem)
{ vstform.stemv[vstform.stemc].s1 = dy1;
vstform.stemv[vstform.stemc].s2 = dy2;
setstems(&vstform, 1);
}
charnest = 0;
break;
case 3: /* vstem */
FDEBUGN("vstem", 2);
if (charnest < 2) error(errinvalidfont);
dx1 = charssx + charstack[0];
dx2 = dx1 + charstack[1];
if (dx1 > dx2)
{ dx3 = dx1;
dx1 = dx2;
dx2 = dx3;
}
if (hstform.stemc < maxstem)
{ hstform.stemv[hstform.stemc].s1 = dx1;
hstform.stemv[hstform.stemc].s2 = dx2;
setstems(&hstform, 1);
}
charnest = 0;
break;
case 15: /* moveto +++ UNDOCUMENTED, OBSOLETE +++ */
FDEBUGN("MOVETO", 2);
if (charnest < 2) error(errinvalidfont);
dx1 = charstack[0] + charssx - charcpx;
dy1 = charstack[1] + charssy - charcpy;
goto rmoveto;
case 16: /* lineto +++ UNDOCUMENTED, OBSOLETE +++ */
FDEBUGN("LINETO", 2);
if (charnest < 2) error(errinvalidfont);
dx1 = charstack[0] + charssx - charcpx;
dy1 = charstack[1] + charssy - charcpy;
goto rlineto;
case 17: /* curveto +++ UNDOCUMENTED, OBSOLETE +++ */
FDEBUGN("CURVETO", 6);
if (charnest < 6) error(errinvalidfont);
dx1 = charstack[0] + charssx - charcpx;
dy1 = charstack[1] + charssy - charcpy;
dx2 = charstack[2] + charssx - charcpx;
dy2 = charstack[3] + charssy - charcpy;
dx3 = charstack[4] + charssx - charcpx;
dy3 = charstack[5] + charssy - charcpy;
goto rrcurveto;
case 12: /* ... */
if (length == 0) error(errinvalidfont);
length--;
cx = *((unsigned char *) (sptr++));
ch = cx ^ (erand >> eshift);
erand = ((erand + cx) * ec1 + ec2) & emask;
switch (ch)
{ case 0: /* dotsection */
FDEBUGN("dotsection", 0);
chardotsection = !chardotsection;
charnest = 0;
break;
case 1: /* vstem3 */
FDEBUGN("vstem3", 6);
if (charnest < 6) error(errinvalidfont);
hstform.stemc = 0;
hstform.stemv[0].s1 =
charssx + charstack[0];
hstform.stemv[0].s2 =
charssx + charstack[0] + charstack[1];
hstform.stemv[1].s1 =
charssx + charstack[2];
hstform.stemv[1].s2 =
charssx + charstack[2] + charstack[3];
hstform.stemv[2].s1 =
charssx + charstack[4];
hstform.stemv[2].s2 =
charssx + charstack[4] + charstack[5];
setstems(&hstform, 3);
charnest = 0;
break;
case 2: /* hstem3 */
FDEBUGN("hstem3", 6);
if (charnest < 6) error(errinvalidfont);
vstform.stemc = 0;
vstform.stemv[0].s1 =
charssy + charstack[0];
vstform.stemv[0].s2 =
charssy + charstack[0] + charstack[1];
vstform.stemv[1].s1 =
charssy + charstack[2];
vstform.stemv[1].s2 =
charssy + charstack[2] + charstack[3];
vstform.stemv[2].s1 =
charssy + charstack[4];
vstform.stemv[2].s2 =
charssy + charstack[4] + charstack[5];
setstems(&vstform, 3);
charnest = 0;
break;
case 6: /* seac */
FDEBUGN("seac", 5);
if (charnest < 5) error(errinvalidfont);
bchar = itrunc(charstack[3]);
achar = itrunc(charstack[4]);
if (charaflag) error(errinvalidfont);
charadx = charstack[1];
charady = charstack[2];
charaflag = 1;
charcpx = 0.0;
charcpy = 0.0;
buildachar(bchar);
charaflag = 2;
charcpx = charadx;
charcpy = charady;
buildachar(achar);
charnest = 0;
charend = 1;
break;
case 7: /* sbw */
FDEBUGN("sbw", 4);
if (charnest < 4) error(errinvalidfont);
dx1 = charstack[0];
dy1 = charstack[1];
dx2 = charstack[2];
dy2 = charstack[3];
goto sbw;
case 12: /* div */
FDEBUGN("div", charnest);
if (charnest < 2) error(errinvalidfont);
charstack[charnest - 2] /=
charstack[charnest - 1];
charnest--;
break;
case 16: /* callothersubr */
FDEBUGN("callothersubr", charnest);
if (charnest < 2) error(errinvalidfont);
i = itrunc(charstack[charnest - 1]);
num = itrunc(charstack[charnest - 2]);
charnest -= 2;
if (num < 0 || num > charnest)
error(errinvalidfont);
charargn = 0;
while (num--)
charargs[charargn++] = charstack[--charnest];
switch (i)
{ case 0: /* Flex */
if (charargn != 3)
error(errinvalidfont);
dmin = fabs(charargs[2]) / 100.0;
charargn--;
if (charflexn != 7)
error(errinvalidfont);
charflexn = -1;
point.x = charfptx[3] - charfptx[0];
point.y = charfpty[3] - charfpty[0];
if
(fabs(charfptx[3] - charcpx) > 20.0 &&
fabs(charfpty[3] - charcpy) > 20.0)
goto flexc;
if
(fabs(charfptx[3] - charfptx[6]) > 20.0 &&
fabs(charfpty[3] - charfpty[6]) > 20.0)
goto flexc;
dtransform(&point, gstate.ctm);
point.x = fabs(point.x);
point.y = fabs(point.y);
if ((point.x < .01 && point.y < dmin) ||
(point.y < .01 && point.x < dmin))
{ point.type = ptline;
point.x = charfptx[6];
point.y = charfpty[6];
charpoint(&point);
break;
}
flexc: point.type = ptcurve;
for (i = 1; i < 7; i++)
{ point.x = charfptx[i];
point.y = charfpty[i];
charpoint(&point);
}
break;
case 1: /* Flex */
if (charargn != 0)
error(errinvalidfont);
if (charflexn >= 0)
error(errinvalidfont);
charflexn = 0;
break;
case 2: /* Flex */
if (charargn != 0)
error(errinvalidfont);
if (charflexn > 6)
error(errinvalidfont);
charfptx[charflexn] = charcpx;
charfpty[charflexn] = charcpy;
charflexn++;
break;
case 3: /* Hint replacement */
hstform.stemc = vstform.stemc = 0;
break;
}
break;
case 17: /* pop */
FDEBUGN("pop", 0);
if (charnest == charstacksize || charargn == 0)
error(errinvalidfont);
charstack[charnest++] = charargs[--charargn];
break;
case 32: /* pushcurrentpoint */
/* +++ UNDOCUMENTED, OBSOLETE +++ */
FDEBUGN("PUSHCURRENTPOINT", 0);
if (charnest + 2 > charstacksize)
error(errinvalidfont);
charstack[charnest++] = charcpx;
charstack[charnest++] = charcpy;
break;
case 33: /* setcurrentpoint */
FDEBUGN("setcurrentpoint", 2);
if (charnest < 2) error(errinvalidfont);
charcpx = charstack[0];
charcpy = charstack[1];
charnest = 0;
break;
default:
error(errinvalidfont);
}
break;
default:
error(errinvalidfont);
}
if (charend) return;
}
/* Number */
else
{ if (ch < 247)
num = ch - 139;
else if (ch == 255)
{ if (length < 4) error(errinvalidfont);
length -= 4;
num = 0;
i = 4;
while (i--)
{ cx = *((unsigned char *) (sptr++));
ch = cx ^ (erand >> eshift);
erand = ((erand + cx) * ec1 + ec2) & emask;
num = (num << 8) | ch;
}
}
else
{ if (length == 0) error(errinvalidfont);
length--;
num = ch;
cx = *((unsigned char *) (sptr++));
ch = cx ^ (erand >> eshift);
erand = ((erand + cx) * ec1 + ec2) & emask;
if (num < 251)
num = (num - 247) * 256 + ch + 108;
else
num = -((num - 251) * 256 + ch + 108);
}
if (charnest == charstacksize) error(errinvalidfont);
charstack[charnest++] = num;
}
}
}
/* Add a point to the character path */
void charpoint(struct point *ppoint)
{ struct point point;
/* Transform to device space, rounding to multiples of 1/16 */
point = *ppoint;
dtransform(&point, gstate.ctm);
point.x = floor(point.x * 16.0 + 0.5) / 16.0;
point.y = floor(point.y * 16.0 + 0.5) / 16.0;
# ifdef FONTDEBUG
if (fontdebug & 2)
fprintf(stderr, ".> (%4.0f,%4.0f) [%7.2f,%7.2f]\n",
ppoint->x, ppoint->y, point.x, point.y);
# endif
/* For moves, the hinting is deferred, in case the hints have changed */
if (lastpoint.type == ptmove)
hintpoint(&lastpoint, &patharray[gstate.pathend - 1]);
lastpoint = *ppoint;
/* Add the point to the path */
if (point.type == ptmove)
{ closepath(ptclosei);
if (gstate.pathbeg != gstate.pathend &&
patharray[gstate.pathend - 1].type == ptmove)
gstate.pathend--;
}
checkpathsize(gstate.pathend + 1);
patharray[gstate.pathend++] = point;
/* For points other than a move, the hinting is done immediately */
if (lastpoint.type != ptmove)
hintpoint(&lastpoint, &patharray[gstate.pathend - 1]);
}
/* Adjust the coordinates of a point according to the hints */
void hintpoint(struct point *cpoint, struct point *ppoint)
{ if (hstform.flag < 0)
hintadjust(&cpoint->x, &ppoint->x, &hstform);
else if (hstform.flag > 0)
hintadjust(&cpoint->x, &ppoint->y, &hstform);
if (vstform.flag < 0)
hintadjust(&cpoint->y, &ppoint->x, &vstform);
else if (vstform.flag > 0)
hintadjust(&cpoint->y, &ppoint->y, &vstform);
}
/* Adjust a single coordinate according to the hints */
void hintadjust(float *ps, float *pz, struct stform *pstform)
{ struct stem *stem1, *stem2, *pstem, *pblue;
float ss, zz, f, d;
int i;
if (chardotsection) return;
/* Locate it relative to the stems. Loop to find the highest stem not
* above us and the lowest not below us. Then we can work out where
* we are */
stem1 = stem2 = NULL;
ss = *ps;
pstem = &pstform->stemv[0];
i = pstform->stemc;
while (i--)
{ if (pstem->s1 <= ss)
if (stem1 == NULL || pstem->s1 > stem1->s1) stem1 = pstem;
if (pstem->s2 >= ss)
if (stem2 == NULL || pstem->s2 < stem2->s2) stem2 = pstem;
pstem++;
}
/* If it is not within a stem, see if it is within an alignment zone */
if (stem1 == NULL || stem2 == NULL)
if (pstform == &vstform)
{ pblue = bluev;
i = bluec;
while (i--)
if (ss >= pblue->s1 - bluefuzz && ss <= pblue->s2 + bluefuzz)
{ f = fabs(pstform->scale);
if (pblue->type < 0)
{ d = pblue->s2 - ss;
zz = pblue->z2;
}
else
{ d = ss - pblue->s1;
zz = pblue->z1;
}
if (f < bluescale || (d < blueshift && d * f < 0.5))
goto hint;
}
}
/* No stems */
if (stem1 == NULL && stem2 == NULL) return;
/* Above all stems */
if (stem1 == NULL)
{ zz = stem2->z2 + (ss - stem2->s2) * pstform->scale;
goto hint;
}
/* Below all stems */
if (stem2 == NULL)
{ zz = stem1->z1 + (ss - stem1->s1) * pstform->scale;
goto hint;
}
/* In case we have averlapping stems */
if (stem2->s1 == stem1->s2) return;
/* Between two stems */
if (stem1 != stem2)
{ zz = stem1->z2 +
(ss - stem1->s2) *
(stem2->z1 - stem1->z2) /
(stem2->s1 - stem1->s2);
goto hint;
}
/* At the bottom of a stem */
if (stem1->s1 == ss)
{ zz = stem1->z1;
goto hint;
}
/* At the top of a stem */
if (stem1->s2 == ss)
{ zz = stem1->z2;
goto hint;
}
/* Within a stem */
zz = stem1->z1 +
(ss - stem1->s1) *
(stem1->z2 - stem1->z1) /
(stem1->s2 - stem1->s1);
hint:
zz = floor(zz * 16.0 + 0.5) / 16.0;
# ifdef FONTDEBUG
if (fontdebug & 4)
fprintf(stderr, "=> Hint %c %6.2f -> %6.2f\n",
(pstform == &hstform ? 'X' : 'Y'), *pz, zz);
# endif
*pz = zz;
}
/* Set the coordinates of the stems */
void setstems(struct stform *pstform, int num)
{ struct stem *pstem, *pblue;
float scale, w1, w2, z1, z2, zz, w, f, d;
int iw, i;
if (pstform->flag == 0) return;
scale = pstform->scale;
pstem = &pstform->stemv[pstform->stemc];
pstform->stemc += num;
while (num--)
{
/* Regularise the width. Don't adjust very small widths */
z1 = pstem->s1 * scale;
z2 = pstem->s2 * scale;
w1 = fabs(z2 - z1);
if (w1 < 0.5)
{ w2 = 0.75;
iw = 1;
}
else
{ w2 = floor(w1 + 0.5);
iw = w2;
w2 -= 0.25;
}
if (z1 < z2)
w = w2;
else
w = -w2;
/* If a stem is not subject to alignment, odd widths are centred
* on 0.4375 pixels, even widths on 0.9365 pixels. */
if (w2 > 0.5)
{ zz = (z1 + z2) / 2.0;
if (iw & 1)
zz = floor(zz + 0.0625) + 0.4375;
else
zz = floor(zz + 0.5625) - 0.0625;
z1 = zz - w / 2.0;
z2 = zz + w / 2.0;
}
/* See if the stem is within an alignment zone. If it is within
* bluefuzz of exact alignment then align it. If it is within the
* alignment zone than align it if our scale is less than bluescale
* or the distance is less than blueshift and less than half a pixel;
* otherwise position relative to the alignment. If the stem is
* outside the alignment zone make sure it remains so
*/
if (pstform == &vstform)
{ pblue = bluev;
i = bluec;
while (i--)
{ if (pblue->type < 0)
{ if (fabs(pstem->s1 - pblue->s2) <= bluefuzz)
{ z1 = pblue->z2;
z2 = z1 + w;
break;
}
if (pstem->s1 < pblue->s2 &&
pstem->s1 >= pblue->s1 - bluefuzz)
{ z1 = pblue->z2;
f = fabs(scale);
d = pblue->s2 - pstem->s1;
if (!(f < bluescale ||
(d < blueshift && d * f < 0.5)))
z1 -= floor(d * scale * 16.0 + 0.5) / 16.0;
z2 = z1 + w;
break;
}
if (pstem->s1 > pblue->s2)
if (scale < 0 ? (z1 > pblue->z2) : (z1 < pblue->z2))
{ z1 = pblue->z2;
z2 = z1 + w;
}
}
else
{ if (fabs(pstem->s2 - pblue->s1) <= bluefuzz)
{ z2 = pblue->z1;
z1 = z2 - w;
break;
}
if (pstem->s2 > pblue->s1 &&
pstem->s2 <= pblue->s2 + bluefuzz)
{ z2 = pblue->z1;
f = fabs(scale);
d = pstem->s2 - pblue->s1;
if (!(f < bluescale ||
(d < blueshift && d * f < 0.5)))
z2 += floor(d * scale * 16.0 + 0.5) / 16.0;
z1 = z2 - w;
break;
}
if (pstem->s2 < pblue->s1)
if (scale < 0 ? (z2 < pblue->z1) : (z2 > pblue->z1))
{ z2 = pblue->z1;
z1 = z2 - w;
}
}
pblue++;
}
}
pstem->z1 = z1;
pstem->z2 = z2;
# ifdef FONTDEBUG
if (fontdebug & 4)
fprintf(stderr, "=> Stem %c [%7.2f, %7.2f] -> [%6.2f, %6.2f]\n",
(pstform == &vstform ? 'H' : 'V'),
pstem->s1, pstem->s2, z1, z2);
# endif
pstem++;
}
}
/* Set the coordinates of the blues */
void setblues(void)
{ struct stem *pblue;
float zz;
int i;
if (vstform.flag == 0) return;
pblue = bluev;
i = bluec;
while (i--)
{
/* Bottom zones are aligned at 0.0625, top zones at 0.9375 */
if (pblue->type < 0)
{ zz = pblue->s2 * vstform.scale;
if (vstform.scale < 0.0)
zz = floor(zz - 0.4375) + 0.9375;
else
zz = floor(zz + 0.4375) + 0.0625;
}
else
{ zz = pblue->s1 * vstform.scale;
if (vstform.scale < 0.0)
zz = floor(zz + 0.4375) + 0.0625;
else
zz = floor(zz - 0.4375) + 0.9375;
}
pblue->z1 = pblue->z2 = zz;
# ifdef FONTDEBUG
if (fontdebug & 8)
fprintf(stderr, "=> Blue %c [%7.2f, %7.2f] -> %6.2f\n",
(pblue->type < 0 ? '-' : '+'),
pblue->s1, pblue->s2, zz);
# endif
pblue++;
}
}
/* Bit packing tables to compress to one bit per pixel without dropouts */
static unsigned char ctbl[256] = /* Bit(s) in center (not edges) */
{ 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 */
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a0 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b0 */
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* c0 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d0 */
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* e0 */
0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 /* f0 */
};
static unsigned char ltbl[256] = /* Number of bits at left */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 30 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a0 */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b0 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* c0 */
0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* d0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* e0 */
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8 /* f0 */
};
static unsigned char rtbl[256] = /* Number of bits at right */
{ 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 00 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 10 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 20 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, /* 30 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 40 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 50 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, /* 70 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 80 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 90 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* a0 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, /* b0 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* c0 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* d0 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* e0 */
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 8 /* f0 */
};
/* Fill a character path, no clipping needed */
void charfill(void)
{ struct point *ppoint;
struct line *pline, **ppline;
char *pptr, *pptr1; /* device buffer pointers */
char *xptr1, *xptr2; /* x buffer pointers */
int count; /* counter */
int active, discard, sort; /* lines active, to be discarded, sorted */
int yy; /* current y coordinate */
int x1, x2, xp, xx; /* current, previous x position range */
int fdir; /* fill direction counter */
int mask1, mask2; /* bit masks for first and last bytes */
int s0, s1, s2; /* segment to draw */
/* Set up the fill lines and y buckets. Set up the x buffer */
lineend = 0;
count = gstate.pathend - gstate.pathbeg;
ppoint = &patharray[gstate.pathbeg];
while (count--)
{ if (ppoint->type != ptmove) charline(ppoint - 1);
ppoint++;
}
setybucket(0, gstate.dev.ysize * 8);
setxbuf(gstate.dev.xsize);
memset((char *) xshf, 0, gstate.dev.xsize * sizeof (int));
/* Fill the area. Start at the lowest scan line in the path and loop
* until we reach the highest, rendering 8 bits per pixel in each
* direction. Eight bits per pixel horizontally */
active = discard = sort = 0;
yy = 0;
pptr = gstate.dev.buf[0];
while (yy < gstate.dev.ysize * 8 + 8)
{ memset(xbuf, 0, gstate.dev.xsize);
if (yy >= gstate.dev.ysize * 8) goto lll;
/* Add all the new lines */
pline = ybucket[yy];
ybucket[yy] = NULL;
while (pline)
{ lineptr[active++] = pline;
pline = pline->chain;
sort++;
}
/* If we have any lines out of order sort them */
sort += discard;
if (sort != 0)
{ count = active;
for (;;)
{ count = count / 3 + 1;
for (x1 = count; x1 < active; x1++)
for (x2 = x1 - count;
x2 >= 0 &&
lineptr[x2]->xx > lineptr[x2 + count]->xx;
x2 -= count)
{ pline = lineptr[x2];
lineptr[x2] = lineptr[x2 + count];
lineptr[x2 + count] = pline;
}
if (count == 1) break;
}
active -= discard;
discard = sort = 0;
}
/* Scan convert the scan line */
count = active;
fdir = 0;
ppline = &lineptr[0];
xp = -32767;
while (count--)
{ pline = *ppline++;
x1 = pline->xx >> 16;
/* At the end of the line draw only its width */
if (yy == pline->y2)
{ pline->xx += pline->d2;
x2 = pline->xx >> 16;
pline->xx = 0x7fffffff;
discard++;
if (x2 < x1)
{ xx = x1;
x1 = x2;
x2 = xx;
}
if (fdir == 0)
{ s1 = x1;
s2 = x2;
}
else
{ if (x1 < s1) s1 = x1;
if (x2 > s2) s2 = x2;
continue;
}
}
/* Otherwise draw both the widths and the area enclosed */
else
{ if (yy == pline->y1)
pline->xx += pline->d1; /* Beginning */
else
pline->xx += pline->dx; /* Middle */
x2 = pline->xx >> 16;
if (x2 < xp) sort++;
xp = x2;
if (x2 < x1)
{ xx = x1;
x1 = x2;
x2 = xx;
}
if (fdir == 0) /* Left edge */
{ fdir += pline->fdir;
s1 = x1;
s2 = x2;
continue;
}
if (x1 < s1) s1 = x1; /* Right edge, or ... */
if (x2 > s2) s2 = x2;
fdir += pline->fdir;
if (fdir != 0) /* Interior */
continue;
}
/* Draw from s1 to s2 in the x buffer, 8 bits per pixel */
xptr1 = xbuf + (s1 >> 3);
xptr2 = xbuf + (s2 >> 3);
mask1 = 0xff >> (s1 & 7);
mask2 = ~0xff >> ((s2 & 7) + 1);
if (xptr1 == xptr2)
*xptr1 |= (mask1 & mask2);
else
{ *xptr1++ |= mask1;
while (xptr1 != xptr2) *xptr1++ = 0xff;
*xptr1 |= mask2;
}
}
/* Pack the x buffer horizontally, 8 bits per pixel */
lll:
xptr1 = xbuf;
count = gstate.dev.xsize;
s1 = 0;
s2 = *((unsigned char *) (xptr1++));
while (count--)
{ s0 = s1;
s1 = s2;
s2 = *((unsigned char *) (xptr1++));
xshf[count] <<= 1;
if (ctbl[s1] ||
ltbl[s1] > rtbl[s0] ||
rtbl[s1] != 0 && rtbl[s1] >= ltbl[s2])
xshf[count] |= 1;
}
/* After every 8 lines, pack bits vertically onto the page */
if (yy > 7 && (yy & 7) == 7)
{ pptr1 = pptr;
mask1 = 0x80;
count = gstate.dev.xsize;
while (count--)
{ s2 = xshf[count];
s0 = (s2 >> 16) & 0xff;
s1 = (s2 >> 8) & 0xff;
s2 = s2 & 0xff;
if (ctbl[s1] ||
ltbl[s1] > rtbl[s0] ||
rtbl[s1] != 0 && rtbl[s1] >= ltbl[s2])
*pptr1 |= mask1;
if ((mask1 >>= 1) == 0)
{ mask1 = 0x80;
pptr1++;
}
}
pptr += gstate.dev.xbytes;
}
yy++;
}
ybflag = 0;
}
/* Scale a line ready for filling */
void charline(struct point *ppoint)
{ struct line line;
double x1, x2, y1, y2, yy;
int fdir;
/* We convert the coordinates to fixed point, with a scale factor of
* 256, rendering 8 bits per pixel */
x1 = floor(ppoint[0].x * 2048.0 + 0.5);
x2 = floor(ppoint[1].x * 2048.0 + 0.5);
y1 = floor(ppoint[0].y * 2048.0 + 0.5);
y2 = floor(ppoint[1].y * 2048.0 + 0.5);
/* Make y1 <= y2 */
fdir = 1;
if (y2 < y1)
{ fdir = -1;
yy = x1; x1 = x2; x2 = yy;
yy = y1; y1 = y2; y2 = yy;
}
/* Construct the line. If it is not horizontal calculate the gradient
* and the special values of the x displacement for the first and last
* lines. The x coordinates are on a scale of 65536 */
line.cdir = 0;
line.fdir = fdir;
line.xx = x1 * 256.0;
line.y1 = ((int) y1) / 256;
line.y2 = ((int) y2) / 256;
if (line.y2 == line.y1)
{ line.dx = 0;
line.d1 = 0;
line.d2 = (x2 - x1) * 256.0;
}
else
{ yy = (x2 - x1) / (y2 - y1) * 256.0;
line.dx = yy * 256.0;
line.d1 = ((line.y1 + 1) * 256.0 - y1) * yy;
line.d2 = (y2 - line.y2 * 256.0) * yy;
}
/* Store the line in the line array */
checklinesize(lineend + 1);
linearray[lineend++] = line;
}
/* Set up the x buffers */
void setxbuf(int size)
{ int len;
if (size > xbsize)
{ len = size * (sizeof (int) + sizeof (char)) + 1;
xbsize = 0;
memfree(memxbeg, memxlen);
memxlen = 0;
memxbeg = memalloc(len);
if (memxbeg == NULL) error(errmemoryallocation);
memxlen = len;
xshf = memxbeg;
xbsize = size;
}
xbuf = (char *) (xshf + size);
}
/* End of file "postfont.c" */