ArtworkRuleImpl.mesa
Copyright Ó 1986, 1987, 1989, 1990, 1992 by Xerox Corporation. All rights reserved.
Rick Beach, March 11, 1986 10:28:50 am PST
Michael Plass, March 24, 1992 12:25 pm PST
Doug Wyatt, October 10, 1990 10:47 am PDT
DIRECTORY
Convert USING [RealFromLiteral],
Imager USING [Box, DoSave, MaskBox, SetColor, Trans],
NodeProps USING [],
NodeStyle USING [GetColor, GetReal, GetLineFormatting, Ref],
Real USING [Round],
Rope USING [Fetch, ROPE, Run, Size],
RuntimeError USING [UNCAUGHT],
Scaled USING [Float, Floor, FromReal],
TEditFormat USING [ArtworkClass, ArtworkClassRep, BoundingBoxProc, CharPositionProc, FormatProc, PaintProc, RegisterArtwork, ResolveProc],
TextEditBogus USING [GetRope],
TextEdit USING [RefTextNode, Size];
ArtworkRuleImpl: CEDAR PROGRAM
IMPORTS Convert, Imager, NodeStyle, Real, Rope, RuntimeError, Scaled, TEditFormat, TextEditBogus, TextEdit
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
debug: BOOLEAN ¬ FALSE;
Format: TEditFormat.FormatProc ~ {
inner: PROC ~ {
extraIndent: REAL ¬ nodeStyle.GetReal[$firstIndent];
leftIndent: REAL ¬ nodeStyle.GetReal[$leftIndent] + extraIndent;
rightIndent: REAL ¬ nodeStyle.GetReal[$rightIndent];
lineLength: REAL ~ nodeStyle.GetReal[$lineLength];
trimmedLineWidth: REAL ~
(IF lineLength > 0.0 AND lineLength < Scaled.Float[lineWidth] THEN lineLength ELSE Scaled.Float[lineWidth]) - 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[Scaled.Float[lineWidth]-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 ¬ NodeStyle.GetColor[nodeStyle, text];
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+Scaled.Floor[lineInfo.xOffset];
width ¬ lineInfo.xmax;
rightOfLine ¬ FALSE;
};
CharPosition: TEditFormat.CharPositionProc ~ {
x ¬ lineInfo.xmin+Scaled.Floor[lineInfo.xOffset];
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 ~ TextEditBogus.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.GetReal[$fontSize];
'# => thickness ¬ 0.8*nodeStyle.GetReal[$fontSize];
ENDCASE => {
SELECT TRUE FROM
Match["thickness:"] => thickness ¬ GetReal[];
Match["length:"] => length ¬ GetReal[];
ENDCASE => ERROR;
};
ENDLOOP;
}
ELSE {
thickness ¬ 1.0;
length ¬ nodeStyle.GetReal[$lineLength];
};
};
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.