computeContentBoxLogicalWidth method
void
computeContentBoxLogicalWidth()
Implementation
void computeContentBoxLogicalWidth() {
RenderBoxModel current = renderBoxModel!;
RenderStyle renderStyle = this;
double? logicalWidth;
CSSDisplay? effectiveDisplay = renderStyle.effectiveDisplay;
// Width applies to all elements except non-replaced inline elements.
// https://drafts.csswg.org/css-sizing-3/#propdef-width
if (effectiveDisplay == CSSDisplay.inline && current is! RenderReplaced) {
_contentBoxLogicalWidth = null;
return;
} else if (effectiveDisplay == CSSDisplay.block ||
effectiveDisplay == CSSDisplay.flex ||
effectiveDisplay == 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;
}
}
}
}
} else if (effectiveDisplay == CSSDisplay.inlineBlock ||
effectiveDisplay == CSSDisplay.inlineFlex ||
effectiveDisplay == CSSDisplay.inline) {
if (renderStyle.width.isNotAuto) {
logicalWidth = renderStyle.width.computedValue;
} else if ((renderStyle.position == CSSPositionType.absolute || renderStyle.position == CSSPositionType.fixed) &&
current is! RenderReplaced &&
renderStyle.width.isAuto &&
renderStyle.left.isNotAuto &&
renderStyle.right.isNotAuto) {
// The width of positioned, non-replaced element is determined as following algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
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;
}
}
// Get width by aspect ratio for replaced element if width is auto.
if (logicalWidth == null && aspectRatio != null) {
logicalWidth = renderStyle.getWidthByAspectRatio();
}
// 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;
}