Skip to content

Commit

Permalink
Support aspect-ratio in intrinsic sizing
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=220861

Patch by Rob Buis <rbuis@igalia.com> on 2021-03-08
Reviewed by Antti Koivisto.

Source/WebCore:

Support aspect-ratio in intrinsic sizing calculations.
The values min-content/max-content/fit-content
get set a value through aspect-ratio [1].
However min-width:auto is special, it should take content
into account [2]. In order to support this, compute
logical (intrinsic) width using MinIntrinsic, since staying
with MinContent/MaxContent would cause an infinite loop.

Behavior matches Firefox and Chrome.

[1] https://www.w3.org/TR/css-sizing-4/#propdef-aspect-ratio
[2] https://www.w3.org/TR/css-sizing-4/#aspect-ratio-minimum

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::computePreferredLogicalWidths):
Compute child min/max pref widths from aspect-ratio if it applies.
* rendering/RenderBox.cpp:
(WebCore::RenderBox::constrainLogicalWidthInFragmentByMinMax const):
Add an allowIntrinsic parameter to prevent recursion.
(WebCore::RenderBox::computeIntrinsicLogicalWidthUsing const):
Compute intrinsic logical width from aspect ratio if possible.
(WebCore::RenderBox::computeLogicalWidthInFragmentUsing const):
(WebCore::RenderBox::shouldComputeLogicalHeightFromAspectRatio const):
min/max/fit-content in the block axis is treated as auto.
(WebCore::RenderBox::computeLogicalWidthFromAspectRatio const):
Prevent recursion by passing false for allowIntrinsic.
* rendering/RenderBox.h:

LayoutTests:

Enable tests that pass now.

* TestExpectations:

Canonical link: https://commits.webkit.org/235004@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@274068 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
rwlbuis authored and webkit-commit-queue committed Mar 8, 2021
1 parent 78c85d0 commit e730ca1
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 23 deletions.
11 changes: 11 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
2021-03-08 Rob Buis <rbuis@igalia.com>

Support aspect-ratio in intrinsic sizing
https://bugs.webkit.org/show_bug.cgi?id=220861

Reviewed by Antti Koivisto.

Enable tests that pass now.

* TestExpectations:

2021-03-08 Kimmo Kinnunen <kkinnunen@apple.com>

WebGL asserts after GPU process times out
Expand Down
14 changes: 1 addition & 13 deletions LayoutTests/TestExpectations
Expand Up @@ -4554,6 +4554,7 @@ webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/shadow-direc
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/shadow-directionality-002.tentative.html [ ImageOnlyFailure ]
webkit.org/b/214462 imported/w3c/web-platform-tests/css/css-scoping/slotted-placeholder.html [ ImageOnlyFailure ]

# contain-intrinsic-size
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/abspos-014.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/block-aspect-ratio-024.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/block-aspect-ratio-028.html [ ImageOnlyFailure ]
Expand All @@ -4562,21 +4563,8 @@ webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-022.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/grid-aspect-ratio-015.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/grid-aspect-ratio-016.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/grid-aspect-ratio-017.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-001.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-002.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-004.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-005.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-006.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-008.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-010.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-011.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-012.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-013.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-014.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/intrinsic-size-015.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/aspect-ratio/table-element-001.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-001.html [ ImageOnlyFailure ]
webkit.org/b/214463 imported/w3c/web-platform-tests/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-002.html [ ImageOnlyFailure ]
Expand Down
35 changes: 35 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,38 @@
2021-03-08 Rob Buis <rbuis@igalia.com>

Support aspect-ratio in intrinsic sizing
https://bugs.webkit.org/show_bug.cgi?id=220861

Reviewed by Antti Koivisto.

Support aspect-ratio in intrinsic sizing calculations.
The values min-content/max-content/fit-content
get set a value through aspect-ratio [1].
However min-width:auto is special, it should take content
into account [2]. In order to support this, compute
logical (intrinsic) width using MinIntrinsic, since staying
with MinContent/MaxContent would cause an infinite loop.

