computeDistanceToBaseline method

  1. @override
double? computeDistanceToBaseline()
override

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;
}