computeContentBoxLogicalWidth method

void computeContentBoxLogicalWidth()

Implementation

void computeContentBoxLogicalWidth() {
  RenderBoxModel current = renderBoxModel!;
  RenderStyle renderStyle = this;
  double? logicalWidth;

  CSSDisplay? effectiveDisplay = renderStyle.effectiveDisplay;
  switch (effectiveDisplay) {
    case CSSDisplay.block:
    case CSSDisplay.flex:
    case CSSDisplay.sliver:
      //  Use width directly if defined.
      if (renderStyle.width.isNotAuto) {
        logicalWidth = renderStyle.width.computedValue;
      } else if (renderStyle.parent != null) {
        RenderStyle parentRenderStyle = renderStyle.parent!;
        RenderBoxModel parent = parentRenderStyle.renderBoxModel!;

        // Block element (except replaced element) will stretch to the content width of its parent in flow layout.
        // Replaced element also stretch in flex layout if align-items is stretch.
        if (current is! RenderReplaced || parent is RenderFlexLayout) {
          RenderStyle? ancestorRenderStyle = _findAncestorWithNoDisplayInline();
          // Should ignore renderStyle of display inline when searching for ancestors to stretch width.
          if (ancestorRenderStyle != null) {
            logicalWidth = ancestorRenderStyle.contentBoxLogicalWidth;
            // Should subtract horizontal margin of own from its parent content width.
            if (logicalWidth != null) {
              logicalWidth -= renderStyle.margin.horizontal;
            }
          }
        }
      }
      break;
    case CSSDisplay.inlineBlock:
    case CSSDisplay.inlineFlex:
      if (renderStyle.width.isNotAuto) {
        logicalWidth = renderStyle.width.computedValue;

      // The width of positioned, non-replaced element is determined as following algorithm.
      // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
      } else if ((renderStyle.position == CSSPositionType.absolute ||
        renderStyle.position == CSSPositionType.fixed)
        && current is! RenderReplaced
        && renderStyle.width.isAuto
        && renderStyle.left.isNotAuto
        && renderStyle.right.isNotAuto
      ) {
        if (current.parent is! RenderBoxModel) {
          logicalWidth = 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 = parent.isScrollingContentBox
          ? (parent.parent as RenderBoxModel).renderStyle
          : parent.renderStyle;
        // Width of positioned element should subtract its horizontal margin.
        logicalWidth = (parentRenderStyle.paddingBoxLogicalWidth ?? 0)
          - renderStyle.left.computedValue - renderStyle.right.computedValue
          - renderStyle.marginLeft.computedValue - renderStyle.marginRight.computedValue;

      } else if (current.hasSize && current.constraints.hasTightWidth) {
        logicalWidth = current.constraints.maxWidth;
      }
      break;
    case CSSDisplay.inline:
      break;
    case CSSDisplay.none:
      break;
  }

  // Get width by intrinsic ratio for replaced element if width is auto.
  if (logicalWidth == null && intrinsicRatio != null) {
    logicalWidth = renderStyle.getWidthByIntrinsicRatio();
  }

  // Constrain width by min-width and max-width.
  if (renderStyle.minWidth.isNotAuto) {
    double minWidth = renderStyle.minWidth.computedValue;
    if (logicalWidth != null && logicalWidth < minWidth) {
      logicalWidth = minWidth;
    }
  }
  if (renderStyle.maxWidth.isNotNone) {
    double maxWidth = renderStyle.maxWidth.computedValue;
    if (logicalWidth != null && logicalWidth > maxWidth) {
      logicalWidth = maxWidth;
    }
  }

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

  _contentBoxLogicalWidth = logicalContentWidth;
}