ArtworkRuleImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Rick Beach, March 11, 1986 10:28:50 am PST
Michael Plass, February 12, 1987 11:09:35 am PST
DIRECTORY
Convert USING [RealFromLiteral],
Imager USING [Box, DoSave, MaskBox, SetColor, Trans],
NodeProps USING [],
NodeStyle USING [GetFirstIndent, GetFontSize, GetLeftIndent, GetLineFormatting, GetLineLength, GetReal, GetRightIndent, Ref],
Real USING [Round],
Rope USING [Fetch, ROPE, Run, Size],
RuntimeError USING [UNCAUGHT],
Scaled USING [Float, FromReal],
TEditFormat USING [ArtworkClass, ArtworkClassRep, ArtworkEnabled, BoundingBoxProc, CharPositionProc, FormatProc, GetColor, PaintProc, RegisterArtwork, ResolveProc],
TextEdit USING [GetRope, RefTextNode, Size],
ViewerOps USING [BlinkDisplay, PaintEverything];
ArtworkRuleImpl: CEDAR PROGRAM
IMPORTS Convert, Imager, NodeStyle, Real, Rope, RuntimeError, Scaled, TEditFormat, TextEdit, ViewerOps
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
debug: BOOLEANFALSE;
Format: TEditFormat.FormatProc ~ {
inner: PROC ~ {
extraIndent: REAL ← nodeStyle.GetFirstIndent;
leftIndent: REAL ← nodeStyle.GetLeftIndent + extraIndent;
rightIndent: REAL ← nodeStyle.GetRightIndent;
lineLength: REAL ~ nodeStyle.GetLineLength;
trimmedLineWidth: REAL ~
(IF lineLength > 0.0 AND lineLength < lineWidth.Float THEN lineLength ELSE lineWidth.Float) - leftIndent - rightIndent;
ruleThickness: REAL ← 0.0;
ruleLength: REAL ← 0.0;
[ruleThickness, ruleLength] ← GetRule[node, nodeStyle ! RuntimeError.UNCAUGHT => {ViewerOps.BlinkDisplay[]; CONTINUE}];
IF ruleLength = 0 THEN ruleLength ← trimmedLineWidth;
lineInfo.xmin ← 0;
lineInfo.ymin ← 0;
lineInfo.xmax ← Ceiling[ruleLength];
lineInfo.ymax ← Ceiling[ruleThickness];
SELECT nodeStyle.GetLineFormatting[] FROM
FlushLeft, Justified => {lineInfo.xOffset ← Scaled.FromReal[leftIndent]};
FlushRight => {lineInfo.xOffset ← Scaled.FromReal[MAX[lineWidth.Float-leftIndent-ruleLength, 0]]};
Centered => {lineInfo.xOffset ← Scaled.FromReal[leftIndent+(trimmedLineWidth-ruleLength)/2]};
ENDCASE => ERROR;
};
lineInfo.startPos ← [node, 0];
lineInfo.nextPos ← [node, TextEdit.Size[node]];
lineInfo.nChars ← TextEdit.Size[node];
IF lineInfo.formatInfo.length = 0 THEN {
we should be the only client for this format entry
lineInfo.formatInfo[lineInfo.formatInfo.length].color ← TEditFormat.GetColor[nodeStyle];
lineInfo.formatInfo.length ← lineInfo.formatInfo.length + 1;
};
inner[ ! RuntimeError.UNCAUGHT => {IF NOT debug THEN {ViewerOps.BlinkDisplay[]; CONTINUE}}];
};
Resolve: TEditFormat.ResolveProc ~ {
loc ← lineInfo.startPos;
xmin ← lineInfo.xmin+lineInfo.xOffset.integerPart;
width ← lineInfo.xmax;
rightOfLine ← FALSE;
};
CharPosition: TEditFormat.CharPositionProc ~ {
x ← lineInfo.xmin+lineInfo.xOffset.integerPart;
width ← lineInfo.xmax;
};
BoundingBox: TEditFormat.BoundingBoxProc ~ {
RETURN [[lineInfo.xmin, lineInfo.ymin, lineInfo.xmax, lineInfo.ymax]]
};
Paint: TEditFormat.PaintProc ~ {
inner: PROC ~ {
IF lineInfo.formatInfo.length > 0 AND lineInfo.formatInfo[0].color # NIL THEN {
Imager.SetColor[context, lineInfo.formatInfo[0].color];
};
Imager.Trans[context];
Imager.MaskBox[context, box];
};
box: Imager.Box ~ BoundingBox[lineInfo, lineInfo.startPos.where, lineInfo.nChars];
Imager.DoSave[context, inner];
};
pointsPerMeter: REAL ← 72/0.0254;
GetRule: PROC [node: TextEdit.RefTextNode, nodeStyle: NodeStyle.Ref] RETURNS [thickness, length: REAL ← 0.0] ~ {
returns the length and thickness of the typographic rule defined by the content of the node
rope: ROPE ~ TextEdit.GetRope[node];
size: INT ~ Rope.Size[rope];
IF size # 0 THEN {
i: INT ← -1;
Getc: PROC RETURNS [CHAR] ~ {i←i+1; RETURN [IF i<size THEN rope.Fetch[i] ELSE ' ]};
c: CHAR ← Getc[];
Invariant: c = (IF i<size THEN rope.Fetch[i] ELSE ' )
startTok: INT ← 0;
sizeTok: INT ← 0;
GetTok: PROC ~ {
startTok ← i;
UNTIL c = ' DO c ← Getc[] ENDLOOP;
sizeTok ← i-startTok;
WHILE c = ' AND i<size DO c ← Getc[] ENDLOOP;
};
GetReal: PROC RETURNS [r: REAL] ~ {
r ← 1.0;
IF c = '- THEN {r ← -r; c ← Getc[]};
GetTok[];
r ← r*Convert.RealFromLiteral[rope, startTok];
GetTok[];
SELECT TRUE FROM
Match["mm"] => r ← r*0.001;
Match["cm"] => r ← r*0.01;
Match["in"] => r ← r*0.0254;
Match["pt"] => r ← r*0.0254/72.27;
Match["pc"] => r ← r*12*0.0254/72.27;
Match["bp"] => r ← r*0.0254/72;
ENDCASE => ERROR;
r ← r*pointsPerMeter;
};
Match: PROC [key: ROPE] RETURNS [BOOL] ~ {
k: INT ~ Rope.Size[key];
RETURN [sizeTok = k AND Rope.Run[rope, startTok, key, 0, FALSE] = k]
};
WHILE c = ' AND i<size DO c ← Getc[] ENDLOOP;
UNTIL i>=size DO
GetTok[];
SELECT rope.Fetch[startTok] FROM
'- => thickness ← 0.4;
'— => thickness ← 0.4;
'= => thickness ← 1.0;
'~ => thickness ← 0.8*NodeStyle.GetFontSize[nodeStyle];
'# => thickness ← 0.8*NodeStyle.GetFontSize[nodeStyle];
ENDCASE => {
SELECT TRUE FROM
Match["thickness:"] => thickness ← GetReal[];
Match["length:"] => length ← GetReal[];
ENDCASE => ERROR;
};
ENDLOOP;
}
ELSE {
thickness ← 1.0;
length ← NodeStyle.GetLineLength[nodeStyle];
};
};
Floor: PROC [r: REAL] RETURNS [i: INT] ~ {
i ← Real.Round[r];
IF i > r THEN i ← i-1;
};
Ceiling: PROC [r: REAL] RETURNS [i: INT] ~ {
i ← Real.Round[r];
IF i < r THEN i ← i+1;
};
class: TEditFormat.ArtworkClass ~ NEW[TEditFormat.ArtworkClassRep ← [
name: $Rule,
format: Format,
paint: Paint,
resolve: Resolve,
charPosition: CharPosition,
boundingBox: BoundingBox
]];
TEditFormat.RegisterArtwork[class];
IF TEditFormat.ArtworkEnabled[] THEN ViewerOps.PaintEverything[];
END.