ShowPressImpl.mesa
Last edited by Shore; December 7, 1982 1:38 pm
DIRECTORY
CGCubic USING [Bezier, Coeffs, CoeffsToBezier],
Graphics USING [Box, Color, Context, CurveTo, DrawArea, DrawBox, DrawChar, DrawStroke, FontRef, LastPoint, LineTo, Mark, MoveTo, NewPath, Path, Restore, Rotate, Save, Scale, SetColor, SetCP, SetFat],
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
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 {
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.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]];
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