computeDistanceToBaseline method
Compute distance to baseline
Implementation
@override
double? computeDistanceToBaseline() {
double? lineDistance;
CSSDisplay? effectiveDisplay = renderStyle.effectiveDisplay;
bool isInline = effectiveDisplay == CSSDisplay.inline;
// Margin does not work for inline element.
double marginTop = !isInline ? renderStyle.marginTop.computedValue : 0;
double marginBottom = !isInline ? renderStyle.marginBottom.computedValue : 0;
bool isParentFlowLayout = parent is RenderFlowLayout;
bool isDisplayInline = effectiveDisplay == CSSDisplay.inline ||
effectiveDisplay == CSSDisplay.inlineBlock ||
effectiveDisplay == CSSDisplay.inlineFlex;
// Use margin bottom as baseline if layout has no children.
if (_lineBoxMetrics.isEmpty) {
if (isDisplayInline) {
// Flex item baseline does not includes margin-bottom.
lineDistance = isParentFlowLayout
? marginTop + boxSize!.height + marginBottom
: marginTop + boxSize!.height;
return lineDistance;
} else {
return null;
}
}
// Use baseline of last line in flow layout and layout is inline-level
// otherwise use baseline of first line.
bool isLastLineBaseline = isParentFlowLayout && isDisplayInline;
_RunMetrics lineMetrics = isLastLineBaseline
? _lineBoxMetrics[_lineBoxMetrics.length - 1]
: _lineBoxMetrics[0];
// Use the max baseline of the children as the baseline in flow layout.
lineMetrics.runChildren.forEach((int? hashCode, RenderBox child) {
double? childMarginTop =
child is RenderBoxModel ? _getChildMarginTop(child) : 0;
RenderLayoutParentData? childParentData =
child.parentData as RenderLayoutParentData?;
double? childBaseLineDistance;
if (child is RenderBoxModel) {
childBaseLineDistance = child.computeDistanceToBaseline();
} else if (child is RenderTextBox) {
// Text baseline not depends on its own parent but its grand parents.
childBaseLineDistance = isLastLineBaseline
? child.computeDistanceToLastLineBaseline()
: child.computeDistanceToFirstLineBaseline();
}
if (childBaseLineDistance != null && childParentData != null) {
// Baseline of relative positioned element equals its original position
// so it needs to subtract its vertical offset.
Offset? relativeOffset;
double childOffsetY = childParentData.offset.dy - childMarginTop;
if (child is RenderBoxModel) {
relativeOffset =
CSSPositionedLayout.getRelativeOffset(child.renderStyle);
}
if (relativeOffset != null) {
childOffsetY -= relativeOffset.dy;
}
// It needs to subtract margin-top cause offset already includes margin-top.
childBaseLineDistance += childOffsetY;
if (lineDistance != null)
lineDistance = math.max(lineDistance!, childBaseLineDistance);
else
lineDistance = childBaseLineDistance;
}
});
// If no inline child found, use margin-bottom as baseline.
if (isDisplayInline && lineDistance != null) {
lineDistance = lineDistance! + marginTop;
}
return lineDistance;
}