FormatMathExpr:
PROC[class: CharacterArtworkClass, loc: TextNode.Location, style: NodeStyle.Ref, styleOps: NodeStyleOps.OfStyle]
RETURNS[CharacterArtwork] ~ {
effects: Formats math expression artwork represented by ROPE at loc.
Returns character artwork for formatted expression.
local declarations
TeXToTioga: REAL ~ 20.0; -- default scaling factor from unit-sized TeX Fonts to Tioga
mathExpr: EXPR ← NIL;
object: AlgebraClasses.Object;
displayExpr: DisplayExpr ← NIL;
displayBox: BOX ← NIL;
charArtwork: CharacterArtwork;
postfixValue, leading, topLeading, bottomLeading: ROPE ← NIL; -- for postfix properties
pointSize: REAL ← TeXToTioga; -- point size to use when rendering MEDDLE expr
linearExpr: ROPE ← NARROW[TextEdit.GetCharProp[node: loc.node, index: loc.where, name: $MeddleExpr]];
if the user specified a point size to use, get it and use it
exprPointSize: ROPE ← NARROW[TextEdit.GetCharProp[node: loc.node, index: loc.where, name: $MeddlePtSize]];
IF exprPointSize # NIL THEN pointSize ← Convert.RealFromRope[exprPointSize ! Convert.Error => CONTINUE];
convert linear form of expression to internal form
mathExpr ← MathExpr.ExprFromRope[ViewExpr.StripHeader[linearExpr] ! MathExpr.parseError => {mathExpr ← MathConstructors.MakePlaceHolder[]; CONTINUE}];
check for evaluation flag
IF EvalFirst
THEN {
object ← Evaluator.Eval[mathExpr];
mathExpr ← AlgebraClasses.ApplyLkpNoRecastExpr[$toExpr, object.class, LIST[object] ];
};
convert immutable expression to mutable display form
displayExpr ← MathDisplayExpr.DisplayExprFromExpr[mathExpr];
format expression and get box dimensions
displayBox ← displayExpr.Format[normal];
scale box dimensions from TeX unit sizes to some reasonable size
displayBox ← MathBox.Scale[displayBox, [pointSize, pointSize]];
compute appropriate postfix point values to place on current node
in order to set a maximum value, the following JaM code fragment does this
mumble pt the leading 2 .copy .gt 3 1 .roll .ifelse leading
leading ← Convert.RopeFromReal[displayBox.Height[]];
topLeading ← Convert.RopeFromReal[displayBox.Extents[].ascent + 12.0];
bottomLeading ← Convert.RopeFromReal[displayBox.Extents[].descent + 12.0];
postfixValue ← Rope.Cat[leading, " pt the leading 2 .copy .gt 3 1 .roll .ifelse leading "];
postfixValue ← Rope.Cat[postfixValue, topLeading, " pt the topLeading 2 .copy .gt 3 1 .roll .ifelse topLeading "];
postfixValue ← Rope.Cat[postfixValue, topLeading, " pt the topIndent 2 .copy .gt 3 1 .roll .ifelse topIndent "];
postfixValue ← Rope.Cat[postfixValue, bottomLeading, " pt the bottomLeading 2 .copy .gt 3 1 .roll .ifelse bottomLeading "];
put Postfix properties on node containing displayExpr to insure proper spacing
NodeProps.PutProp[loc.node, $Postfix, postfixValue];
create artwork char
charArtwork ←
NEW[CharacterArtworkRep ←
[paint: PaintMathExpr, extents: displayBox.Extents[], escapement: [displayBox.Width[], 0.0], data: NEW[PaintInfoRep ← [expr: displayExpr, box: displayBox]]]];
RETURN[charArtwork];
};
PaintMathExpr:
PROC[charArtwork: CharacterArtwork, context: Imager.Context] ~ {
effects: Paints charArtwork onto context.
retrieve painting information
paintInfo: PaintInfo ← NARROW[charArtwork.data];
set offset to zero (context origin)
absBox: BOX ← MathBox.ChangeOffset[paintInfo.box, [0.0, 0.0]];
local procedure to do painting within a DoSaveAll
DoPaint:
PROC[] ~ {
Imager.Move[context];
MathDisplayExpr.Paint[paintInfo.expr, context, absBox, NIL];
};
pretend that current x,y position in context is origin while actually painting
Imager.DoSaveAll[context, DoPaint];
};