Behavior matches Firefox and Chrome.

[1] https://www.w3.org/TR/css-sizing-4/#propdef-aspect-ratio
[2] https://www.w3.org/TR/css-sizing-4/#aspect-ratio-minimum

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::computePreferredLogicalWidths):
Compute child min/max pref widths from aspect-ratio if it applies.
* rendering/RenderBox.cpp:
(WebCore::RenderBox::constrainLogicalWidthInFragmentByMinMax const):
Add an allowIntrinsic parameter to prevent recursion.
(WebCore::RenderBox::computeIntrinsicLogicalWidthUsing const):
Compute intrinsic logical width from aspect ratio if possible.
(WebCore::RenderBox::computeLogicalWidthInFragmentUsing const):
(WebCore::RenderBox::shouldComputeLogicalHeightFromAspectRatio const):
min/max/fit-content in the block axis is treated as auto.
(WebCore::RenderBox::computeLogicalWidthFromAspectRatio const):
Prevent recursion by passing false for allowIntrinsic.
* rendering/RenderBox.h:

2021-03-08 Ian Gilbert <iang@apple.com>

[Web Animations] Don't update animation playback rate if timeline is inactive
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/rendering/RenderBlock.cpp
Expand Up @@ -2282,6 +2282,8 @@ void RenderBlock::computePreferredLogicalWidths()
if (!isTableCell() && styleToUse.logicalWidth().isFixed() && styleToUse.logicalWidth().value() >= 0
&& !(isDeprecatedFlexItem() && !styleToUse.logicalWidth().intValue()))
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalWidth());
else if (shouldComputeLogicalWidthFromAspectRatio())
m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeLogicalWidthFromAspectRatio();
else
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);

Expand Down
23 changes: 14 additions & 9 deletions Source/WebCore/rendering/RenderBox.cpp
Expand Up @@ -651,7 +651,7 @@ void RenderBox::updateLayerTransform()
layer()->updateTransform();
}

LayoutUnit RenderBox::constrainLogicalWidthInFragmentByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock& cb, RenderFragmentContainer* fragment) const
LayoutUnit RenderBox::constrainLogicalWidthInFragmentByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock& cb, RenderFragmentContainer* fragment, AllowIntrinsic allowIntrinsic) const
{
const RenderStyle& styleToUse = style();

Expand All @@ -660,13 +660,15 @@ LayoutUnit RenderBox::constrainLogicalWidthInFragmentByMinMax(LayoutUnit logical
logicalWidth = std::clamp(logicalWidth, logicalMinWidth, logicalMaxWidth);
}

if (!styleToUse.logicalMaxWidth().isUndefined())
if (!styleToUse.logicalMaxWidth().isUndefined() && (allowIntrinsic == AllowIntrinsic::Yes || !styleToUse.logicalMaxWidth().isIntrinsic()))
logicalWidth = std::min(logicalWidth, computeLogicalWidthInFragmentUsing(MaxSize, styleToUse.logicalMaxWidth(), availableWidth, cb, fragment));
if (allowIntrinsic == AllowIntrinsic::No && styleToUse.logicalMinWidth().isIntrinsic())
return logicalWidth;
auto minLength = styleToUse.logicalMinWidth();
if (styleToUse.hasAspectRatio() && styleToUse.logicalWidth().isAuto() && minLength.isAuto() && styleToUse.overflowInlineDirection() == Overflow::Visible) {
if (styleToUse.hasAspectRatio() && minLength.isAuto() && (styleToUse.logicalWidth().isAuto() || styleToUse.logicalWidth().isMinContent() || styleToUse.logicalWidth().isMaxContent()) && styleToUse.overflowInlineDirection() == Overflow::Visible) {
// Make sure we actually used the aspect ratio.
if (shouldComputeLogicalWidthFromAspectRatio())
minLength = Length(LengthType::MinContent);
minLength = Length(LengthType::MinIntrinsic);
}
return std::max(logicalWidth, computeLogicalWidthInFragmentUsing(MinSize, minLength, availableWidth, cb, fragment));
}
Expand Down Expand Up @@ -2612,9 +2614,12 @@ LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLengt

LayoutUnit minLogicalWidth;
LayoutUnit maxLogicalWidth;
computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
if (!logicalWidthLength.isMinIntrinsic() && shouldComputeLogicalWidthFromAspectRatio())
minLogicalWidth = maxLogicalWidth = computeLogicalWidthFromAspectRatio();
else
computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);

