EntityProc: PressReader.EntityProc = {
-- Xe, Ye, fontSet
Xe: INTEGER = entityTrailer.Xe;
Ye: INTEGER = entityTrailer.Ye;
hue, saturation, brightness: INT ← 0; -- current color in the Press file
fontNum: NAT ← 0; -- current font number
unset: INTEGER = FIRST[INTEGER];
spaceX, spaceY: INTEGER ← unset; -- current space width
pX, pY: INTEGER ← 0; -- current (entity-relative) position in the Press file
newPosition: BOOL ← TRUE; -- new position set, not yet reflected in IP master
newFont: BOOL ← TRUE; -- new font number set, curFont not yet updated
newAmplify: BOOL ← TRUE; -- amplifySpace must be recomputed
newColor: BOOL ← TRUE; -- new color set, not yet reflected in IP master
curFont: Font ← NIL; -- current font (if ~newFont)
skippingAlternative, inAlternative: BOOLEAN ← FALSE;
SetPosition:
PROC = {
ipMaster.SetXY[IP.int[pX+Xe], IP.int[pY+Ye]];
newPosition ← FALSE;
};
SetFont:
PROC = {
key: NAT = entityTrailer.fontSet*16+fontNum;
IF skippingAlternative THEN RETURN;
IF nFonts=0 THEN RETURN;
IF curFont=
NIL
OR curFont.encoding#key
THEN {
l: NAT ← 0;
u: NAT ← nFonts;
WHILE l <= u
DO
i: NAT = (l+u)/2;
f: Font = fonts[i];
SELECT f.encoding
FROM
> key => u ← i-1;
< key => l ← i+1;
= key => { curFont ← f; EXIT };
ENDCASE;
REPEAT FINISHED => ERROR Error[FontNotFound];
ENDLOOP;
IF tooManyFontsForFrame
THEN {
ipMaster.FGet[IPVariables.FrameVariable[0]];
ipMaster.Get[curFont.fontNumber];
ipMaster.AppendInteger[
LOOPHOLE[IPVariables.ImagerVariable[showVec], CARDINAL]];
ipMaster.AppendOp[iset];
}
ELSE ipMaster.SetFont[curFont.fontNumber];
};
newFont ← FALSE;
newAmplify ← TRUE;
};
SetAmplify:
PROC = {
sX, sY, dX, dY, s, d: INTEGER;
amplify: REAL;
IF newFont THEN SetFont[];
dX ← WidthX[curFont, ' ];
dY ← WidthY[curFont, ' ];
sX ← (IF spaceX=unset THEN dX ELSE spaceX);
sY ← (IF spaceY=unset THEN dY ELSE spaceY);
IF sY=0 AND dY=0 THEN { s ← sX; d ← dX }
ELSE IF sX=0 AND dX=0 THEN { s ← sY; d ← dY }
ELSE ERROR; -- not implemented
amplify ← REAL[s]/REAL[d];
IF amplify#ipAmplify
THEN {
ipMaster.SetAmplifySpace[IF s=d THEN IP.int[1] ELSE IP.rational[s, d]];
ipAmplify ← amplify;
};
newAmplify ← FALSE;
};
SetColor:
PROC = {
h: REAL = hue/255.0;
s: REAL = saturation/255.0;
v: REAL = brightness/255.0;
i: REAL = GraphicsColor.ColorToIntensity[GraphicsColor.HSVToColor[h, s, v]];
gray: REAL = 1.0-i;
IF gray#ipGray THEN ipMaster.SetGray[IP.real[ipGray ← gray]];
newColor ← FALSE;
};
showCharactersProc: PressReader.ShowCharactersProc = {
-- [opCode, length, text]
HasSpaces:
PROC[rope: Rope.
ROPE]
RETURNS[
BOOL] =
INLINE {
RETURN[rope.Find[" "]>=0] };
IF skippingAlternative THEN RETURN;
IF newColor THEN SetColor[];
IF newPosition THEN SetPosition[];
IF newFont THEN SetFont[]; -- Note: may set newAmplify
IF newAmplify AND HasSpaces[text] THEN SetAmplify[];
ipMaster.Show[text];
FOR i:
INT
IN[0..text.Length[])
DO
c: CHAR = text.Fetch[i];
IF c='
THEN {
pX ← pX+(IF spaceX=unset THEN WidthX[curFont, ' ] ELSE spaceX);
pY ← pY+(IF spaceY=unset THEN WidthY[curFont, ' ] ELSE spaceY);
}
ELSE {
pX ← pX+WidthX[curFont, c];
pY ← pY+WidthY[curFont, c];
};
ENDLOOP;
};
spacingProc: PressReader.SpacingProc = {
-- [opCode, value]
IF skippingAlternative THEN RETURN;
IF value=unset THEN ERROR;
SELECT opCode
FROM
setSpaceX, setSpaceXShort => spaceX ← value;
setSpaceY, setSpaceYShort => spaceY ← value;
resetSpace => spaceX ← spaceY ← unset;
ENDCASE => ERROR;
newAmplify ← TRUE;
};
spaceProc: PressReader.SpaceProc = {
-- []
sX, sY: INTEGER;
IF skippingAlternative THEN RETURN;
IF newFont THEN SetFont[];
sX ← (IF spaceX=unset THEN WidthX[curFont, ' ] ELSE spaceX);
sY ← (IF spaceY=unset THEN WidthY[curFont, ' ] ELSE spaceY);
SELECT
TRUE
FROM
sY=0 => ipMaster.SetXRel[IP.int[sX]];
sX=0 => ipMaster.SetYRel[IP.int[sY]];
ENDCASE => ipMaster.SetXYRel[IP.int[sX], IP.int[sY]];
pX ← pX+sX; pY ← pY+sY;
};
positionProc: PressReader.PositionProc = {
IF skippingAlternative THEN RETURN;
SELECT opCode
FROM
setX => pX ← value;
setY => pY ← value;
ENDCASE => ERROR;
newPosition ← TRUE;
};
colorProc: PressReader.ColorProc = {
IF skippingAlternative THEN RETURN;
SELECT opCode
FROM
setHue => hue ← value;
setSaturation => saturation ← value;
setBrightness => brightness ← value;
ENDCASE => ERROR;
newColor ← TRUE;
};
fontProc: PressReader.FontProc = {
-- [font]
IF font#fontNum THEN { fontNum ← font; newFont ← TRUE };
}; -- fontProc
alternativeProc: PressReader.AlternativeProc = {
IF (types = 0)
AND (elBytes = 0)
AND (dlBytes = 0)
THEN
inAlternative ← skippingAlternative ← FALSE
ELSE IF inAlternative THEN skippingAlternative ← TRUE
ELSE inAlternative ← TRUE;
};
showObjectProc: PressReader.ShowObjectProc = {
nTrajectories: INT ← 0;
CurveFlatten:
PROCEDURE [curve: CGCubic.Bezier] = {
c1, c2: CGCubic.Bezier;
IF CGCubic.Flat[curve, 1.5]
THEN {
x: INT = Real.RoundLI[curve.b3.x];
y: INT = Real.RoundLI[curve.b3.y];
ipMaster.LineTo[IP.int[x], IP.int[y]]
}
ELSE {
[c1, c2] ← CGCubic.Split[curve];
CurveFlatten[c1];
CurveFlatten[c2]; };
}; -- CurveFlatten
moveToProc: PressReader.MoveToProc = {
pX ← entityTrailer.Xe+x;
pY ← entityTrailer.Ye+y;
ipMaster.MoveTo[IP.int[pX], IP.int[pY]];
nTrajectories ← nTrajectories+1;
};
drawToProc: PressReader.DrawToProc = {
xNew: INT ← entityTrailer.Xe+x;
yNew: INT ← entityTrailer.Ye+y;
IF (xNew = pX) AND (yNew = pY) THEN RETURN
ELSE IF yNew = pY THEN ipMaster.LineToX[IP.int[xNew]]
ELSE IF xNew = pX THEN ipMaster.LineToY[IP.int[yNew]]
ELSE ipMaster.LineTo[IP.int[xNew], IP.int[yNew]];
pX ← xNew;
pY ← yNew;
};
drawCurveProc: PressReader.DrawCurveProc = {
-- note: Full IP has CurveTo
bezier: CGCubic.Bezier;
bezier ← CGCubic.CoeffsToBezier[CGCubic.Coeffs[
c0: GraphicsBasic.Vec[REAL[pX], REAL[pY]],
c1: GraphicsBasic.Vec[cX, cY],
c2: GraphicsBasic.Vec[bX, bY],
c3: GraphicsBasic.Vec[aX, aY]]];
IF fullInterpress
THEN {
x1, y1, x2, y2, x3, y3: INT;
x1 ← Real.RoundLI[bezier.b1.x];
y1 ← Real.RoundLI[bezier.b1.y];
x2 ← Real.RoundLI[bezier.b2.x];
y2 ← Real.RoundLI[bezier.b2.y];
x3 ← Real.RoundLI[bezier.b3.x];
y3 ← Real.RoundLI[bezier.b3.y];
ipMaster.CurveTo[
IP.int[x1], IP.int[y1], IP.int[x2], IP.int[y2], IP.int[x3], IP.int[y3]];
pX ← x3;
pY ← y3;
}
ELSE {
CurveFlatten[bezier];
pX ← Real.RoundLI[bezier.b3.x];
pY ← Real.RoundLI[bezier.b3.y];
};
}; -- drawCurveProc
IF skippingAlternative THEN RETURN;
IF newColor THEN SetColor[];
pressFile.GetObject[[moveToProc, drawToProc, drawCurveProc]];
ipMaster.AppendInteger[nTrajectories];
ipMaster.AppendOp[makeoutline];
ipMaster.AppendOp[maskfill];
}; -- showObjectProc
showRectangleProc: PressReader.ShowRectangleProc = {
IF skippingAlternative THEN RETURN;
IF newColor THEN SetColor[];
ipMaster.MaskRectangle[IP.int[pX+Xe], IP.int[pY+Ye], IP.int[width], IP.int[height]];
};
pressFile.GetCommands[PressReader.CommandProcs[
showCharactersProc: showCharactersProc,
spacingProc: spacingProc,
spaceProc: spaceProc,
positionProc: positionProc,
colorProc: colorProc,
fontProc: fontProc,
alternativeProc: alternativeProc,
showObjectProc: showObjectProc,
showRectangleProc: showRectangleProc
]];
}; -- EntityProc