ShowPressImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Shore; December 7, 1982 1:38 pm
Beach, September 13, 1983 5:54 pm
Michael Plass, June 22, 1985 9:11:58 pm PDT
Russ Atkinson (RRA) March 18, 1985 7:01:02 pm PST
Doug Wyatt, December 6, 1985 2:55:41 pm PST
DIRECTORY
Convert USING [AppendInt],
Imager USING [black, Context, DoSave, MaskFill, MaskRectangle, SetColor, SetFont, SetGray, SetXY, SetXRel, SetXYRel, SetYRel, Show, TranslateT],
ImagerColor USING [ColorFromRGB, RGBFromHSV],
ImagerBackdoor USING [GetCP, DoIfVisible],
ImagerFont USING [Extents, Find, Font, FontBoundingBox, Modify, Scale, Width, XChar],
ImagerPath USING [PathProc],
ImagerTransformation USING [Rotate],
PressImage USING [DrawPressImage, MakePressImage, PressImage, PressImageError],
PressReader USING [AlternativeProc, ClosePressFile, ColorProc, Dots, DotsFollowProc, DrawCurveProc, DrawToProc, EntityProc, FontDirectoryProc, FontEntryProc, FontFace, FontProc, GetCommands, GetDocumentDirectory, GetDots, GetFonts, GetObject, GetPage, GetParts, Handle, MoveToProc, OpenPressFile, PageProc, PositionProc, PressReaderError, SetCodingProc, SetModeProc, SetSamplingPropertiesProc, SetSizeProc, SetWindowProc, ShowCharactersProc, ShowDotsProc, ShowObjectProc, ShowRectangleProc, SpaceProc, SpacingProc],
Real USING [Round, LargestNumber],
RefText USING [AppendChar, AppendRope, ObtainScratch, ReleaseScratch],
Rope USING [Fetch, FromRefText, Map, ROPE, Size],
ShowPress USING [FontRec, PressFileRec],
Vector2 USING [Add, Div, Mul, Sub, VEC];
ShowPressImpl: CEDAR PROGRAM
IMPORTS Convert, Imager, ImagerBackdoor, ImagerColor, ImagerFont, ImagerTransformation, PressImage, PressReader, Real, RefText, Rope, Vector2
EXPORTS ShowPress
= BEGIN
ROPE: TYPE ~ Rope.ROPE;
Handle: TYPE ~ REF PressFileRec;
PressFileRec: TYPE ~ ShowPress.PressFileRec;
FontRec: TYPE ~ ShowPress.FontRec;
nullReal: REAL ← -Real.LargestNumber;
micasPerPoint: REAL ← 2540.0/72.0;
pointsPerMica: REAL ← 72.0/2540.0;
ShowPressError: PUBLIC ERROR [code: ATOM] = CODE;
Coeffs: TYPE = RECORD [c0, c1, c2, c3: Vector2.VEC];
Bezier: TYPE = RECORD [b0, b1, b2, b3: Vector2.VEC];
SetHSV: PROC [context: Imager.Context, h, s, v: REAL] = {
IF v = 0.0 THEN {
Imager.SetColor[context, Imager.black];
}
ELSE {
IF s = 0.0 THEN {
Imager.SetGray[context, 1.0-v];
}
ELSE {
Imager.SetColor[context, ImagerColor.ColorFromRGB[ImagerColor.RGBFromHSV[[H: h, S: s, V: v]]]];
};
};
};
CoeffsToBezier: PROC [coeffs: Coeffs] RETURNS [bezier: Bezier] = {
Compute the bezier control points of the cubic
These points form a convex hull of the curve
b0 is the starting point, b3 is the ending point
b0 ← c0;
b1 ← c0 + c1/3;
b2 ← c0 + 2*c1/3 + c2/3; [ = b1 + (c1+c2)/3 ]
b3 ← c0 + c1 + c2 + c3;
bezier.b0 ← coeffs.c0;
bezier.b1 ← coeffs.c0.Add[coeffs.c1.Div[3]];
bezier.b2 ← bezier.b1.Add[coeffs.c1.Add[coeffs.c2].Div[3]];
bezier.b3 ← coeffs.c0.Add[coeffs.c1].Add[coeffs.c2].Add[coeffs.c3];
RETURN[bezier];
};
BezierToCoeffs: PROC [bezier: Bezier] RETURNS [coeffs: Coeffs] = {
Compute the cubic coefficients from the Bezier points.
c0 ← b0;
c1 ← 3(b1-b0);
c2 ← 3(b0-2b1+b2); [ = 3(b2-b1) - c1 ]
c3 ← -b0 +3(b1-b2) + b3; [ = b3 - (b0 + 3(b2-b1)) ]
t: Vector2.VEC ← bezier.b2.Sub[bezier.b1].Mul[3];
coeffs.c0 ← bezier.b0;
coeffs.c1 ← bezier.b1.Sub[bezier.b0].Mul[3];
coeffs.c2 ← t.Sub[coeffs.c1];
coeffs.c3 ← bezier.b3.Sub[bezier.b0.Add[t]];
RETURN[coeffs];
};
NameFromPressFontID: PROC [family: ROPE, face: PressReader.FontFace] RETURNS [name: ROPE] ~ {
t: REF TEXT ← RefText.ObtainScratch[100];
t ← RefText.AppendRope[t, "Xerox/Pressfonts/"];
t ← RefText.AppendRope[t, family];
IF face.texDesignSize > 0 THEN {
t ← Convert.AppendInt[t, Real.Round[face.texDesignSize]];
}
ELSE {
t ← RefText.AppendChar[t, '-];
t ← RefText.AppendChar[t, SELECT face.weight FROM
medium => 'M, bold => 'B, light => 'L, ENDCASE => 'M
];
t ← RefText.AppendChar[t, SELECT face.slope FROM
regular => 'R, italic => 'I, ENDCASE => 'R
];
t ← RefText.AppendChar[t, SELECT face.expansion FROM
regular => 'R, condensed => 'C, expanded => 'E, ENDCASE => 'R
];
};
name ← Rope.FromRefText[t];
RefText.ReleaseScratch[t];
};
Open: PUBLIC PROCEDURE [fileName: Rope.ROPE] RETURNS [show: Handle ← NIL] = {
FontInitProc: PressReader.FontEntryProc = { -- build a list of needed fonts
sizeInMicas: REAL ~ (
IF fontDirectoryEntry.size > 0 THEN ((REAL[fontDirectoryEntry.size]*2540.0)/72.0)
ELSE (REAL[-fontDirectoryEntry.size])
);
name: ROPE ~ NameFromPressFontID[fontDirectoryEntry.family, fontDirectoryEntry.face];
imagerFont: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find[name], sizeInMicas];
IF fontDirectoryEntry.rotation#0 THEN {
degrees: REAL ← fontDirectoryEntry.rotation/60.0;
imagerFont ← ImagerFont.Modify[imagerFont, ImagerTransformation.Rotate[degrees]];
};
show.fontTable[fontDirectoryEntry.fontSet*16+fontDirectoryEntry.font] ← [
imagerFont: imagerFont,
family: fontDirectoryEntry.family,
face: fontDirectoryEntry.face.encoding,
size: sizeInMicas,
rotation: REAL[fontDirectoryEntry.rotation]/60.0
];
}; -- FontInitProc
pressFile: PressReader.Handle ← PressReader.OpenPressFile[fileName !
PressReader.PressReaderError => {
SELECT errorCode FROM
FileNotAPressFile => ERROR ShowPressError[$CantReadFile];
ENDCASE => REJECT;
}
];
show ← NEW[PressFileRec];
show.pressFile ← pressFile;
show.lastPart ← pressFile.GetDocumentDirectory[].nParts;
show.pressFile.GetFonts[FontInitProc];
};
DrawPressPage: PUBLIC PROCEDURE [context: Imager.Context, show: Handle, pageNumber: INT, tinyPaint: BOOLFALSE] = {
skipAlternative: BOOLFALSE;
hue: REAL ← 0.0;
saturation: REAL ← 0.0;
brightness: REAL ← 0.0;
colorChanged: BOOLTRUE;
ValidateColor: PROC ~ {
IF colorChanged THEN {
IF saturation = 0 THEN Imager.SetGray[context, 1.0-brightness]
ELSE SetHSV[context, hue, saturation, brightness];
colorChanged ← FALSE;
};
};
showObjectProc: PressReader.ShowObjectProc = {
IF NOT skipAlternative THEN {
Path: ImagerPath.PathProc ~ {
lp: Vector2.VEC ← [0, 0];
moveToProc: PressReader.MoveToProc = {moveTo[lp ← [x, y]]};
drawToProc: PressReader.DrawToProc = {lineTo[lp ← [x, y]]};
drawCurveProc: PressReader.DrawCurveProc = {
cubic: Coeffs ~ [c0: lp, c1: [cX, cY], c2: [bX, bY], c3: [aX, aY]];
bezier: Bezier ~ CoeffsToBezier[cubic];
curveTo[bezier.b1, bezier.b2, bezier.b3];
lp ← bezier.b3;
};
show.pressFile.GetObject[moveToProc, drawToProc, drawCurveProc];
};
ValidateColor[];
Imager.MaskFill[context: context, path: Path, parity: TRUE]
};
}; -- showObjectProc
PageProc: PressReader.PageProc = {
EntityProc: PressReader.EntityProc = { -- Xe, Ye, fontSet
currentFont: FontRec; -- will be established by setFont
currentFontYMin, currentFontYMax: REAL; -- for faster culling of characters
currentSpaceX: REAL; -- will be established by setFont
currentSpaceY: REAL; -- will be established by setFont
spaceChanged: BOOLFALSE;
x, y: REAL ← 0.0;
cpChanged: BOOLTRUE;
inAlternative: BOOLFALSE;
ValidateCP: PROC ~ {
IF cpChanged THEN {
IF x = nullReal THEN x ← ImagerBackdoor.GetCP[context].x;
IF y = nullReal THEN y ← ImagerBackdoor.GetCP[context].y;
Imager.SetXY[context, [x, y]];
cpChanged ← FALSE;
};
};
showCharactersProc: PressReader.ShowCharactersProc = {
ShowAction: PROC ~ {
start: INT ← 0;
size: INT ~ Rope.Size[text];
WHILE start<size DO
XString: PROC [charAction: PROC [char: ImagerFont.XChar]] ~ {
action: PROC [c: CHAR] RETURNS [quit: BOOLFALSE] ~ {
IF c='\040 AND spaceChanged THEN quit ← TRUE
ELSE {charAction[[set: 0, code: ORD[c]]]; start ← start + 1};
};
[] ← Rope.Map[base: text, start: start, len: size-start, action: action];
};
IF spaceChanged AND Rope.Fetch[text, start]='\040 THEN {
Imager.SetXYRel[context, [currentSpaceX, currentSpaceY]];
start ← start + 1;
};
IF start<size THEN Imager.Show[context, XString];
ENDLOOP;
};
IF skipAlternative THEN RETURN;
ValidateCP[];
ValidateColor[];
IF currentFont.rotation = 0.0 THEN {
Cull unrotated characters obviously outside the context
textYMax: REAL ~ y + currentFontYMax;
textYMin: REAL ~ y + currentFontYMin;
ImagerBackdoor.DoIfVisible[context, [x: 0, y: textYMin, w: 32768, h: textYMax-textYMin], ShowAction];
}
ELSE ShowAction[];
x ← nullReal;
IF currentFont.rotation # 0 THEN y ← nullReal;
}; -- showCharactersProc
fontProc: PressReader.FontProc = {
IF skipAlternative THEN RETURN;
currentFont ← show.fontTable[entityTrailer.fontSet*16+font];
IF currentFont.imagerFont # NIL THEN {
extents: ImagerFont.Extents ~ ImagerFont.FontBoundingBox[currentFont.imagerFont];
currentFontYMin ← -extents.descent;
currentFontYMax ← extents.ascent;
}
ELSE {
currentFontYMin ← FIRST[INTEGER];
currentFontYMax ← LAST[INTEGER];
};
IF currentFont.imagerFont = NIL THEN RETURN;
Imager.SetFont[context, currentFont.imagerFont];
};
positionProc: PressReader.PositionProc = {
IF skipAlternative THEN RETURN;
SELECT opCode FROM
setX => {
IF cpChanged THEN NULL
ELSE IF x=nullReal THEN cpChanged ← TRUE
ELSE Imager.SetXRel[context, value-x];
x ← value;
};
setY => {
IF cpChanged THEN NULL
ELSE IF y=nullReal THEN cpChanged ← TRUE
ELSE Imager.SetYRel[context, value-y];
y ← value;
};
ENDCASE => ERROR;
};
spacingProc: PressReader.SpacingProc = {
IF skipAlternative THEN RETURN;
IF opCode#resetSpace AND NOT spaceChanged THEN {
IF currentFont.imagerFont=NIL THEN ERROR ShowPressError[$NoCurrentFont];
[[currentSpaceX, currentSpaceY]] ← ImagerFont.Width[currentFont.imagerFont, [set:0,code:ORD[' ]]];
spaceChanged ← TRUE;
};
SELECT opCode FROM
setSpaceX, setSpaceXShort => currentSpaceX ← value;
setSpaceY, setSpaceYShort => currentSpaceY ← value;
resetSpace => spaceChanged ← FALSE;
ENDCASE => ERROR;
};
spaceProc: PressReader.SpaceProc = {
IF skipAlternative THEN RETURN;
showCharactersProc[opCode: showCharacterImmediate, length: 1, text: "\040"];
};
colorProc: PressReader.ColorProc = {
IF skipAlternative THEN RETURN;
SELECT opCode FROM
setHue => hue ← REAL[value MOD 240]/240.0;
setSaturation => saturation ← REAL[value]/255.0;
setBrightness => brightness ← REAL[value]/255.0;
ENDCASE => ERROR;
colorChanged ← TRUE;
};
showRectangleProc: PressReader.ShowRectangleProc = {
IF skipAlternative THEN RETURN;
IF x = nullReal THEN x ← ImagerBackdoor.GetCP[context].x;
IF y = nullReal THEN y ← ImagerBackdoor.GetCP[context].y;
ValidateColor[];
Imager.MaskRectangle[context, [x, y, width, height]];
};
alternativeProc: PressReader.AlternativeProc = {
IF (types = 0) AND (elBytes = 0) AND (dlBytes = 0) THEN
inAlternative ← skipAlternative ← FALSE
ELSE IF inAlternative THEN skipAlternative ← TRUE
ELSE inAlternative ← TRUE;
};
showDotsProc: PressReader.ShowDotsProc = {
codingType, dotsPerLine, scanLines, scanMode, passDots, displayDots, passLines, displayLines: INT ← 0;
windowWidth, windowHeight: REAL ← 0.0;
dotInfo: PressReader.Dots;
image: PressImage.PressImage;
mark: Graphics.Mark ← Graphics.Save[context];
setCodingProc: PressReader.SetCodingProc = {
codingType ← code;
windowWidth ← dotsPerLine ← displayDots ← dots;
windowHeight ← scanLines ← displayLines ← lines;
};
setModeProc: PressReader.SetModeProc = {scanMode ← mode;};
setWindowProc: PressReader.SetWindowProc = {
passDots ← pd;
displayDots ← dd;
passLines ← pl;
displayLines ← dl;
};
setSizeProc: PressReader.SetSizeProc = {
windowWidth ← REAL[width];
windowHeight ← REAL[height];
};
setSampling: PressReader.SetSamplingPropertiesProc = {
[samplingProperties: LIST OF PressReader.SamplingProperty]
??
};
dotsFollowProc: PressReader.DotsFollowProc = {
dotInfo ← dots;
};
IF skipAlternative THEN RETURN;
show.pressFile.GetDots[setCodingProc, setModeProc, setWindowProc, setSizeProc, setSampling, dotsFollowProc];
{
-- Cull dots obviously outside the context
box: Graphics.Box ← Graphics.GetBounds[context];
cpX, cpY: REAL;
[cpX, cpY] ← Graphics.GetCP[context];
IF box.ymax < cpY OR box.ymin > cpY+(windowHeight*micasPerPoint) THEN
RETURN;
};
{
image ← PressImage.MakePressImage[
sampleType: codingType,
dots: dotsPerLine,
lines: scanLines,
mode: scanMode,
pd: passDots,
dd: displayDots,
pl: passLines,
dl: displayLines,
width: windowWidth,
height: windowHeight,
bits: dotInfo
! PressImage.PressImageError => GOTO Quit
];
ValidateCP[];
PressImage.DrawPressImage[context, image];
};
EXITS
Quit => RETURN;
}; -- showDotsProc
skipAlternative ← FALSE;
hue ← saturation ← brightness ← 0.0;
colorChanged ← TRUE;
Imager.TranslateT[context, [entityTrailer.Xe, entityTrailer.Ye]];
fontProc[0]; -- SetFont 0; ResetSpace;
Imager.SetXY[context, [0, 0]];
show.pressFile.GetCommands[
showCharactersProc: showCharactersProc,
fontProc: fontProc,
positionProc: positionProc,
spacingProc: spacingProc,
spaceProc: spaceProc,
colorProc: colorProc,
showRectangleProc: showRectangleProc,
alternativeProc: alternativeProc,
showObjectProc: showObjectProc,
showDotsProc: showDotsProc
];
}; -- EntityProc
OuterEntityProc: PressReader.EntityProc ~ {
proc: PROC ~ {EntityProc[handle, entityTrailer]};
Imager.DoSave[context, proc];
};
show.pressFile.GetPage[OuterEntityProc];
}; -- PageProc
SkipFonts: PressReader.FontDirectoryProc = {
pageNumber ←
IF pageNumber = show.lastPart THEN ERROR ShowPressError[$NoSuchPage]
ELSE MIN[pageNumber+1, show.lastPart];
show.pressFile.GetParts[pageNumber, PageProc, SkipFonts];
};
[] ← Graphics.SetFat[self: context, fat: TRUE];
show.pressFile.GetParts[pageNumber, PageProc, SkipFonts];
}; -- DrawPressPage
Close: PUBLIC PROCEDURE [show: Handle] = TRUSTED {
show.pressFile.ClosePressFile[];
};
END.
Change Log
Created by Andrew Shore; September 13, 1982 6:45 pm
Changed by Shore; October 14, 1982 10:03 pm
converted to Cedar 3.4 (Graphics.Path operations)
Changed by Shore; December 4, 1982 12:10 am
converted to Cedar.Style
Edited on December 7, 1982 1:37 pm, by Shore
added Graphics.SetFat so thin lines will show
changes to: DIRECTORY, DrawPressPage
Edited on September 13, 1983 5:46 pm, by Beach
changes to: showCharactersProc to provide faster culling of characters obviously outside the context, fontProc to establish the culling bounds for the current font, showDotsProc to provide faster culling of dots obviously outside the context
Edited on February 14, 1984 11:26:48 am PST, by Plass
changes to: drawCurveProc to handle spline outlines correctly
Michael Plass, April 3, 1985 5:50:57 pm PST
Imager Conversion
changes to: DIRECTORY, ShowPressImpl, CoeffsToBezier, BezierToCoeffs, Open, FontInitProc (local of Open), DrawPressPage, EntityProc (local of PageProc, local of DrawPressPage), showCharactersProc (local of EntityProc, local of PageProc, local of DrawPressPage), ShowAction (local of showCharactersProc, local of EntityProc, local of PageProc, local of DrawPressPage), XString (local of ShowAction, local of showCharactersProc, local of EntityProc, local of PageProc, local of DrawPressPage), action (local of XString, local of ShowAction, local of showCharactersProc, local of EntityProc, local of PageProc, local of DrawPressPage), fontProc (local of EntityProc, local of PageProc, local of DrawPressPage), positionProc (local of EntityProc, local of PageProc, local of DrawPressPage), spacingProc (local of EntityProc, local of PageProc, local of DrawPressPage), spaceProc (local of EntityProc, local of PageProc, local of DrawPressPage), colorProc (local of EntityProc, local of PageProc, local of DrawPressPage), showRectangleProc (local of EntityProc, local of PageProc, local of DrawPressPage), showObjectProc (local of EntityProc, local of PageProc, local of DrawPressPage), Path (local of showObjectProc, local of EntityProc, local of PageProc, local of DrawPressPage), moveToProc (local of Path, local of showObjectProc, local of EntityProc, local of PageProc, local of DrawPressPage), drawToProc (local of Path, local of showObjectProc, local of EntityProc, local of PageProc, local of DrawPressPage), drawCurveProc (local of Path, local of showObjectProc, local of EntityProc, local of PageProc, local of DrawPressPage), showDotsProc (local of EntityProc, local of PageProc, local of DrawPressPage), SkipFonts (local of DrawPressPage), SpecialShow, Close