SilDisplayUtilsImplA.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited by Ken Pier, August 22, 1985 6:38:51 pm PDT
A module implementing some display service routines.
DIRECTORY
Atom USING
[MakeAtom],
Imager USING
[Color, Context, Error, MaskRectangleI, --MaskVector, SetStrokeEnd, SetStrokeWidth, --SetXYI, SetColor, SetFont, ShowRope, white, black],
ImagerBackdoor USING
[MakeStipple],
ImagerFont USING
[Font, FontBoundingBox, Scale, Find, Modify],
ImagerOps USING
[KindOf],
ImagerTransformation USING
[Scale2, Transformation],
IO USING
[GetInt, RIS],
NodeStyle USING
[FontFace, FontAlphabets],
NodeStyleFont USING
[FontFromStyleParams],
Real USING
[Fix],
Rope USING
[Concat, Fetch, Find, Length, Replace, ROPE, SkipTo, Substr],
SilColor,
SilCommand,
SilDisplayInternal,
SilDisplayUtils,
SilFile,
SilKernel,
ViewRec USING [SampleRV]
;
SilDisplayUtilsImplA: CEDAR MONITOR
IMPORTS Atom, Imager, ImagerBackdoor, ImagerFont, ImagerOps, ImagerTransformation, IO, NodeStyleFont, Real, Rope, ViewRec, SilKernel, SilFile, SilColor
EXPORTS SilDisplayUtils, SilKernel = BEGIN OPEN SilFile;
ROPE: TYPE = Rope.ROPE;
SilData: TYPE = SilKernel.SilData;
SilDisplayData: TYPE = REF SilDisplayDataRec;
SilDisplayDataRec: PUBLIC TYPE = SilDisplayInternal.SilDisplayDataRec;
SilModel: TYPE = SilFile.SilModel;
SilUIData: TYPE = SilKernel.SilUIData;
GLOBAL VARIABLES:
Font Refs for Fonts
allModelsFonts: ARRAY SilFile.InternalPresetFonts OF ImagerFont.Font; -- current fonts
allModelsFontsAscents: ARRAY SilFile.InternalPresetFonts OF INTEGER; -- current fonts ascents
allModelsItalicFonts: ARRAY SilFile.InternalPresetFonts OF ImagerFont.Font;
allModelsItalicFontsAscents: ARRAY SilFile.InternalPresetFonts OF INTEGER;
allModelsPFonts: ARRAY SilFile.InternalPresetFonts OF ImagerFont.Font; -- printing fonts
allModelsPFontsAscents: ARRAY SilFile.InternalPresetFonts OF INTEGER; -- printing fonts ascents
allModelsItalicPFonts: ARRAY SilFile.InternalPresetFonts OF ImagerFont.Font;
allModelsItalicPFontsAscents: ARRAY SilFile.InternalPresetFonts OF INTEGER;
allModelsDFonts: ARRAY SilFile.InternalPresetFonts OF ImagerFont.Font; -- display fonts
allModelsDFontsAscents: ARRAY SilFile.InternalPresetFonts OF INTEGER; -- display fonts ascents
allModelsItalicDFonts: ARRAY SilFile.InternalPresetFonts OF ImagerFont.Font;
allModelsItalicDFontsAscents: ARRAY SilFile.InternalPresetFonts OF INTEGER;
fontState: SilFile.FontType ← display;
selectGrey: Imager.Color ← ImagerBackdoor.MakeStipple[122645B];
backgroundGrey: Imager.Color ← ImagerBackdoor.MakeStipple[102041B];
selectedBackgroundGrey: Imager.Color ← ImagerBackdoor.MakeStipple[100000B];
SilUtilsInit: PUBLIC PROC [] = {
Set all the global arrays that have to do with font refs (allModelsFonts, ... and the command variables) so that the correct info is available for future use.
SilPrintFontsInit[]; -- this must be called before SilDisplayFontsInit is called !!
SilDisplayFontsInit[];
UpEndFonts[]; -- turn fonts upside down to match Sil coordinate system with Y pointing down
UsePrintFonts[]; -- required upon initialization because Sil files carry print font sizes internally
};
UpEndFonts: PROC [] RETURNS [] ~ {
this proc turns fonts upside down and swaps ascenders with descenders for positioning
xform: ImagerTransformation.Transformation ← ImagerTransformation.Scale2[s: [1.0, -1.0]];
FOR i: SilFile.InternalPresetFonts IN SilFile.InternalPresetFonts DO
allModelsPFonts[i] ← ImagerFont.Modify[font: allModelsPFonts[i], m: xform];
allModelsPFontsAscents[i] ← Real.Fix[ImagerFont.FontBoundingBox[allModelsPFonts[i]].descent];
allModelsItalicPFonts[i] ← ImagerFont.Modify[font: allModelsItalicPFonts[i], m: xform];
allModelsItalicPFontsAscents[i] ← Real.Fix[ImagerFont.FontBoundingBox[allModelsItalicPFonts[i]].descent];
allModelsDFonts[i] ← ImagerFont.Modify[font: allModelsDFonts[i], m: xform];
allModelsDFontsAscents[i] ← Real.Fix[ImagerFont.FontBoundingBox[allModelsDFonts[i]].descent];
allModelsItalicDFonts[i] ← ImagerFont.Modify[font: allModelsItalicDFonts[i], m: xform];
allModelsItalicDFontsAscents[i] ← Real.Fix[ImagerFont.FontBoundingBox[allModelsItalicDFonts[i]].descent];
ENDLOOP;
};
SilPrintFontsInit: PROC [] = {
tFont: ImagerFont.Font ← NIL;
fontNamePrefix: ROPE = "xerox/pressfonts/";
FOR fontIndex: PresetFonts IN PresetFonts DO
fShortName: ROPE ← SilFile.FontNameFromInternalFont[fontIndex, print];
isBold, isItalic: BOOLFALSE;
Get the font family separate from its size. (e.g. Helvetica7 -> Helvetica, 7)
fSize, length: INTEGER ← 0;
controlPos: INTEGER ← fShortName.SkipTo[0, "0123456789"];
control: ROPE ← fShortName.Substr[controlPos, fShortName.Length[] - controlPos];
fName: ROPE ← Rope.Concat[fontNamePrefix, fShortName.Substr[0, controlPos] ];
fTemp, fSuccessful: ROPE;
Check for control characters (e.g. Helvetica7B -> Helvetica, 7, bold)
IF Rope.Find[s1: control, s2: "B", case: FALSE] # -1 THEN isBold ← TRUE;
IF Rope.Find[s1: control, s2: "I", case: FALSE] # -1 THEN isItalic ← TRUE;
fName ← Rope.Concat[fName, "-"];
IF isBold THEN fName ← Rope.Concat[fName, "B"] ELSE fName ← Rope.Concat[fName, "M"];
IF isItalic THEN fName ← Rope.Concat[fName, "I"] ELSE fName ← Rope.Concat[fName, "R"];
fName ← Rope.Concat[fName, "R"]; -- no more narrow fonts
fTemp ← fName;
length ← Rope.Length[fName];
change the character rep for the size to an integer rep
fSize ← IO.GetInt[IO.RIS[control]];
fSuccessful ← fName;
tFont ← ImagerFont.Find[fName ! Imager.Error => {
fName ← Rope.Replace[fName, length - 3, 3, "MRR"];
fSuccessful ← fName;
RETRY;
};];
tFont ← allModelsPFonts[fontIndex*2] ← ImagerFont.Scale[tFont, fSize];
allModelsPFontsAscents[fontIndex*2] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
fName ← Rope.Replace[fName, length - 3, 1, "B"];
tFont ← ImagerFont.Find[fName ! Imager.Error => {fName ← fSuccessful; RETRY; };];
tFont ← allModelsPFonts[fontIndex*2 + 1] ← ImagerFont.Scale[tFont, fSize];
allModelsPFontsAscents[fontIndex*2 + 1] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
fTemp ← Rope.Replace[fTemp, length - 2, 1, "I"];
fSuccessful ← fTemp;
tFont ← ImagerFont.Find[fTemp ! Imager.Error => {
fTemp ← Rope.Replace[fTemp, length - 3, 3, "MRR"];
fSuccessful ← fTemp; RETRY; };];
tFont ← allModelsItalicPFonts[fontIndex*2] ← ImagerFont.Scale[tFont, fSize];
allModelsItalicPFontsAscents[fontIndex*2] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
fTemp ← Rope.Replace[fTemp, length - 3, 1, "B"];
tFont ← ImagerFont.Find[fTemp ! Imager.Error => {fTemp ← fSuccessful; RETRY;};];
tFont ← allModelsItalicPFonts[fontIndex*2 + 1] ← ImagerFont.Scale[tFont, fSize];
allModelsItalicPFontsAscents[fontIndex*2 + 1] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
ENDLOOP;
};
SilDisplayFontsInit: PROC [] = {
FindFont: PROC [index: InternalPresetFonts, prefix: ATOM, family: Rope.ROPE, face: NodeStyle.FontFace, size: REAL, alphabets: NodeStyle.FontAlphabets] RETURNS [ImagerFont.Font] ~ {
f: ImagerFont.Font ← NodeStyleFont.FontFromStyleParams[prefix: prefix, family: Atom.MakeAtom[family], face: face, size: size, alphabets: alphabets];
IF Rope.Find[s1: f.name, s2: family, case: FALSE] = -1 THEN RETURN[IF face=Italic OR face=BoldItalic THEN allModelsItalicPFonts[index] ELSE allModelsPFonts[index]];
RETURN[f];
};
tFont: ImagerFont.Font;
isBold, isItalic: BOOLFALSE;
fSize: INTEGER ← 0;
face: NodeStyle.FontFace;
fontNamePrefix: ATOM = Atom.MakeAtom["xerox/tiogafonts/"];
FOR fontIndex: PresetFonts IN PresetFonts DO
fShortName: ROPE ← SilFile.FontNameFromInternalFont[fontIndex, display];
Get the font family separate from its face and size. (e.g. Helvetica7B-> Helvetica, 7, bold)
controlPos: INTEGER ← fShortName.SkipTo[0, "0123456789"];
control: ROPE ← fShortName.Substr[controlPos, fShortName.Length[] - controlPos];
fName: ROPE ← fShortName.Substr[0, controlPos];
IF Rope.Find[s1: control, s2: "B", case: FALSE] # -1 THEN isBold ← TRUE;
IF Rope.Find[s1: control, s2: "I", case: FALSE] # -1 THEN isItalic ← TRUE;
face ← SELECT TRUE FROM
isBold AND isItalic => BoldItalic,
isBold => Bold,
isItalic => Italic,
ENDCASE => Regular;
change the character rep for the size to an integer rep
fSize ← IO.GetInt[IO.RIS[control]];
NodeStyleFont will perform font substitution (unfortunately)
tFont ← allModelsDFonts[fontIndex*2] ← FindFont[index: fontIndex*2, prefix: fontNamePrefix, family: fName, face: face, size: fSize, alphabets: CapsAndLower];
allModelsDFontsAscents[fontIndex*2] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
tFont ← allModelsDFonts[fontIndex*2 + 1] ← FindFont[index: fontIndex*2 + 1, prefix: fontNamePrefix, family: fName, face: Bold, size: fSize, alphabets: CapsAndLower];
allModelsDFontsAscents[fontIndex*2 + 1] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
tFont ← allModelsItalicDFonts[fontIndex*2] ← FindFont[index: fontIndex*2, prefix: fontNamePrefix, family: fName, face: Italic, size: fSize, alphabets: CapsAndLower];
allModelsItalicDFontsAscents[fontIndex*2] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
tFont ← allModelsItalicDFonts[fontIndex*2 + 1] ← FindFont[index: fontIndex*2 + 1, prefix: fontNamePrefix, family: fName, face: BoldItalic, size: fSize, alphabets: CapsAndLower];
allModelsItalicDFontsAscents[fontIndex*2 + 1] ← Real.Fix[ImagerFont.FontBoundingBox[tFont].ascent];
ENDLOOP;
};
GetFont: PUBLIC PROC [font: SilFile.InternalFonts, italic: BOOLFALSE] RETURNS [fontRef: ImagerFont.Font] = {
Return the font description for a given internal Font( number).
IF italic THEN RETURN [allModelsItalicFonts[font]] ELSE RETURN[allModelsFonts[font]];
};
UsePrintFonts: ENTRY PROC [] = {
allModelsFonts ← allModelsPFonts; -- transfer entire array
allModelsFontsAscents ← allModelsPFontsAscents; -- transfer entire array
allModelsItalicFonts ← allModelsItalicPFonts; -- transfer entire array
allModelsItalicFontsAscents ← allModelsItalicPFontsAscents; -- transfer entire array
fontState ← print;
};
UseDisplayFonts: ENTRY PROC [] = {
allModelsFonts ← allModelsDFonts; -- transfer entire array
allModelsFontsAscents ← allModelsDFontsAscents; -- transfer entire array
allModelsItalicFonts ← allModelsItalicDFonts; -- transfer entire array
allModelsItalicFontsAscents ← allModelsItalicDFontsAscents; -- transfer entire array
fontState ← display;
};
SwapFonts: PUBLIC PROC [data: SilData, ctx: Imager.Context] = {
toggle display font between "normal" and "hardcopy" display
IF fontState = display THEN UsePrintFonts[] ELSE UseDisplayFonts[];
SilKernel.RepaintSilViewers[];
};
ChangeCommandLineData: PUBLIC PROC [data: SilData, ctx: Imager.Context, change: SilDisplayUtils.CommandChange ← Pos, boolArg: BOOLFALSE, intArg1: INTEGER ← 0, intArg2: INTEGER ← 0] = {
Modify the Command Line data for this window to reflect the new info. Depending on change one or more of the arguments will be used to supply interesting values. In all cases except when change is pos, the display data of the Sil will be updated.
dData: SilDisplayData ← data.displayData;
commandLine: SilCommand.CommandRef ← NARROW[dData.commandLine];
SELECT change FROM
Bold => {
dData.currentBoldState ← boolArg;
};
Italic => {
dData.currentItalicState ← boolArg;
};
Grid => {
commandLine.Grid ← dData.currentGridSpacing ← intArg1;
};
LineWidth => {
commandLine.LineW ← dData.currentBoxWidth ← intArg1;
};
Mag => {
commandLine.Mag ← dData.currentMagnification ← intArg1;
};
Font => {
commandLine.Font ← dData.currentFont ← intArg1;
};
Color => {
dData.currentColor ← intArg1;
commandLine.Color ← intArg1;
commandLine.Color ← SilColor.silCChars[intArg1]; --look up color char
};
MacExpand => {
commandLine.MX ← dData.currentOneLevel ← boolArg;
};
Ylock => {
commandLine.Ylk ← dData.yLock ← boolArg;
};
Selections => {
commandLine.Selected ← dData.currentNumObjectsSelected ← intArg1;
};
Pos => {
commandLine.X ← intArg1;
commandLine.Y ← intArg2;
};
ENDCASE => ERROR;
ViewRec.SampleRV[dData.viewRec];
};
PaintObject: PUBLIC PROC [model: SilModel, sobr: SilObjectRec, dMode: SilDisplayUtils.DisplayChoice, ctx: Imager.Context, oneLevel, foregroundOnly: BOOLEANFALSE, print: BOOLEANFALSE] = {
Paint one Sil Object on the screen
SELECT dMode FROM
show => Imager.SetColor[ctx, IF ImagerOps.KindOf[ctx] = $Bitmap THEN Imager.black ELSE SilColor.silColors[sobr.color]];
erase => Imager.SetColor[ctx, Imager.white];
select => Imager.SetColor[ctx, selectGrey];
ENDCASE; --no need to optimize calls to SetColor
SELECT sobr.font FROM
IN InternalPresetFonts => {
fontRef: ImagerFont.Font;
fontAscent: INTEGER ← 0;
notPrint: BOOLNOT print;
notItalic: BOOLNOT sobr.italic;
SELECT TRUE FROM
notItalic AND notPrint => {
fontRef ← allModelsFonts[sobr.font];
fontAscent ← allModelsFontsAscents[sobr.font];
};
notItalic AND print => {
fontRef ← allModelsPFonts[sobr.font];
fontAscent ← allModelsPFontsAscents[sobr.font];
};
sobr.italic AND notPrint => {
fontRef ← allModelsItalicFonts[sobr.font];
fontAscent ← allModelsItalicFontsAscents[sobr.font];
};
sobr.italic AND print => {
fontRef ← allModelsItalicPFonts[sobr.font];
fontAscent ← allModelsItalicPFontsAscents[sobr.font];
};
ENDCASE => ERROR;
Imager.SetXYI[ctx, sobr.xMin, sobr.yMin + fontAscent]; --Put where belongs
Imager.SetFont[ctx, fontRef]; --set the new font
Imager.ShowRope[ctx, sobr.value];
};
IN InternalMacroFonts => {
needFinalRepaint: BOOLEANFALSE;
currentX: INTEGER ← sobr.xMin;
currentY: INTEGER ← sobr.yMin;
FOR i: INT IN [0..Rope.Length[sobr.value]) DO
c: CHAR ← Rope.Fetch[sobr.value, i];
mxMin, mxMax : INTEGER;
[xMin: mxMin, yMin: , xMax: mxMax, yMax: ] ←
SilFile.GetMacroBoundingBox[model, sobr.font, c];
FOR s: SilObject ← GetObjectList[model, macro, sobr.font, c], s.rest WHILE s # NIL DO
macElem: SilObjectRec ← s.first;
macElem.xMin ← macElem.xMin + currentX;
macElem.yMin ← macElem.yMin + currentY;
macElem.xMax ← macElem.xMax + currentX;
macElem.yMax ← macElem.yMax + currentY;
macElem.color ← sobr.color;
If a library uses a macro, it must be a macro in its own font
IF macElem.font IN SilFile.InternalFileMacroFonts THEN
macElem.font ← sobr.font;
PaintObject[model, macElem, dMode, ctx, oneLevel, foregroundOnly, print];
IF macElem.font IN InternalBackgroundBoxFonts THEN needFinalRepaint ← TRUE;
ENDLOOP;
foreground objects may have been obscured by other repainting
IF needFinalRepaint THEN {
FOR s: SilObject ← GetObjectList[model, macro, sobr.font, c ], s.rest WHILE s # NIL DO
macElem: SilObjectRec ← s.first;
macElem.xMin ← macElem.xMin + currentX;
macElem.yMin ← macElem.yMin + currentY;
macElem.xMax ← macElem.xMax + currentX;
macElem.yMax ← macElem.yMax + currentY;
macElem.color ← sobr.color;
PaintObject[model, macElem, dMode, ctx, TRUE, TRUE, print];
ENDLOOP;
needFinalRepaint ← FALSE;
};
currentX ← currentX + mxMax - mxMin;
ENDLOOP;
};
IN InternalForegroundBoxFonts => {
Imager.MaskRectangleI[ctx, sobr.xMin, sobr.yMin, sobr.xMax - sobr.xMin, sobr.yMax - sobr.yMin];
};
IN InternalBackgroundBoxFonts => {
IF foregroundOnly THEN RETURN;
SELECT dMode FROM
erase => Imager.MaskRectangleI[ctx, sobr.xMin, sobr.yMin, sobr.xMax - sobr.xMin, sobr.yMax - sobr.yMin];
show, select => {
sSel: SilSelection ← GetSelection[];
IF dMode = show THEN Imager.SetColor[ctx, backgroundGrey]
ELSE {
Imager.SetColor[ctx, Imager.white];
Imager.MaskRectangleI[ctx, sobr.xMin, sobr.yMin, sobr.xMax - sobr.xMin, sobr.yMax - sobr.yMin];
Imager.SetColor[ctx, selectedBackgroundGrey];
};
Imager.MaskRectangleI[ctx, sobr.xMin, sobr.yMin, sobr.xMax - sobr.xMin, sobr.yMax - sobr.yMin];
now traverse the entire model and paint over this background box with foreground objects. oneLevel will be true if you are here because you are doing a nested traversal of the model, in which case you stop traversal. This parameter called oneLevel has nothing to do with the Sil parameter called OneLevel in the Sil Command line.
IF oneLevel THEN RETURN;
FOR s: SilObject ← GetObjectList[model: model, mode: fgnd], s.rest WHILE s # NIL DO
IF IBBoxFilter[sobr.xMin, sobr.yMin, sobr.xMax, sobr.yMax, s.first]
THEN PaintObject[model, s.first, show, ctx, TRUE, FALSE, print];
ENDLOOP;
IF sSel.model = model THEN
FOR s: SilObject ← sSel.objects, s.first.selectObj WHILE s # sSel.lastObject DO
IF NOT SilFile.ObjectIsSelected[model, s] AND IBBoxFilter[sobr.xMin, sobr.yMin, sobr.xMax, sobr.yMax, s.first] THEN PaintObject[model, s.first, select, ctx, TRUE, FALSE, print];
ENDLOOP;
};
ENDCASE;
};
ENDCASE;
};
IBBoxFilter: PROC [xMin, yMin, xMax, yMax: INTEGER, sobr: SilObjectRec] RETURNS [BOOL] = INLINE {
RETURN TRUE if some part of sobr appears inside the box.
RETURN[ NOT (yMin > sobr.yMax OR xMin > sobr.xMax OR yMax < sobr.yMin OR xMax < sobr.xMin)];
};
END.
yy: REAL ← sobr.yMin+(sobr.yMax - sobr.yMin)/2.0;
Imager.SetStrokeEnd[ctx, butt];
Imager.SetStrokeWidth[ctx, sobr.yMax - sobr.yMin];
Imager.MaskVector[ctx, [x: sobr.xMin, y: yy ], [x: sobr.xMax, y: yy]]