computeContentBoxLogicalHeight method

void computeContentBoxLogicalHeight()

Implementation

void computeContentBoxLogicalHeight() {
  RenderStyle renderStyle = this;
  double? logicalHeight;

  CSSDisplay? effectiveDisplay = renderStyle.effectiveDisplay;

  // Height applies to all elements except non-replaced inline elements.
  // https://drafts.csswg.org/css-sizing-3/#propdef-height
  if (effectiveDisplay == CSSDisplay.inline && !renderStyle.isSelfRenderReplaced()) {
    _contentBoxLogicalHeight = null;
    return;
  } else {
    if (renderStyle.height.isNotAuto) {
      logicalHeight = renderStyle.height.computedValue;
    } else if (aspectRatio != null && renderStyle.width.isNotAuto) {
      // Prefer aspect-ratio when width is definite and height is auto.
      double contentW = renderStyle.width.computedValue - renderStyle.border.horizontal - renderStyle.padding.horizontal;
      contentW = math.max(0, contentW);
      final double contentH = contentW / aspectRatio!;
      logicalHeight = contentH + renderStyle.border.vertical + renderStyle.padding.vertical;
    } else if (renderStyle.isSelfHTMLElement()) {
      logicalHeight = renderStyle.target.ownerView.viewport!.boxSize!.height;
    } else if ((renderStyle.position == CSSPositionType.absolute || renderStyle.position == CSSPositionType.fixed) &&
        !renderStyle.isSelfRenderReplaced() &&
        renderStyle.height.isAuto &&
        renderStyle.top.isNotAuto &&
        renderStyle.bottom.isNotAuto) {
      // The height of positioned, non-replaced element is determined as following algorithm.
      // https://www.w3.org/TR/css-position-3/#abs-non-replaced-height
      if (!renderStyle.isParentRenderBoxModel()) {
        logicalHeight = null;
      }
      // Should access the renderStyle of renderBoxModel parent but not renderStyle parent
      // cause the element of renderStyle parent may not equal to containing block.
      // RenderBoxModel parent = current.parent as RenderBoxModel;
      // Get the renderStyle of outer scrolling box cause the renderStyle of scrolling
      // content box is only a fraction of the complete renderStyle.
      RenderStyle parentRenderStyle = renderStyle.getParentRenderStyle()!;
      // Height of positioned element should subtract its vertical margin.
      logicalHeight = (parentRenderStyle.paddingBoxLogicalHeight ?? 0) -
          renderStyle.top.computedValue -
          renderStyle.bottom.computedValue -
          renderStyle.marginTop.computedValue -
          renderStyle.marginBottom.computedValue;
    } else {
      CSSRenderStyle? parentRenderStyle = renderStyle.getParentRenderStyle();

      if (parentRenderStyle != null) {
        RenderWidgetElementChild? childWrapper = target.attachedRenderer?.findWidgetElementChild();
        BoxConstraints? childWrapperConstraints;
        try {
          childWrapperConstraints = childWrapper?.constraints;
        } catch (_) {}
        // Override the default logicalHeight value is the parent is RenderWidget
        if (parentRenderStyle.isSelfRenderWidget() &&
            childWrapper != null &&
            childWrapperConstraints != null &&
            (childWrapperConstraints.maxHeight.isFinite &&
                childWrapperConstraints.maxHeight != renderStyle.target.ownerView.viewport!.boxSize!.height)) {
          logicalHeight = childWrapperConstraints.maxHeight;
        } else if (renderStyle.isHeightStretch) {
          logicalHeight = parentRenderStyle.contentBoxLogicalHeight;
        }

        // Should subtract vertical margin of own from its parent content height.
        if (logicalHeight != null) {
          logicalHeight -= renderStyle.margin.vertical;
        }
      }
    }
  }

  // Get height by aspect ratio if height is auto.
  if (logicalHeight == null && aspectRatio != null) {
    // If a definite width is specified, prefer converting via the preferred aspect-ratio.
    if (renderStyle.width.isNotAuto) {
      double contentW = renderStyle.width.computedValue - renderStyle.border.horizontal - renderStyle.padding.horizontal;
      contentW = math.max(0, contentW);
      final double contentH = contentW / aspectRatio!;
      logicalHeight = contentH + renderStyle.border.vertical + renderStyle.padding.vertical;
    }
    // Fallback for replaced/intrinsic scenarios.
    logicalHeight ??= renderStyle.getHeightByAspectRatio();
  }

  // Constrain height by min-height and max-height.
  if (renderStyle.minHeight.isNotAuto) {
    double minHeight = renderStyle.minHeight.computedValue;
    if (logicalHeight != null && logicalHeight < minHeight) {
      logicalHeight = minHeight;
    }
  }
  if (renderStyle.maxHeight.isNotNone) {
    double maxHeight = renderStyle.maxHeight.computedValue;
    if (logicalHeight != null && logicalHeight > maxHeight) {
      logicalHeight = maxHeight;
    }
  }

  double? logicalContentHeight;
  // Subtract padding and border width to get content width.
  if (logicalHeight != null) {
    logicalContentHeight = logicalHeight - renderStyle.border.vertical - renderStyle.padding.vertical;
    // Logical height may be smaller than its border and padding width,
    // in this case, content height will be negative which is illegal.
    logicalContentHeight = math.max(0, logicalContentHeight);
  }

  _contentBoxLogicalHeight = logicalContentHeight;
}