measure method
NodeLayout
measure({
- required LatexNode node,
- required RenderContext context,
- required NodeLayout measureNode(),
- required NodeLayout measureGroup(),
override
Measures a node and returns its layout.
Implementation
@override
NodeLayout measure({
required LatexNode node,
required RenderContext context,
required NodeLayout Function(LatexNode, RenderContext) measureNode,
required NodeLayout Function(List<LatexNode>, RenderContext) measureGroup,
}) {
final stackNode = node as StackNode;
// FIX: Safely use .children() as a method per the Dart AST definitions.
LatexNode unwrapSingleGroup(LatexNode node0) {
LatexNode n = node0;
while (n is GroupNode && n.children().length == 1) {
n = n.children()[0];
}
return n;
}
LatexNode? merge(LatexNode? a, LatexNode? b) {
if (a == null) return b;
if (b == null) return a;
return GroupNode([a, b]);
}
LatexNode baseNode = unwrapSingleGroup(stackNode.base);
LatexNode? aboveNode = stackNode.above != null
? unwrapSingleGroup(stackNode.above!)
: null;
LatexNode? belowNode = stackNode.below != null
? unwrapSingleGroup(stackNode.below!)
: null;
while (baseNode is StackNode) {
final inner = baseNode;
aboveNode = merge(
aboveNode,
inner.above != null ? unwrapSingleGroup(inner.above!) : null,
);
belowNode = merge(
belowNode,
inner.below != null ? unwrapSingleGroup(inner.below!) : null,
);
baseNode = unwrapSingleGroup(inner.base);
}
final baseLayout = measureGroup([baseNode], context);
final scriptStyle = context.shrink(MathConstants.stackScriptScale);
final aboveLayout = aboveNode != null
? measureGroup([aboveNode], scriptStyle)
: null;
final belowLayout = belowNode != null
? measureGroup([belowNode], scriptStyle)
: null;
final totalWidth = math.max(
baseLayout.width,
math.max(aboveLayout?.width ?? 0.0, belowLayout?.width ?? 0.0),
);
final fontSizePx = context.fontSize;
final gap = fontSizePx * MathConstants.stackVerticalGap;
final double? aboveY = aboveLayout != null ? 0.0 : null;
final baseY =
(aboveLayout?.height ?? 0.0) + (aboveLayout != null ? gap : 0.0);
final belowY = belowLayout != null ? baseY + baseLayout.height + gap : null;
final totalHeight = belowLayout != null
? baseY + baseLayout.height + gap + belowLayout.height
: baseY + baseLayout.height;
final baseline = baseY + baseLayout.baseline;
return NodeLayout(
width: totalWidth,
height: totalHeight,
baseline: baseline,
draw: (canvas, x, y) {
final baseX = x + (totalWidth - baseLayout.width) / 2.0;
baseLayout.draw(canvas, baseX, y + baseY);
if (aboveLayout != null) {
final aboveX = x + (totalWidth - aboveLayout.width) / 2.0;
aboveLayout.draw(canvas, aboveX, y + (aboveY ?? 0.0));
}
if (belowLayout != null) {
final belowX = x + (totalWidth - belowLayout.width) / 2.0;
belowLayout.draw(canvas, belowX, y + (belowY ?? 0.0));
}
},
);
}