NodeFromText:
PUBLIC
PROC [lines:
LIST
OF
ROPE, textFormat: TextFormat, fillSizes:
LIST
OF
REAL ¬
NIL, clientData:
REF ¬
NIL, click: ViewerClasses.ClickProc ¬
NIL]
RETURNS [Node] ~ {
node: Node ~
NEW[TreeGrapher.NodeRep ¬ [
data: NEW[TextDataRep ¬ [lines: lines, clientData: clientData, fillSizes: fillSizes]],
class: TextClassFromTextFormat[textFormat, click],
children: NIL
]];
RETURN [node]
};
TextClassFromTextFormat:
PROC [format: TextFormat, click: ViewerClasses.ClickProc]
RETURNS [result:
REF TreeGrapher.ClassRep] ~ {
CheckCache: RefTab.UpdateAction ~ {
PROC [found: BOOL, val: Val] RETURNS [op: UpdateOperation ← none, new: Val ← NIL];
IF found
AND
NARROW[(result ¬
NARROW[val]).classData, ClassData].click = click
THEN { result ¬ result }
ELSE {
op ¬ store;
new ¬ result ¬
NEW[TreeGrapher.ClassRep ¬ [
classData: NEW[ClassDataRep ¬ [more: format, paint: TextPaint, click: click]],
bounds: TextBounds,
attachmentPoint: TreeGrapher.DefaultAttachmentPoint
]];
};
};
RefTab.Update[textClassCache, format, CheckCache];
};
TextBounds:
PROC [self: Node]
RETURNS [Box] ~ {
classData: ClassData ~ NARROW[self.class.classData];
format: TextFormat ~ NARROW[classData.more];
fonts: LIST OF Font ¬ format.font;
text: TextData ~ NARROW[self.data];
bb: Box ¬ ImagerBox.BoxFromExtents[ImagerFont.RopeBoundingBox[format.font.first, "Bg"]];
y: REAL ¬ 0.0;
fillSize: REAL ¬ 0.0;
FOR tail:
LIST
OF
REAL ¬ text.fillSizes, tail.rest
UNTIL tail =
NIL
DO
fillSize ¬ fillSize + tail.first;
ENDLOOP;
bb.xmax ¬ bb.xmin;
FOR tail:
LIST
OF
ROPE ¬ text.lines, tail.rest
UNTIL tail =
NIL
DO
b: Box ¬ ImagerBox.BoxFromExtents[ImagerFont.RopeBoundingBox[fonts.first, tail.first]];
b.ymin ¬ b.ymin + y;
b.ymax ¬ b.ymax + y;
bb ¬ ImagerBox.BoundingBox[bb, b];
y ¬ y - format.skip;
IF fonts.rest # NIL THEN fonts ¬ fonts.rest;
ENDLOOP;
bb.xmin ¬ bb.xmin - format.bearoff.x;
bb.xmax ¬ bb.xmax + format.bearoff.x;
bb.ymin ¬ bb.ymin - format.bearoff.y;
bb.ymax ¬ bb.ymax + format.bearoff.y;
bb.ymin ¬ MIN[bb.ymin, bb.ymax - fillSize];
RETURN [bb];
};
TextPaint:
PROC [node: Node, context: Context] ~ {
classData: ClassData ~ NARROW[node.class.classData];
format: TextFormat ~ NARROW[classData.more];
fonts: LIST OF Font ¬ format.font;
text: TextData ~ NARROW[node.data];
b: Box ¬ node.layout.bounds;
y: REAL ¬ 0.0;
fillColors: LIST OF Color ¬ format.fillColors;
b.xmin ¬ b.xmin + node.layout.origin.x;
b.xmax ¬ b.xmax + node.layout.origin.x;
b.ymin ¬ b.ymin + node.layout.origin.y;
FOR tail:
LIST
OF
REAL ¬ text.fillSizes, tail.rest
UNTIL tail =
NIL
DO
b.ymax ¬ b.ymin + tail.first;
IF fillColors =
NIL
THEN { Imager.SetGray[context, 0] }
ELSE {
Imager.SetColor[context, fillColors.first];
fillColors ¬ fillColors.rest;
};
Imager.MaskBox[context, b];
b.ymin ¬ b.ymax;
ENDLOOP;
b.ymax ¬ node.layout.bounds.ymax + node.layout.origin.y;
IF b.ymax > b.ymin
THEN {
IF fillColors =
NIL
THEN Imager.SetGray[context, 0]
ELSE Imager.SetColor[context, fillColors.first];
Imager.MaskBox[context, b];
};
b.ymin ¬ node.layout.bounds.ymin + node.layout.origin.y;
Imager.SetColor[context, format.textColor];
Imager.SetFont[context, fonts.first];
FOR tail:
LIST
OF
ROPE ¬ text.lines, tail.rest
UNTIL tail =
NIL
DO
Imager.SetXY[context, [node.layout.origin.x, node.layout.origin.y+y]];
Imager.ShowRope[context, tail.first];
y ¬ y - format.skip;
IF fonts.rest #
NIL
AND tail #
NIL
THEN {
fonts ¬ fonts.rest;
Imager.SetFont[context, fonts.first];
};
ENDLOOP;
Imager.SetGray[context, 1];
Imager.MaskVector[context, [b.xmin, b.ymin], [b.xmin, b.ymax]];
Imager.MaskVector[context, [b.xmax, b.ymin], [b.xmax, b.ymax]];
Imager.MaskVector[context, [b.xmin, b.ymin], [b.xmax, b.ymin]];
Imager.MaskVector[context, [b.xmax, b.ymax], [b.xmin, b.ymax]];
};