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
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],
NodeStyle
USING
[FontFace, FontAlphabets],
NodeStyleFont
USING
[FontFromStyleParams],
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: BOOL ← FALSE;
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: BOOL ← FALSE;
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:
BOOL ←
FALSE]
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:
BOOL ←
FALSE, 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:
BOOLEAN ←
FALSE, print:
BOOLEAN ←
FALSE] = {
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: BOOL ← NOT print;
notItalic: BOOL ← NOT 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: BOOLEAN ← FALSE;
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]]