ShowPressImpl.mesa
Last edited by Shore; December 7, 1982 1:38 pm
Last Edited by: Beach, September 13, 1983 5:54 pm
DIRECTORY
CGCubic USING [Bezier, Coeffs, CoeffsToBezier],
Graphics,
GraphicsBasic USING [Vec],
GraphicsColor USING [HSVToColor],
PressImage USING [DrawPressImage, MakePressImage, PressImage, PressImageError],
PressReader,
PressFontReader USING [CharInfo, Close, EnumerateDirectory, Font, FromFile, GetCharInfo, Handle, VisitFontProc],
Real USING [Fix, RoundC],
Rope USING [Equal, Fetch, Length, ROPE],
ShowPress,
VFonts USING [EstablishFont, Font, GraphicsFont];
ShowPressImpl: PROGRAM
IMPORTS CGCubic, Graphics, GraphicsColor, PressImage, PressReader, PressFontReader, Real, Rope, VFonts
EXPORTS ShowPress
SHARES Graphics = BEGIN
OPEN ShowPress;
micasPerPoint: REAL = 2540.0/72.0;
pointsPerMica: REAL = 72.0/2540.0;
ShowPressError: PUBLIC ERROR[code: Code] = CODE;
Open: PUBLIC PROCEDURE [fileName: Rope.ROPE] RETURNS [show: Handle ← NIL] = {
pressFile: PressReader.Handle;
pressFontFile: PressFontReader.Handle ← PressFontReader.FromFile["/Indigo/Fonts/Fonts.Widths"];
FontInitProc: PressReader.FontEntryProc = { -- build a list of needed fonts
sizeInPoints: CARDINAL;
sizeInMicas: REAL;
font: VFonts.Font;
pressFont: PressFontReader.Font;
screenFontFamily: Rope.ROPE;
VisitFontProc: PressFontReader.VisitFontProc = {
IF Rope.Equal[fontRec.family, fontDirectoryEntry.family, FALSE]
AND (fontRec.face = fontDirectoryEntry.face.encoding)
AND ((fontRec.size = 0) OR (fontRec.size = REAL[sizeInMicas]*(1.0E-5)))
AND ((fontRec.rotation = fontDirectoryEntry.rotation) OR ((fontRec.rotation = 0) AND (fontDirectoryEntry.rotation MOD 5400 = 0))) THEN RETURN[quit: TRUE];
};
IF fontDirectoryEntry.size > 0 THEN {
sizeInPoints ← fontDirectoryEntry.size;
sizeInMicas ← (REAL[fontDirectoryEntry.size]*2540.0)/72.0; }
ELSE {
sizeInPoints ← Real.RoundC[(REAL[-fontDirectoryEntry.size]*72.0)/2540.0];
sizeInMicas ← REAL[-fontDirectoryEntry.size]; };
NOTE: the following code is a complete hack!!!! It is included only because of the Tioga -> Laurel -> (Timesroman) inconsistency in Cedar/Tioga screen fonts and the current Tioga TSetter. BE IT KNOWN: I'm ashamed of myself!!!
IF Rope.Equal[fontDirectoryEntry.family, "LAUREL", FALSE] THEN {
fontDirectoryEntry.family ← "TIMESROMAN";
screenFontFamily ← "TIOGA";
}
ELSE screenFontFamily ← fontDirectoryEntry.family;
font ← VFonts.EstablishFont[
family: screenFontFamily,
size: sizeInPoints,
bold: (fontDirectoryEntry.face.weight = bold),
italic: (fontDirectoryEntry.face.slope = italic),
defaultOnFailure: TRUE ];
! VFonts.Error => SELECT code FROM
VFonts.ErrorCode[fontNotFound] => ERROR ShowPressError[CantFindFonts, viewer];
ENDCASE => ERROR;
];
pressFont ← show.pressFontFile.EnumerateDirectory[VisitFontProc];
IF pressFont = NIL THEN ERROR ShowPressError[CantFindFonts];
show.fontTable[fontDirectoryEntry.fontSet*16+fontDirectoryEntry.font] ← [
screenFont: VFonts.GraphicsFont[font],
pressFont: pressFont,
size: sizeInMicas,
rotation: REAL[fontDirectoryEntry.rotation]/60.0 ];
}; -- FontInitProc
pressFile ← PressReader.OpenPressFile[fileName !
PressReader.PressReaderError => {
SELECT errorCode FROM
FileNotAvailableForRead, FileNotAPressFile => ERROR ShowPressError[CantReadFile];
ENDCASE => REJECT;
}
];
show ← NEW[PressFileRec ← [pressFile: pressFile, pressFontFile: pressFontFile, lastPart: pressFile.GetDocumentDirectory[].nParts]];
show.pressFile.GetFonts[FontInitProc];
}; -- Open
DrawPressPage: PUBLIC PROCEDURE [context: Graphics.Context, show: Handle, pageNumber: INT, tinyPaint: BOOLFALSE] = {
PageProc: PressReader.PageProc = {
EntityProc: PressReader.EntityProc = { -- Xe, Ye, fontSet
x: INT ← entityTrailer.Xe;
y: INT ← entityTrailer.Ye;
currentFont: FontRec; -- will be established by setFont
currentFontYMin, currentFontYMax: REAL; -- for faster culling of characters
currentSpaceX, currentSpaceY: INT; -- will be established by setFont
hue: REAL ← 0.0;
saturation: REAL ← 1.0;
brightness: REAL ← 0.0;
skipAlternative, inAlternative: BOOLFALSE;
showCharactersProc: PressReader.ShowCharactersProc = {
c: CHAR;
i: INT;
charInfo: PressFontReader.CharInfo;
dx, dy: INT;
IF skipAlternative THEN RETURN;
IF tinyPaint THEN {
xw, yw: INT ← 0;
path: Graphics.Path;
FOR i IN [0..text.Length[]) DO
c ← text.Fetch[i];
IF c = ' THEN {
xw ← xw+currentSpaceX;
yw ← yw+currentSpaceY; }
ELSE {
charInfo ← PressFontReader.GetCharInfo[currentFont.pressFont, c];
xw ← xw+Real.Fix[charInfo.widthX*currentFont.size];
yw ← yw+Real.Fix[charInfo.widthY*currentFont.size];
};
ENDLOOP;
Graphics.MoveTo[path, x, y];
SELECT currentFont.rotation FROM
0.0 => { x ← x+xw; y ← y+yw };
90.0 => { x ← x-yw; y ← y+xw };
180.0 => { x ← x-xw; y ← y-yw };
270.0 => { x ← x+yw; y ← y-xw };
ENDCASE => ERROR;
Graphics.LineTo[path, x, y];
Graphics.DrawStroke[context, path];
}
ELSE {
Cull unrotated characters obviously outside the context
IF currentFont.rotation = 0.0 THEN {
box: Graphics.Box ← Graphics.GetBounds[context];
cpX, cpY: REAL;
[cpX, cpY] ← Graphics.GetCP[context];
IF box.ymax < cpY+currentFontYMin OR box.ymin > cpY+currentFontYMax THEN RETURN;
};
FOR i IN [0..text.Length[]) DO
c ← text.Fetch[i];
IF c = ' THEN {
dx ← currentSpaceX;
dy ← currentSpaceY; }
ELSE {
mark: Graphics.Mark ← Graphics.Save[context];
charInfo ← PressFontReader.GetCharInfo[currentFont.pressFont, c];
Graphics.Scale[context, micasPerPoint, micasPerPoint];
Graphics.Rotate[context, currentFont.rotation];
Graphics.DrawChar[context, c, currentFont.screenFont];
Graphics.Restore[context, mark];
dx ← Real.Fix[charInfo.widthX*currentFont.size];
dy ← Real.Fix[charInfo.widthY*currentFont.size]; };
SELECT currentFont.rotation FROM
0.0 => { x ← x+dx; y ← y+dy };
90.0 => { x ← x-dy; y ← y+dx };
180.0 => { x ← x-dx; y ← y-dy };
270.0 => { x ← x+dy; y ← y-dx };
ENDCASE => ERROR;
Graphics.SetCP[context, x, y];
ENDLOOP;
};
}; -- showCharactersProc
fontProc: PressReader.FontProc = {
IF skipAlternative THEN RETURN;
currentFont ← show.fontTable[entityTrailer.fontSet*16+font];
IF currentFont.screenFont # NIL THEN {
[ymin: currentFontYMin, ymax: currentFontYMax] ← Graphics.FontBox[currentFont.screenFont];
currentFontYMin ← micasPerPoint * currentFontYMin;
currentFontYMax ← micasPerPoint * currentFontYMax;
}
ELSE {
currentFontYMin ← FIRST[INTEGER];
currentFontYMax ← LAST[INTEGER];
};
IF currentFont.pressFont = NIL THEN RETURN;
spacingProc[resetSpace, 0];
};
positionProc: PressReader.PositionProc = {
IF skipAlternative THEN RETURN;
IF opCode = setX THEN x ← entityTrailer.Xe + value
ELSE y ← entityTrailer.Ye + value;
Graphics.SetCP[context, x, y];
};
spacingProc: PressReader.SpacingProc = {
IF skipAlternative THEN RETURN;
IF currentFont.pressFont = NIL THEN ERROR;
SELECT opCode FROM
setSpaceX, setSpaceXShort => currentSpaceX ← value;
setSpaceY, setSpaceYShort => currentSpaceY ← value;
resetSpace => {
charInfo: PressFontReader.CharInfo ← PressFontReader.GetCharInfo[currentFont.pressFont, ' ];
currentSpaceX ← Real.Fix[charInfo.widthX*currentFont.size];
currentSpaceY ← Real.Fix[charInfo.widthY*currentFont.size]; };
ENDCASE => ERROR;
};
spaceProc: PressReader.SpaceProc = {
IF skipAlternative THEN RETURN;
SELECT currentFont.rotation FROM
0.0 => { x ← x+currentSpaceX; y ← y+currentSpaceY };
90.0 => { x ← x-currentSpaceY; y ← y+currentSpaceX };
180.0 => { x ← x-currentSpaceX; y ← y-currentSpaceY };
270.0 => { x ← x+currentSpaceY; y ← y-currentSpaceX };
ENDCASE => ERROR;
Graphics.SetCP[context, x, y];
};
colorProc: PressReader.ColorProc = {
color: Graphics.Color;
IF skipAlternative THEN RETURN;
SELECT opCode FROM
setHue => hue ← REAL[value]/255.0;
setSaturation => saturation ← REAL[value]/255.0;
setBrightness => brightness ← REAL[value]/255.0;
ENDCASE => ERROR;
color ← GraphicsColor.HSVToColor[hue, saturation, brightness];
Graphics.SetColor[context, color];
};
showRectangleProc: PressReader.ShowRectangleProc = {
IF skipAlternative THEN RETURN;
Graphics.DrawBox[context, Graphics.Box[x, y, x+width, y+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;
};
showObjectProc: PressReader.ShowObjectProc = {
path: Graphics.Path ← Graphics.NewPath[];
moveToProc: PressReader.MoveToProc = {Graphics.MoveTo[self: path, x: x+entityTrailer.Xe, y: y+entityTrailer.Ye, flush: FALSE];};
drawToProc: PressReader.DrawToProc = {Graphics.LineTo[self: path, x: x+entityTrailer.Xe, y: y+entityTrailer.Ye];};
drawCurveProc: PressReader.DrawCurveProc = {
lpX, lpY: REAL;
bezier: CGCubic.Bezier;
[lpX, lpY] ← Graphics.LastPoint[path];
bezier ← CGCubic.CoeffsToBezier[CGCubic.Coeffs[
c0: GraphicsBasic.Vec[lpX, lpY],
c1: GraphicsBasic.Vec[cX+entityTrailer.Xe, cY+entityTrailer.Ye],
c2: GraphicsBasic.Vec[bX+entityTrailer.Xe, bY+entityTrailer.Ye],
c3: GraphicsBasic.Vec[aX+entityTrailer.Xe, aY+entityTrailer.Ye]]];
Graphics.CurveTo[self: path,
x1: bezier.b1.x, y1:bezier.b1.y,
x2: bezier.b2.x, y2: bezier.b2.y,
x3: bezier.b3.x, y3: bezier.b3.y]; };
IF skipAlternative THEN RETURN;
show.pressFile.GetObject[[moveToProc, drawToProc, drawCurveProc]];
Graphics.DrawArea[self: context, path: path, parityFill: TRUE];
}; -- showObjectProc
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]*pointsPerMica;
windowHeight ← REAL[height]*pointsPerMica;
};
dotsFollowProc: PressReader.DotsFollowProc = {
dotInfo ← dots;
};
IF skipAlternative THEN RETURN;
show.pressFile.GetDots[[setCodingProc, setModeProc, setWindowProc, setSizeProc, 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 ];
Graphics.Scale[context, micasPerPoint, micasPerPoint];
PressImage.DrawPressImage[context, image];
Graphics.Restore[context, mark];
EXITS
Quit => RETURN;
}; -- showDotsProc
fontProc[0]; -- SetFont 0; ResetSpace;
show.pressFile.GetCommands[PressReader.CommandProcs[
showCharactersProc: showCharactersProc,
fontProc: fontProc,
positionProc: positionProc,
spacingProc: spacingProc,
spaceProc: spaceProc,
colorProc: colorProc,
showRectangleProc: showRectangleProc,
alternativeProc: alternativeProc,
showObjectProc: showObjectProc,
showDotsProc: showDotsProc]];
}; -- EntityProc
show.pressFile.GetPage[EntityProc];
}; -- 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] = {
show.pressFile.ClosePressFile[];
PressFontReader.Close[show.pressFontFile];
};
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