#ifndef FONTMODULE
#include <stdio.h>
#include <math.h>
#else
#include "Xdefs.h"
#include "Xmd.h"
#include "xf86_ansic.h"
#endif
#include "objects.h"
#include "spaces.h"
#include "paths.h"
#include "fonts.h"
#include "pictures.h"
#include "range.h"
typedef struct xobject xobject;
#include "util.h"
#include "fontfcn.h"
#include "blues.h"
#define MAXSTACK 24
#define MAXCALLSTACK 10
#define MAXPSFAKESTACK 32
#define MAXSTRLEN 512
#define MAXLABEL 256
#ifdef BUILDCID
#define MAXSTEMS 500
#else
#define MAXSTEMS 128
#endif
#define EPS 0.001
#define HSTEM 1
#define VSTEM 3
#define VMOVETO 4
#define RLINETO 5
#define HLINETO 6
#define VLINETO 7
#define RRCURVETO 8
#define CLOSEPATH 9
#define CALLSUBR 10
#define RETURN 11
#define ESCAPE 12
#define HSBW 13
#define ENDCHAR 14
#define RMOVETO 21
#define HMOVETO 22
#define VHCURVETO 30
#define HVCURVETO 31
#define DOTSECTION 0
#define VSTEM3 1
#define HSTEM3 2
#define SEAC 6
#define SBW 7
#define DIV 12
#define CALLOTHERSUBR 16
#define POP 17
#define SETCURRENTPOINT 33
#define FABS(x) fabs(x)
#define CEIL(x) ceil(x)
#define FLOOR(x) floor(x)
#define ROUND(x) FLOOR((x) + 0.5)
#define ODD(x) (((int)(x)) & 01)
#define Error {errflag = TRUE; return;}
#define ErrorRet(ret) {errflag = TRUE; return (ret);}
struct stem {
int vertical;
double x, dx;
double y, dy;
struct segment *lbhint, *lbrevhint;
struct segment *rthint, *rtrevhint;
};
struct xobject *Type1Char(char *env, struct XYspace *S,
psobj *charstrP, psobj *subrsP, psobj *osubrsP,
struct blues_struct *bluesP, int *modeP);
#ifdef BUILDCID
struct xobject *CIDChar(char *env, struct XYspace *S,
psobj *charstrP, psobj *subrsP, psobj *osubrsP,
struct blues_struct *bluesP, int *modeP);
#endif
static double escapementX, escapementY;
static double sidebearingX, sidebearingY;
static double accentoffsetX, accentoffsetY;
static struct segment *path;
static int errflag;
static char *Environment;
static struct XYspace *CharSpace;
static psobj *CharStringP, *SubrsP;
static struct segment *Applyhint ( struct segment *p, int stemnumber,
int half );
static struct segment *Applyrevhint ( struct segment *p, int stemnumber,
int half );
static void CallOtherSubr ( int othersubrno );
static void CallSubr ( int subrno );
static struct segment *CenterStem ( double edge1, double edge2 );
static void ClearCallStack ( void );
static void ClearPSFakeStack ( void );
static void ClearStack ( void );
static void ComputeAlignmentZones ( void );
static void ComputeStem ( int stemno );
static void Decode ( int Code );
static unsigned char Decrypt ( unsigned char cipher );
static double Div ( double num1, double num2 );
static void DoClosePath ( void );
static void DoCommand ( int Code );
static int DoRead ( int *CodeP );
static void DotSection ( void );
static void EndChar ( void );
static void Escape ( int Code );
static struct segment *FindStems ( double x, double y, double dx, double dy );
static void FinitStems ( void );
static void FlxProc ( double c1x2, double c1y2, double c3x0, double c3y0,
double c3x1, double c3y1, double c3x2, double c3y2,
double c4x0, double c4y0, double c4x1, double c4y1,
double c4x2, double c4y2, double epY, double epX,
int idmin );
static void FlxProc1 ( void );
static void FlxProc2 ( void );
static void HintReplace ( void );
static void HStem ( double y, double dy );
static void InitStems ( void );
static void PopCall ( psobj **CurrStrPP, int *CurrIndexP,
unsigned short *CurrKeyP );
static double PSFakePop ( void );
static void PSFakePush ( double Num );
static void Push ( double Num );
static void PushCall ( psobj *CurrStrP, int CurrIndex,
unsigned short CurrKey );
static void Return ( void );
static void RLineTo ( double dx, double dy );
static void RMoveTo ( double dx, double dy );
static void RRCurveTo ( double dx1, double dy1, double dx2, double dy2,
double dx3, double dy3 );
static void Sbw ( double sbx, double sby, double wx, double wy );
static void Seac ( double asb, double adx, double ady, unsigned char bchar,
unsigned char achar );
static void SetCurrentPoint ( double x, double y );
static void StartDecrypt ( void );
static void VStem ( double x, double dx );
static struct segment *FlxOldPath;
static struct blues_struct *blues;
static struct alignmentzone alignmentzones[MAXALIGNMENTZONES];
static int numalignmentzones;
static void
ComputeAlignmentZones(void)
{
int i;
double dummy, bluezonepixels, familyzonepixels;
struct segment *p;
numalignmentzones = 0;
for (i = 0; i < blues->numBlueValues; i +=2, ++numalignmentzones) {
if (i == 0)
alignmentzones[numalignmentzones].topzone = FALSE;
else
alignmentzones[numalignmentzones].topzone = TRUE;
if (i < blues->numFamilyBlues) {
p = ILoc(CharSpace,0,blues->BlueValues[i] - blues->BlueValues[i+1]);
QueryLoc(p, IDENTITY, &dummy, &bluezonepixels);
Destroy(p);
p = ILoc(CharSpace,0,blues->FamilyBlues[i]-blues->FamilyBlues[i+1]);
QueryLoc(p, IDENTITY, &dummy, &familyzonepixels);
Destroy(p);
if (FABS(bluezonepixels - familyzonepixels) < 1.0) {
alignmentzones[numalignmentzones].bottomy =
blues->FamilyBlues[i];
alignmentzones[numalignmentzones].topy =
blues->FamilyBlues[i+1];
continue;
}
}
alignmentzones[numalignmentzones].bottomy = blues->BlueValues[i];
alignmentzones[numalignmentzones].topy = blues->BlueValues[i+1];
}
for (i = 0; i < blues->numOtherBlues; i +=2, ++numalignmentzones) {
alignmentzones[numalignmentzones].topzone = FALSE;
if (i < blues->numFamilyOtherBlues) {
p = ILoc(CharSpace,0,blues->OtherBlues[i] - blues->OtherBlues[i+1]);
QueryLoc(p, IDENTITY, &dummy, &bluezonepixels);
Destroy(p);
p = ILoc(CharSpace,0,blues->FamilyOtherBlues[i] -
blues->FamilyOtherBlues[i+1]);
QueryLoc(p, IDENTITY, &dummy, &familyzonepixels);
Destroy(p);
if (FABS(bluezonepixels - familyzonepixels) < 1.0) {
alignmentzones[numalignmentzones].bottomy =
blues->FamilyOtherBlues[i];
alignmentzones[numalignmentzones].topy =
blues->FamilyOtherBlues[i+1];
continue;
}
}
alignmentzones[numalignmentzones].bottomy = blues->OtherBlues[i];
alignmentzones[numalignmentzones].topy = blues->OtherBlues[i+1];
}
}
static int InDotSection;
static struct stem stems[MAXSTEMS];
static int numstems;
static int currstartstem;
static int oldvert, oldhor;
static int oldhorhalf, oldverthalf;
static double wsoffsetX, wsoffsetY;
static int wsset;
static void
InitStems(void)
{
InDotSection = FALSE;
currstartstem = numstems = 0;
oldvert = oldhor = -1;
}
static void
FinitStems(void)
{
int i;
for (i = 0; i < numstems; i++) {
Destroy(stems[i].lbhint);
Destroy(stems[i].lbrevhint);
Destroy(stems[i].rthint);
Destroy(stems[i].rtrevhint);
}
}
static void
ComputeStem(int stemno)
{
int verticalondevice, idealwidth;
double stemstart, stemwidth;
struct segment *p;
int i;
double stembottom, stemtop, flatposition;
double Xpixels, Ypixels;
double unitpixels, onepixel;
int suppressovershoot, enforceovershoot;
double stemshift, flatpospixels, overshoot;
double widthdiff;
double lbhintvalue, rthintvalue;
double cxx, cyx, cxy, cyy;
int rotated;
QuerySpace(CharSpace, &cxx, &cyx, &cxy, &cyy);
if (FABS(cxx) < 0.00001 || FABS(cyy) < 0.00001)
rotated = TRUE;
else if (FABS(cyx) < 0.00001 || FABS(cxy) < 0.00001)
rotated = FALSE;
else {
stems[stemno].lbhint = NULL;
stems[stemno].lbrevhint = NULL;
stems[stemno].rthint = NULL;
stems[stemno].rtrevhint = NULL;
return;
}
if (stems[stemno].vertical) {
verticalondevice = !rotated;
stemstart = stems[stemno].x;
stemwidth = stems[stemno].dx;
} else {
verticalondevice = rotated;
stemstart = stems[stemno].y;
stemwidth = stems[stemno].dy;
}
if (stems[stemno].vertical)
p = ILoc(CharSpace, 1, 0);
else
p = ILoc(CharSpace, 0, 1);
QueryLoc(p, IDENTITY, &Xpixels, &Ypixels);
Destroy(p);
if (verticalondevice)
unitpixels = FABS(Xpixels);
else
unitpixels = FABS(Ypixels);
onepixel = 1.0 / unitpixels;
widthdiff = 0.0;
if (stems[stemno].vertical) {
if (blues->StdVW != 0)
widthdiff = blues->StdVW - stemwidth;
for (i = 0; i < blues->numStemSnapV; ++i) {
if (blues->StemSnapV[i] - stemwidth < widthdiff)
widthdiff = blues->StemSnapV[i] - stemwidth;
}
} else {
if (blues->StdHW != 0)
widthdiff = blues->StdHW - stemwidth;
for (i = 0; i < blues->numStemSnapH; ++i) {
if (blues->StemSnapH[i] - stemwidth < widthdiff)
widthdiff = blues->StemSnapH[i] - stemwidth;
}
}
if (FABS(widthdiff) > onepixel)
widthdiff = 0.0;
idealwidth = ROUND((stemwidth + widthdiff) * unitpixels);
if (idealwidth == 0)
idealwidth = 1;
if (blues->ForceBold && stems[stemno].vertical)
if (idealwidth < DEFAULTBOLDSTEMWIDTH)
idealwidth = DEFAULTBOLDSTEMWIDTH;
widthdiff = idealwidth * onepixel - stemwidth;
stemshift = 0.0;
if (!stems[stemno].vertical) {
stembottom = stemstart;
stemtop = stemstart + stemwidth;
for (i = 0; i < numalignmentzones; ++i) {
if (alignmentzones[i].topzone) {
if (stemtop >= alignmentzones[i].bottomy &&
stemtop <= alignmentzones[i].topy + blues->BlueFuzz) {
break;
}
} else {
if (stembottom <= alignmentzones[i].topy &&
stembottom >= alignmentzones[i].bottomy - blues->BlueFuzz) {
break;
}
}
}
if (i < numalignmentzones) {
suppressovershoot = FALSE;
enforceovershoot = FALSE;
if (unitpixels < blues->BlueScale)
suppressovershoot = TRUE;
else
if (alignmentzones[i].topzone) {
if (stemtop >= alignmentzones[i].bottomy + blues->BlueShift)
enforceovershoot = TRUE;
} else
if (stembottom <= alignmentzones[i].topy - blues->BlueShift)
enforceovershoot = TRUE;
if (alignmentzones[i].topzone)
flatposition = alignmentzones[i].bottomy;
else
flatposition = alignmentzones[i].topy;
flatpospixels = flatposition * unitpixels;
stemshift = (ROUND(flatpospixels) - flatpospixels) * onepixel;
if (alignmentzones[i].topzone)
overshoot = stemtop - flatposition;
else
overshoot = flatposition - stembottom;
if (overshoot > 0.0) {
if (enforceovershoot)
if (overshoot < onepixel) {
if (alignmentzones[i].topzone)
stemshift += onepixel - overshoot;
else
stemshift -= onepixel - overshoot;
}
if (suppressovershoot) {
if (alignmentzones[i].topzone)
stemshift -= overshoot;
else
stemshift += overshoot;
}
}
if (alignmentzones[i].topzone) {
lbhintvalue = stemshift - widthdiff;
rthintvalue = stemshift;
} else {
lbhintvalue = stemshift;
rthintvalue = stemshift + widthdiff;
}
stems[stemno].lbhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, lbhintvalue));
stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -lbhintvalue));
stems[stemno].rthint = (struct segment *)Permanent(Loc(CharSpace, 0.0, rthintvalue));
stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -rthintvalue));
return;
}
}
stemstart = stemstart - widthdiff / 2;
stemshift = ROUND(stemstart * unitpixels) * onepixel - stemstart;
lbhintvalue = stemshift - widthdiff / 2;
rthintvalue = stemshift + widthdiff / 2;
if (stems[stemno].vertical) {
stems[stemno].lbhint = (struct segment *)Permanent(Loc(CharSpace, lbhintvalue, 0.0));
stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, -lbhintvalue, 0.0));
stems[stemno].rthint = (struct segment *)Permanent(Loc(CharSpace, rthintvalue, 0.0));
stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, -rthintvalue, 0.0));
} else {
stems[stemno].lbhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, lbhintvalue));
stems[stemno].lbrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -lbhintvalue));
stems[stemno].rthint = (struct segment *)Permanent(Loc(CharSpace, 0.0, rthintvalue));
stems[stemno].rtrevhint = (struct segment *)Permanent(Loc(CharSpace, 0.0, -rthintvalue));
}
}
#define LEFT 1
#define RIGHT 2
#define BOTTOM 3
#define TOP 4
static struct segment *
Applyhint(struct segment *p, int stemnumber, int half)
{
if (half == LEFT || half == BOTTOM)
return Join(p, stems[stemnumber].lbhint);
else
return Join(p, stems[stemnumber].rthint);
}
static struct segment *
Applyrevhint(struct segment *p, int stemnumber, int half)
{
if (half == LEFT || half == BOTTOM)
return Join(p, stems[stemnumber].lbrevhint);
else
return Join(p, stems[stemnumber].rtrevhint);
}
static struct segment *
FindStems(double x, double y, double dx, double dy)
{
int i;
int newvert, newhor;
struct segment *p;
int newhorhalf, newverthalf;
if (InDotSection) return(NULL);
newvert = newhor = -1;
newhorhalf = newverthalf = -1;
for (i = currstartstem; i < numstems; i++) {
if (stems[i].vertical) {
if ((x >= stems[i].x - EPS) &&
(x <= stems[i].x+stems[i].dx + EPS)) {
newvert = i;
if (dy != 0.0) {
if (dy < 0) newverthalf = LEFT;
else newverthalf = RIGHT;
} else {
if (x < stems[i].x+stems[i].dx / 2) newverthalf = LEFT;
else newverthalf = RIGHT;
}
}
} else {
if ((y >= stems[i].y - EPS) &&
(y <= stems[i].y+stems[i].dy + EPS)) {
newhor = i;
if (dx != 0.0) {
if (dx < 0) newhorhalf = TOP;
else newhorhalf = BOTTOM;
} else {
if (y < stems[i].y+stems[i].dy / 2) newhorhalf = BOTTOM;
else newhorhalf = TOP;
}
}
}
}
p = NULL;
if (newvert == -1 && oldvert == -1) ;
else if (newvert == oldvert &&
newverthalf == oldverthalf);
else if (oldvert == -1) {
p = Applyhint(p, newvert, newverthalf);
} else if (newvert == -1) {
p = Applyrevhint(p, oldvert, oldverthalf);
} else {
p = Applyrevhint(p, oldvert, oldverthalf);
p = Applyhint(p, newvert, newverthalf);
}
if (newhor == -1 && oldhor == -1) ;
else if (newhor == oldhor &&
newhorhalf == oldhorhalf) ;
else if (oldhor == -1) {
p = Applyhint(p, newhor, newhorhalf);
} else if (newhor == -1) {
p = Applyrevhint(p, oldhor, oldhorhalf);
}
else {
p = Applyrevhint(p, oldhor, oldhorhalf);
p = Applyhint(p, newhor, newhorhalf);
}
oldvert = newvert; oldverthalf = newverthalf;
oldhor = newhor; oldhorhalf = newhorhalf;
return p;
}
static int strindex;
static double currx, curry;
struct callstackentry {
psobj *currstrP;
int currindex;
unsigned short currkey;
};
static double Stack[MAXSTACK];
static int Top;
static struct callstackentry CallStack[MAXCALLSTACK];
static int CallTop;
static double PSFakeStack[MAXPSFAKESTACK];
static int PSFakeTop;
static void
ClearStack(void)
{
Top = -1;
}
static void
Push(double Num)
{
if (++Top < MAXSTACK) Stack[Top] = Num;
else Error;
}
static void
ClearCallStack(void)
{
CallTop = -1;
}
static void
PushCall(psobj *CurrStrP, int CurrIndex, unsigned short CurrKey)
{
if (++CallTop < MAXCALLSTACK) {
CallStack[CallTop].currstrP = CurrStrP;
CallStack[CallTop].currindex = CurrIndex;
CallStack[CallTop].currkey = CurrKey;
}
else Error;
}
static void
PopCall(psobj **CurrStrPP, int *CurrIndexP, unsigned short *CurrKeyP)
{
if (CallTop >= 0) {
*CurrStrPP = CallStack[CallTop].currstrP;
*CurrIndexP = CallStack[CallTop].currindex;
*CurrKeyP = CallStack[CallTop--].currkey;
}
else Error;
}
static void
ClearPSFakeStack(void)
{
PSFakeTop = -1;
}
static void
PSFakePush(double Num)
{
if (++PSFakeTop < MAXPSFAKESTACK) PSFakeStack[PSFakeTop] = Num;
else Error;
}
static double
PSFakePop (void)
{
if (PSFakeTop >= 0) return(PSFakeStack[PSFakeTop--]);
else ErrorRet(0.0);
}
static struct segment *
CenterStem(double edge1, double edge2)
{
int idealwidth, verticalondevice;
double leftx, lefty, rightx, righty, center, width;
double widthx, widthy;
double shift, shiftx, shifty;
double Xpixels, Ypixels;
struct segment *p;
p = Loc(CharSpace, edge1, 0.0);
QueryLoc(p, IDENTITY, &leftx, &lefty);
p = Join(p, Loc(CharSpace, edge2, 0.0));
QueryLoc(p, IDENTITY, &rightx, &righty);
Destroy(p);
widthx = FABS(rightx - leftx);
widthy = FABS(righty - lefty);
if (widthy <= EPS) {
verticalondevice = TRUE;
center = (rightx + leftx) / 2.0;
width = widthx;
}
else if (widthx <= EPS) {
verticalondevice = FALSE;
center = (righty + lefty) / 2.0;
width = widthy;
}
else {
return (NULL);
}
idealwidth = ROUND(width);
if (idealwidth == 0) idealwidth = 1;
if (ODD(idealwidth)) {
shift = FLOOR(center) + 0.5 - center;
}
else {
shift = ROUND(center) - center;
}
if (verticalondevice) {
shiftx = shift;
shifty = 0.0;
} else {
shifty = shift;
shiftx = 0.0;
}
p = Loc(IDENTITY, shiftx, shifty);
QueryLoc(p, CharSpace, &Xpixels, &Ypixels);
wsoffsetX = Xpixels; wsoffsetY = Ypixels;
currx += wsoffsetX; curry += wsoffsetY;
return (p);
}
#define KEY 4330
#define C1 52845
#define C2 22719
static unsigned short r;
static unsigned char
Decrypt(unsigned char cipher)
{
unsigned char plain;
plain = cipher ^ (r >> 8);
r = (cipher + r) * C1 + C2;
return plain;
}
static int
DoRead(int *CodeP)
{
if (strindex >= CharStringP->len) return(FALSE);
*CodeP = Decrypt((unsigned char) CharStringP->data.stringP[strindex++]);
return(TRUE);
}
static void
StartDecrypt(void)
{
int Code;
r = KEY;
for (strindex = 0; strindex < blues->lenIV;)
if (!DoRead(&Code))
Error;
}
static void
Decode(int Code)
{
int Code1, Code2, Code3, Code4;
if (Code <= 31)
DoCommand(Code);
else if (Code <= 246)
Push((double)(Code - 139));
else if (Code <= 250) {
if (!DoRead(&Code2)) goto ended;
Push((double)(((Code - 247) << 8) + Code2 + 108));
}
else if (Code <= 254) {
if (!DoRead(&Code2)) goto ended;
Push((double)( -((Code - 251) << 8) - Code2 - 108));
}
else {
if (!DoRead(&Code1)) goto ended;
if (!DoRead(&Code2)) goto ended;
if (!DoRead(&Code3)) goto ended;
if (!DoRead(&Code4)) goto ended;
Push((double)((((((Code1<<8) + Code2)<<8) + Code3)<<8) + Code4));
}
return;
ended: Error;
}
static void
DoCommand(int Code)
{
switch(Code) {
case HSTEM:
if (Top < 1) Error;
HStem(Stack[0], Stack[1]);
ClearStack();
break;
case VSTEM:
if (Top < 1) Error;
VStem(Stack[0], Stack[1]);
ClearStack();
break;
case VMOVETO:
if (Top < 0) Error;
RMoveTo(0.0, Stack[0]);
ClearStack();
break;
case RLINETO:
if (Top < 1) Error;
RLineTo(Stack[0], Stack[1]);
ClearStack();
break;
case HLINETO:
if (Top < 0) Error;
RLineTo(Stack[0], 0.0);
ClearStack();
break;
case VLINETO:
if (Top < 0) Error;
RLineTo(0.0, Stack[0]);
ClearStack();
break;
case RRCURVETO:
if (Top < 5) Error;
RRCurveTo(Stack[0], Stack[1], Stack[2], Stack[3],
Stack[4], Stack[5]);
ClearStack();
break;
case CLOSEPATH:
DoClosePath();
ClearStack();
break;
case CALLSUBR:
if (Top < 0) Error;
CallSubr((int)Stack[Top--]);
break;
case RETURN:
Return();
break;
case ESCAPE:
if (!DoRead(&Code)) Error;
Escape(Code);
break;
case HSBW:
if (Top < 1) Error;
Sbw(Stack[0], 0.0, Stack[1], 0.0);
ClearStack();
break;
case ENDCHAR:
EndChar();
ClearStack();
break;
case RMOVETO:
if (Top < 1) Error;
RMoveTo(Stack[0], Stack[1]);
ClearStack();
break;
case HMOVETO:
if (Top < 0) Error;
RMoveTo(Stack[0], 0.0);
ClearStack();
break;
case VHCURVETO:
if (Top < 3) Error;
RRCurveTo(0.0, Stack[0], Stack[1], Stack[2],
Stack[3], 0.0);
ClearStack();
break;
case HVCURVETO:
if (Top < 3) Error;
RRCurveTo(Stack[0], 0.0, Stack[1], Stack[2], 0.0, Stack[3]);
ClearStack();
break;
default:
ClearStack();
Error;
}
}
static void
Escape(int Code)
{
int i, Num;
struct segment *p;
switch(Code) {
case DOTSECTION:
DotSection();
ClearStack();
break;
case VSTEM3:
if (Top < 5) Error;
if (!wsset && ProcessHints) {
p = CenterStem(Stack[2] + sidebearingX, Stack[3]);
path = Join(path, p);
wsset = 1;
}
VStem(Stack[0], Stack[1]);
VStem(Stack[2], Stack[3]);
VStem(Stack[4], Stack[5]);
ClearStack();
break;
case HSTEM3:
if (Top < 5) Error;
HStem(Stack[0], Stack[1]);
HStem(Stack[2], Stack[3]);
HStem(Stack[4], Stack[5]);
ClearStack();
break;
case SEAC:
if (Top < 4) Error;
Seac(Stack[0], Stack[1], Stack[2],
(unsigned char) Stack[3],
(unsigned char) Stack[4]);
ClearStack();
break;
case SBW:
if (Top < 3) Error;
Sbw(Stack[0], Stack[1], Stack[2], Stack[3]);
ClearStack();
break;
case DIV:
if (Top < 1) Error;
Stack[Top-1] = Div(Stack[Top-1], Stack[Top]);
Top--;
break;
case CALLOTHERSUBR:
if (Top < 1) Error;
Num = Stack[Top-1];
if (Top < Num+1) Error;
for (i = 0; i < Num; i++) PSFakePush(Stack[Top - i - 2]);
Top -= Num + 2;
#ifdef BUILDCID
if ((int)Stack[Top + Num + 2] > 3)
ClearPSFakeStack();
else
CallOtherSubr((int)Stack[Top + Num + 2]);
#else
CallOtherSubr((int)Stack[Top + Num + 2]);
#endif
break;
case POP:
Push(PSFakePop());
break;
case SETCURRENTPOINT:
if (Top < 1) Error;
SetCurrentPoint(Stack[0], Stack[1]);
ClearStack();
break;
default:
ClearStack();
Error;
}
}
static void
HStem(double y, double dy)
{
if (ProcessHints) {
if (numstems >= MAXSTEMS) Error;
if (dy < 0.0) {y += dy; dy = -dy;}
stems[numstems].vertical = FALSE;
stems[numstems].x = 0.0;
stems[numstems].y = sidebearingY + y + wsoffsetY;
stems[numstems].dx = 0.0;
stems[numstems].dy = dy;
ComputeStem(numstems);
numstems++;
}
}
static void
VStem(double x, double dx)
{
if (ProcessHints) {
if (numstems >= MAXSTEMS) Error;
if (dx < 0.0) {x += dx; dx = -dx;}
stems[numstems].vertical = TRUE;
stems[numstems].x = sidebearingX + x + wsoffsetX;
stems[numstems].y = 0.0;
stems[numstems].dx = dx;
stems[numstems].dy = 0.0;
ComputeStem(numstems);
numstems++;
}
}
static void
RLineTo(double dx, double dy)
{
struct segment *B;
B = Loc(CharSpace, dx, dy);
if (ProcessHints) {
currx += dx;
curry += dy;
B = Join(B, FindStems(currx, curry, dx, dy));
}
path = Join(path, Line(B));
}
static void
RRCurveTo(double dx1, double dy1, double dx2, double dy2,
double dx3, double dy3)
{
struct segment *B, *C, *D;
B = Loc(CharSpace, dx1, dy1);
C = Loc(CharSpace, dx2, dy2);
D = Loc(CharSpace, dx3, dy3);
if (ProcessHints) {
currx += dx1 + dx2 + dx3;
curry += dy1 + dy2 + dy3;
C = Join(C, FindStems(currx, curry, dx3, dy3));
}
C = Join(C, (struct segment *)Dup(B));
D = Join(D, (struct segment *)Dup(C));
path = Join(path, (struct segment *)Bezier(B, C, D));
}
static void
DoClosePath(void)
{
struct segment *CurrentPoint;
CurrentPoint = Phantom(path);
path = ClosePath(path);
path = Join(Snap(path), CurrentPoint);
}
static void
CallSubr(int subrno)
{
if ((subrno < 0) || (subrno >= SubrsP->len))
Error;
PushCall(CharStringP, strindex, r);
CharStringP = &SubrsP->data.arrayP[subrno];
StartDecrypt();
}
static void
Return(void)
{
PopCall(&CharStringP, &strindex, &r);
}
static void
EndChar(void)
{
path = ClosePath(path);
path = Join(Snap(path), Loc(CharSpace, escapementX, escapementY));
}
static void
RMoveTo(double dx, double dy)
{
struct segment *B;
B = Loc(CharSpace, dx, dy);
if (ProcessHints) {
currx += dx;
curry += dy;
B = Join(B, FindStems(currx, curry, 0.0, 0.0));
}
path = Join(path, B);
}
static void
DotSection(void)
{
InDotSection = !InDotSection;
}
static void
Seac(double asb, double adx, double ady,
unsigned char bchar, unsigned char achar)
{
int Code;
struct segment *mypath;
accentoffsetX = sidebearingX + adx - asb;
accentoffsetY = sidebearingY + ady;
path = NULL;
CharStringP = GetType1CharString((psfont *)Environment, achar);
StartDecrypt();
ClearStack();
ClearPSFakeStack();
ClearCallStack();
for (;;) {
if (!DoRead(&Code)) break;
Decode(Code);
if (errflag) return;
}
mypath = Snap(path);
path = NULL;
accentoffsetX = accentoffsetY = 0;
CharStringP = GetType1CharString((psfont *)Environment, bchar);
StartDecrypt();
ClearStack();
ClearPSFakeStack();
ClearCallStack();
FinitStems();
InitStems();
for (;;) {
if (!DoRead(&Code)) break;
Decode(Code);
if (errflag) return;
}
path = Join(mypath, path);
}
static void
Sbw(double sbx, double sby, double wx, double wy)
{
escapementX = wx;
escapementY = wy;
sidebearingX = sbx + accentoffsetX;
sidebearingY = sby + accentoffsetY;
path = Join(path, Loc(CharSpace, sidebearingX, sidebearingY));
if (ProcessHints) {currx = sidebearingX; curry = sidebearingY;}
}
static double
Div(double num1, double num2)
{
return(num1 / num2);
}
#define dtransform(dxusr,dyusr,dxdev,dydev) { \
register struct segment *point = Loc(CharSpace, dxusr, dyusr); \
QueryLoc(point, IDENTITY, dxdev, dydev); \
Destroy(point); \
}
#define itransform(xdev,ydev,xusr,yusr) { \
register struct segment *point = Loc(IDENTITY, xdev, ydev); \
QueryLoc(point, CharSpace, xusr, yusr); \
Destroy(point); \
}
#define transform(xusr,yusr,xdev,ydev) dtransform(xusr,yusr,xdev,ydev)
#define PaintType (0)
#define lineto(x,y) { \
struct segment *CurrentPoint; \
double CurrentX, CurrentY; \
CurrentPoint = Phantom(path); \
QueryLoc(CurrentPoint, CharSpace, &CurrentX, &CurrentY); \
Destroy(CurrentPoint); \
RLineTo(x - CurrentX, y - CurrentY); \
}
#define curveto(x0,y0,x1,y1,x2,y2) { \
struct segment *CurrentPoint; \
double CurrentX, CurrentY; \
CurrentPoint = Phantom(path); \
QueryLoc(CurrentPoint, CharSpace, &CurrentX, &CurrentY); \
Destroy(CurrentPoint); \
RRCurveTo(x0 - CurrentX, y0 - CurrentY, x1 - x0, y1 - y0, x2 - x1, y2 - y1); \
}
#define xshrink(x) ((x - c4x2) * shrink +c4x2)
#define yshrink(y) ((y - c4y2) * shrink +c4y2)
#define PickCoords(flag) \
if (flag) { \
x0 = c1x0; y0 = c1y0; \
x1 = c1x1; y1 = c1y1; \
x2 = c1x2; y2 = c1y2; \
x3 = c2x0; y3 = c2y0; \
x4 = c2x1; y4 = c2y1; \
x5 = c2x2; y5 = c2y2; \
} else { \
x0 = c3x0; y0 = c3y0; \
x1 = c3x1; y1 = c3y1; \
x2 = c3x2; y2 = c3y2; \
x3 = c4x0; y3 = c4y0; \
x4 = c4x1; y4 = c4y1; \
x5 = c4x2; y5 = c4y2; \
}
static void
FlxProc(double c1x2, double c1y2, double c3x0, double c3y0,
double c3x1, double c3y1, double c3x2, double c3y2,
double c4x0, double c4y0, double c4x1, double c4y1,
double c4x2, double c4y2, double epY, double epX, int idmin)
{
double dmin;
double c1x0, c1y0, c1x1, c1y1;
double c2x0, c2y0, c2x1, c2y1, c2x2, c2y2;
char yflag;
double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5;
double cxx, cyx, cxy, cyy;
int flipXY;
double x, y;
double erosion = 1;
double shrink;
double dX, dY;
char erode;
double eShift;
double cx, cy;
double ex, ey;
c1x0 = c1y0 = c1x1 = c1y1 = c2x0 = c2y0 = c2x1 = c2y1 = c2x2 = c2y2 = 0.0;
Destroy(path);
path = FlxOldPath;
if (ProcessHints) {
dmin = ABS(idmin) / 100.0;
c2x2 = c4x2; c2y2 = c4y2;
yflag = FABS(c1y2 - c3y2) > FABS(c1x2 - c3x2);
QuerySpace(CharSpace, &cxx, &cyx, &cxy, &cyy);
if (FABS(cxx) < 0.00001 || FABS(cyy) < 0.00001)
flipXY = -1;
else if (FABS(cyx) < 0.00001 || FABS(cxy) < 0.00001)
flipXY = 1;
else
flipXY = 0;
if (yflag) {
if (flipXY == 0 || c3y2 == c4y2) {
PickCoords(FALSE);
} else {
shrink = FABS((c1y2 - c4y2) / (c3y2 - c4y2));
c1x0 = c3x0; c1y0 = yshrink(c3y0);
c1x1 = c3x1; c1y1 = yshrink(c3y1);
c2x0 = c4x0; c2y0 = yshrink(c4y0);
c2x1 = c4x1; c2y1 = yshrink(c4y1);
dtransform(0.0, ROUND(c3y2-c1y2), &x, &y);
dY = FABS((flipXY == 1) ? y : x);
PickCoords(dY < dmin);
if (FABS(y2 - c1y2) > 0.001) {
transform(c1x2, c1y2, &x, &y);
if (flipXY == 1) {
cx = x; cy = y;
} else {
cx = y; cy = x;
}
dtransform(0.0, ROUND(y2-c1y2), &x, &y);
dY = (flipXY == 1) ? y : x;
if (ROUND(dY) != 0)
dY = ROUND(dY);
else
dY = (dY < 0) ? -1 : 1;
erode = PaintType != 2 && erosion >= 0.5;
if (erode)
cy -= 0.5;
ey = cy + dY;
ey = CEIL(ey) - ey;
ey = ey + FLOOR(cy + dY);
if (erode)
ey += 0.5;
if (flipXY == 1) {
itransform(cx, ey, &x, &y);
} else {
itransform(ey, cx, &x, &y);
}
eShift = y - y2;
y1 += eShift;
y2 += eShift;
y3 += eShift;
}
}
} else {
if (flipXY == 0 || c3x2 == c4x2) {
PickCoords(FALSE);
} else {
shrink = FABS((c1x2 - c4x2) / (c3x2 - c4x2));
c1x0 = xshrink(c3x0); c1y0 = c3y0;
c1x1 = xshrink(c3x1); c1y1 = c3y1;
c2x0 = xshrink(c4x0); c2y0 = c4y0;
c2x1 = xshrink(c4x1); c2y1 = c4y1;
dtransform(ROUND(c3x2 - c1x2), 0.0, &x, &y);
dX = FABS((flipXY == -1) ? y : x);
PickCoords(dX < dmin);
if (FABS(x2 - c1x2) > 0.001) {
transform(c1x2, c1y2, &x, &y);
if (flipXY == -1) {
cx = y; cy = x;
} else {
cx = x; cy = y;
}
dtransform(ROUND(x2-c1x2), 0.0, &x, &y);
dX = (flipXY == -1) ? y : x;
if (ROUND(dX) != 0)
dX = ROUND(dX);
else
dX = (dX < 0) ? -1 : 1;
erode = PaintType != 2 && erosion >= 0.5;
if (erode)
cx -= 0.5;
ex = cx + dX;
ex = CEIL(ex) - ex;
ex = ex + FLOOR(cx + dX);
if (erode)
ex += 0.5;
if (flipXY == -1) {
itransform(cy, ex, &x, &y);
} else {
itransform(ex, cy, &x, &y);
}
eShift = x - x2;
x1 += eShift;
x2 += eShift;
x3 += eShift;
}
}
}
if (x2 == x5 || y2 == y5) {
lineto(x5, y5);
} else {
curveto(x0, y0, x1, y1, x2, y2);
curveto(x3, y3, x4, y4, x5, y5);
}
} else {
PickCoords(FALSE);
curveto(x0, y0, x1, y1, x2, y2);
curveto(x3, y3, x4, y4, x5, y5);
}
PSFakePush(epY);
PSFakePush(epX);
}
static void
FlxProc1(void)
{
struct segment *CurrentPoint;
CurrentPoint = Phantom(path);
FlxOldPath = path;
path = CurrentPoint;
}
static void
FlxProc2(void)
{
struct segment *CurrentPoint;
double CurrentX, CurrentY;
CurrentPoint = Phantom(path);
QueryLoc(CurrentPoint, CharSpace, &CurrentX, &CurrentY);
Destroy(CurrentPoint);
PSFakePush(CurrentX);
PSFakePush(CurrentY);
}
static void
HintReplace(void)
{
currstartstem = numstems;
}
static void
CallOtherSubr(int othersubrno)
{
switch(othersubrno) {
case 0:
if (PSFakeTop < 16) Error;
ClearPSFakeStack();
FlxProc(
PSFakeStack[0], PSFakeStack[1], PSFakeStack[2], PSFakeStack[3],
PSFakeStack[4], PSFakeStack[5], PSFakeStack[6], PSFakeStack[7],
PSFakeStack[8], PSFakeStack[9], PSFakeStack[10], PSFakeStack[11],
PSFakeStack[12], PSFakeStack[13], PSFakeStack[14], PSFakeStack[15],
(int) PSFakeStack[16]
);
break;
case 1:
FlxProc1();
break;
case 2:
FlxProc2();
break;
case 3:
HintReplace();
break;
default: {
}
}
}
static void
SetCurrentPoint(double x, double y)
{
currx = x;
curry = y;
}
struct xobject *
Type1Char(char *env, struct XYspace *S, psobj *charstrP, psobj *subrsP,
psobj *osubrsP,
struct blues_struct *bluesP,
int *modeP)
{
int Code;
path = NULL;
errflag = FALSE;
Environment = env;
CharSpace = S;
CharStringP = charstrP;
SubrsP = subrsP;
blues = bluesP;
ComputeAlignmentZones();
StartDecrypt();
ClearStack();
ClearPSFakeStack();
ClearCallStack();
InitStems();
currx = curry = 0;
escapementX = escapementY = 0;
sidebearingX = sidebearingY = 0;
accentoffsetX = accentoffsetY = 0;
wsoffsetX = wsoffsetY = 0;
wsset = 0;
for (;;) {
if (!DoRead(&Code)) break;
Decode(Code);
if (errflag) break;
}
FinitStems();
if (errflag) {
if (path != NULL) {
Destroy(path);
path = NULL;
}
}
return((struct xobject *) path);
}
#ifdef BUILDCID
struct xobject *
CIDChar(char *env, struct XYspace *S,
psobj *charstrP, psobj *subrsP, psobj *osubrsP,
struct blues_struct *bluesP,
int *modeP)
{
int Code;
path = NULL;
errflag = FALSE;
Environment = env;
CharSpace = S;
CharStringP = charstrP;
SubrsP = subrsP;
blues = bluesP;
ComputeAlignmentZones();
StartDecrypt();
ClearStack();
ClearPSFakeStack();
ClearCallStack();
InitStems();
currx = curry = 0;
escapementX = escapementY = 0;
sidebearingX = sidebearingY = 0;
accentoffsetX = accentoffsetY = 0;
wsoffsetX = wsoffsetY = 0;
wsset = 0;
for (;;) {
if (!DoRead(&Code)) break;
Decode(Code);
if (errflag) break;
}
FinitStems();
if (errflag) {
if (path != NULL) {
Destroy(path);
path = NULL;
}
}
return((struct xobject *) path);
}
#endif