if (logicalWidthLength.isMinContent())
if (logicalWidthLength.isMinContent() || logicalWidthLength.isMinIntrinsic())
return minLogicalWidth + borderAndPadding;

if (logicalWidthLength.isMaxContent())
Expand Down Expand Up @@ -2642,7 +2647,7 @@ LayoutUnit RenderBox::computeLogicalWidthInFragmentUsing(SizeType widthType, Len
return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth), logicalWidth.type());
}

if (logicalWidth.isIntrinsic())
if (logicalWidth.isIntrinsic() || logicalWidth.isMinIntrinsic())
return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth());

LayoutUnit marginStart;
Expand Down Expand Up @@ -5098,7 +5103,7 @@ bool RenderBox::shouldComputeLogicalHeightFromAspectRatio() const
return false;

auto h = style().logicalHeight();
return h.isAuto() || (!isOutOfFlowPositioned() && h.isPercentOrCalculated() && !percentageLogicalHeightIsResolvable());
return h.isAuto() || h.isIntrinsic() || (!isOutOfFlowPositioned() && h.isPercentOrCalculated() && !percentageLogicalHeightIsResolvable());
}

bool RenderBox::shouldComputeLogicalWidthFromAspectRatio() const
Expand Down Expand Up @@ -5134,7 +5139,7 @@ LayoutUnit RenderBox::computeLogicalWidthFromAspectRatio(RenderFragmentContainer
auto logicalWidth = inlineSizeFromAspectRatio(horizontalBorderAndPaddingExtent(), verticalBorderAndPaddingExtent(), LayoutUnit(style().logicalAspectRatio()), style().boxSizingForAspectRatio(), logicalHeightforAspectRatio);

LayoutUnit containerWidthInInlineDirection = std::max<LayoutUnit>(0, containingBlockLogicalWidthForContentInFragment(fragment));
return constrainLogicalWidthInFragmentByMinMax(logicalWidth, containerWidthInInlineDirection, *containingBlock(), fragment);
return constrainLogicalWidthInFragmentByMinMax(logicalWidth, containerWidthInInlineDirection, *containingBlock(), fragment, AllowIntrinsic::No);
}

std::pair<LayoutUnit, LayoutUnit> RenderBox::computeMinMaxLogicalWidthFromAspectRatio() const
Expand Down
3 changes: 2 additions & 1 deletion Source/WebCore/rendering/RenderBox.h
Expand Up @@ -85,7 +85,8 @@ class RenderBox : public RenderBoxModelObject {
LayoutUnit logicalWidth() const { return style().isHorizontalWritingMode() ? width() : height(); }
LayoutUnit logicalHeight() const { return style().isHorizontalWritingMode() ? height() : width(); }

LayoutUnit constrainLogicalWidthInFragmentByMinMax(LayoutUnit, LayoutUnit, RenderBlock&, RenderFragmentContainer* = nullptr) const;
enum class AllowIntrinsic { Yes, No };
LayoutUnit constrainLogicalWidthInFragmentByMinMax(LayoutUnit, LayoutUnit, RenderBlock&, RenderFragmentContainer*, AllowIntrinsic = AllowIntrinsic::Yes) const;
LayoutUnit constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, Optional<LayoutUnit> intrinsicContentHeight) const;
LayoutUnit constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, Optional<LayoutUnit> intrinsicContentHeight) const;

Expand Down

0 comments on commit e730ca1

Please sign in to comment.