COMMIT_MESSAGE

 1Percentage max-width on aspect-ratio box resolves against wrong axis in perpendicular writing mode
 2https://bugs.webkit.org/show_bug.cgi?id=314554
 3
 4Reviewed by NOBODY (OOPS!).
 5
 6We had two functions:
 7- computeLogicalWidthFromAspectRatioInternal: height x aspect-ratio, no clamping
 8- computeLogicalWidthFromAspectRatio: calls Internal, then clamps with min/max
 9
 10The "Internal" naming was confusing - callers had to know which one to pick
 11based on context. But the split is simple: preferred-width computation never
 12wants clamping (min/max is applied later by a shared helper), layout always does.
 13
 14Remove the split. Keep one function (the unconstrained one) named
 15computeLogicalWidthFromAspectRatio(). The two layout callsites now call
 16constrainLogicalWidthByMinMax() inline, just like the normal width path already
 17does. This also fixes an inconsistency (see test case): the old wrapper used
 18containingBlockLogicalWidthForContent() to resolve percentage min/max, but the
 19normal path in computeLogicalWidth uses a containerWidthInInlineDirection
 20variable that accounts for perpendicular writing modes. The aspect-ratio path
 21now uses the same variable.
 22
 23* Source/WebCore/rendering/RenderBlock.cpp:
 24(WebCore::RenderBlock::computePreferredLogicalWidths):
 25* Source/WebCore/rendering/RenderBox.cpp:
 26(WebCore::RenderBox::computeLogicalWidth):
 27(WebCore::RenderBox::computeIntrinsicKeywordLogicalWidths):
 28(WebCore::RenderBox::computeOutOfFlowPositionedLogicalWidth):
 29(WebCore::RenderBox::computeLogicalWidthFromAspectRatio):
 30* Source/WebCore/rendering/RenderBox.h:
 31* Source/WebCore/rendering/RenderReplaced.cpp:
 32(WebCore::RenderReplaced::computePreferredLogicalWidths):
 33* LayoutTests/imported/w3c/web-platform-tests/css/css-sizing/intrinsic-percent-non-replaced-008-expected.html: Added.
 34* LayoutTests/imported/w3c/web-platform-tests/css/css-sizing/intrinsic-percent-non-replaced-008-ref.html: Added.
 35* LayoutTests/imported/w3c/web-platform-tests/css/css-sizing/intrinsic-percent-non-replaced-008.html: Added.

Source/WebCore/rendering/RenderBlock.cpp

@@void RenderBlock::computePreferredLogicalWidths()
22432243 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
22442244 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
22452245 } else if (shouldComputeLogicalWidthFromAspectRatio()) {
2246  m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = (computeLogicalWidthFromAspectRatioInternal() - borderAndPaddingLogicalWidth());
 2246 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = (computeLogicalWidthFromAspectRatio() - borderAndPaddingLogicalWidth());
22472247 m_minPreferredLogicalWidth = std::max(0_lu, m_minPreferredLogicalWidth);
22482248 m_maxPreferredLogicalWidth = std::max(0_lu, m_maxPreferredLogicalWidth);
22492249 } else

Source/WebCore/rendering/RenderBox.cpp

@@void RenderBox::computeLogicalWidth(LogicalExtentComputedValues& computedValues)
28422842 return *overridingLogicalWidth;
28432843 if (treatAsReplaced)
28442844 return downcast<RenderReplaced>(*this).computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth();
2845  if (shouldComputeLogicalWidthFromAspectRatio() && style().logicalWidth().isAuto())
2846  return computeLogicalWidthFromAspectRatio();
28472845
28482846 auto containerWidthInInlineDirection = !hasPerpendicularContainingBlock ? containerLogicalWidth : perpendicularContainingBlockLogicalHeight();
 2847 if (shouldComputeLogicalWidthFromAspectRatio() && style().logicalWidth().isAuto())
 2848 return constrainLogicalWidthByMinMax(computeLogicalWidthFromAspectRatio(), containerWidthInInlineDirection, containingBlock, AllowIntrinsic::No);
 2849
28492850 auto preferredWidth = computeLogicalWidthUsing(usedLogicalWidthLength, containerWidthInInlineDirection, containingBlock);
28502851 return constrainLogicalWidthByMinMax(preferredWidth, containerWidthInInlineDirection, containingBlock);
28512852 };

@@template<typename Keyword> void RenderBox::computeIntrinsicKeywordLogicalWidths(
29272928 computeIntrinsicKeywordLogicalWidths(minLogicalWidth, maxLogicalWidth);
29282929 else {
29292930 if (shouldComputeLogicalWidthFromAspectRatio()) {
2930  minLogicalWidth = maxLogicalWidth = computeLogicalWidthFromAspectRatioInternal() - borderAndPadding;
 2931 minLogicalWidth = maxLogicalWidth = computeLogicalWidthFromAspectRatio() - borderAndPadding;
29312932 if (firstChild() && style().logicalMinWidth().isAuto()) {
29322933 LayoutUnit minChildrenLogicalWidth;
29332934 LayoutUnit maxChildrenLogicalWidth;

@@template<typename SizeType> LayoutUnit RenderBox::computeOutOfFlowPositionedLogi
43754376 return 0_lu;
43764377 } else {
43774378 if (shouldComputeLogicalWidthFromAspectRatio()) {
4378  auto logicalWidth = computeLogicalWidthFromAspectRatio();
 4379 auto logicalWidth = constrainLogicalWidthByMinMax(computeLogicalWidthFromAspectRatio(), inlineConstraints.containingSize(), *containingBlock(), AllowIntrinsic::No);
43794380 return style().boxSizingForAspectRatio() == BoxSizing::BorderBox ? logicalWidth : logicalWidth - inlineConstraints.bordersPlusPadding();
43804381 }
43814382 return fallback();

@@bool RenderBox::shouldComputeLogicalWidthFromAspectRatio() const
52375238 return overridingBorderBoxLogicalHeight() || shouldComputeLogicalWidthFromAspectRatioAndInsets(*this) || style().logicalHeight().isFixed() || isResolvablePercentageHeight() || isResolveableStretchSize(style().logicalHeight());
52385239}
52395240
5240 LayoutUnit RenderBox::computeLogicalWidthFromAspectRatioInternal() const
 5241LayoutUnit RenderBox::computeLogicalWidthFromAspectRatio() const
52415242{
52425243 ASSERT(preferredAspectRatio());
52435244

@@LayoutUnit RenderBox::computeLogicalWidthFromAspectRatioInternal() const
52465247 return inlineSizeFromAspectRatio(horizontalBorderAndPaddingExtent(), verticalBorderAndPaddingExtent(), preferredAspectRatio().value_or(0.f), style().boxSizingForAspectRatio(), logicalHeightforAspectRatio, style().aspectRatio(), isRenderReplaced());
52475248}
52485249
5249 LayoutUnit RenderBox::computeLogicalWidthFromAspectRatio() const
5250 {
5251  auto logicalWidth = computeLogicalWidthFromAspectRatioInternal();
5252  LayoutUnit containerWidthInInlineDirection = std::max<LayoutUnit>(0, containingBlockLogicalWidthForContent());
5253  return constrainLogicalWidthByMinMax(logicalWidth, containerWidthInInlineDirection, *containingBlock(), AllowIntrinsic::No);
5254 }
5255 
52565250std::optional<double> RenderBox::preferredAspectRatio() const
52575251{
52585252 if (style().aspectRatio().hasRatio())

Source/WebCore/rendering/RenderBox.h

@@protected:
690690 bool NODELETE shouldIgnoreAspectRatio() const;
691691 bool isResolveableStretchSize(const auto& size) const { return size.isStretch() && containingBlockHasDefiniteBlockSize(); }
692692 bool isUnresolveableStretchSize(const auto& size) const { return size.isStretch() && !containingBlockHasDefiniteBlockSize(); }
693  LayoutUnit computeLogicalWidthFromAspectRatioInternal() const;
694693 LayoutUnit computeLogicalWidthFromAspectRatio() const;
695694 void applyTransferredMinMaxSizesFromAspectRatio();
696695 std::pair<LayoutUnit, LayoutUnit> computeMinMaxLogicalWidthFromAspectRatio() const;

Source/WebCore/rendering/RenderReplaced.cpp

@@void RenderReplaced::computePreferredLogicalWidths()
870870 // width may not be set on our containing block.
871871 if (style().logicalWidth().isPercentOrCalculated()) {
872872 if (canDerivePreferredWidthFromAspectRatio(*this)) {
873  m_maxPreferredLogicalWidth = computeLogicalWidthFromAspectRatioInternal() - borderAndPaddingLogicalWidth();
 873 m_maxPreferredLogicalWidth = computeLogicalWidthFromAspectRatio() - borderAndPaddingLogicalWidth();
874874 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
875875 } else {
876876 computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);

LayoutTests/imported/w3c/web-platform-tests/css/css-sizing/intrinsic-percent-non-replaced-008-expected.html

 1<!DOCTYPE html>
 2<title>Reference</title>
 3<style>
 4.container {
 5 writing-mode: vertical-rl;
 6 width: 300px;
 7 height: 200px;
 8}
 9
 10.ref {
 11 writing-mode: horizontal-tb;
 12 width: 150px;
 13 height: 50px;
 14 background: green;
 15}
 16</style>
 17<p>Test passes if there is a 150x50 green rectangle.</p>
 18<div class="container">
 19 <div class="ref"></div>
 20</div>

LayoutTests/imported/w3c/web-platform-tests/css/css-sizing/intrinsic-percent-non-replaced-008-ref.html

 1<!DOCTYPE html>
 2<title>Reference</title>
 3<style>
 4.container {
 5 writing-mode: vertical-rl;
 6 width: 300px;
 7 height: 200px;
 8}
 9
 10.ref {
 11 writing-mode: horizontal-tb;
 12 width: 150px;
 13 height: 50px;
 14 background: green;
 15}
 16</style>
 17<p>Test passes if there is a 150x50 green rectangle.</p>
 18<div class="container">
 19 <div class="ref"></div>
 20</div>

LayoutTests/imported/w3c/web-platform-tests/css/css-sizing/intrinsic-percent-non-replaced-008.html

 1<!DOCTYPE html>
 2<title>Percentage max-width with aspect-ratio resolves against correct axis in perpendicular writing mode</title>
 3<link rel="help" href="https://www.w3.org/TR/css-sizing-3/#cyclic-percentage-contribution">
 4<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
 5<link rel="match" href="intrinsic-percent-non-replaced-008-ref.html">
 6<style>
 7.container {
 8 writing-mode: vertical-rl;
 9 width: 300px;
 10 height: 200px;
 11}
 12
 13.child {
 14 writing-mode: horizontal-tb;
 15 aspect-ratio: 4 / 1;
 16 height: 50px;
 17 max-width: 50%;
 18 background: green;
 19 font: 20px/1 Ahem;
 20}
 21</style>
 22<p>Test passes if there is a 150x50 green rectangle.</p>
 23<div class="container">
 24 <div class="child"></div>
 25</div>