Changeset 284359 in webkit
- Timestamp:
- Oct 18, 2021, 3:07:52 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/rendering/RenderFlexibleBox.cpp (modified) (9 diffs)
-
Source/WebCore/rendering/RenderFlexibleBox.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r284347 r284359 1 2021-09-24 Sergio Villar Senin <svillar@igalia.com> 2 3 [css-flexbox] Improve & simplify the flex-basis computation 4 https://bugs.webkit.org/show_bug.cgi?id=230755 5 6 Reviewed by Manuel Rego Casasnovas. 7 8 * TestExpectations: Unskipped flex-basis-011.html which is now working fine. 9 1 10 2021-10-17 Dean Jackson <dino@apple.com> 2 11 -
trunk/LayoutTests/TestExpectations
r284343 r284359 4220 4220 webkit.org/b/221479 imported/w3c/web-platform-tests/css/css-flexbox/flexbox-flex-basis-content-004a.html [ ImageOnlyFailure ] 4221 4221 4222 # flex-basis with %.4223 webkit.org/b/ imported/w3c/web-platform-tests/css/css-flexbox/flex-basis-011.html [ ImageOnlyFailure ]4224 4225 4222 # Flex item's min|max content contributions 4226 4223 webkit.org/b/230747 imported/w3c/web-platform-tests/css/css-flexbox/flex-container-max-content-001.html [ ImageOnlyFailure ] -
trunk/Source/WebCore/ChangeLog
r284358 r284359 1 2021-09-24 Sergio Villar Senin <svillar@igalia.com> 2 3 [css-flexbox] Improve & simplify the flex-basis computation 4 https://bugs.webkit.org/show_bug.cgi?id=230755 5 6 Reviewed by Manuel Rego Casasnovas. 7 8 The flex-basis computation code was a bit convoluted. It had some pre-computations for items 9 with intrinsic main size that were causing several issues due to reentrancy. Actually those 10 computations where not needed at all for the flex basis computation but for a later stage, the 11 computation of the hyphotetical main size in which we need to compute 'min-{width|height}: auto'. 12 13 That's why the code that was executed before the flex-basis computation is now part of 14 computeFlexItemMinMaxSizes(). As we are no longer doing a layout before computing the flex-basis, 15 a layout has to be added to those cases in which the main size is the block size of the child. Apart 16 from that the flex-basis computation uses a newly defined RAII class to set the main size of the item 17 to the value specified by flex-basis which is what the specs mandate. 18 19 Last but not least, the computeInnerFlexBaseSizeForChild() method was renamed to computeFlexBaseSizeForChild() 20 which fits better with the terminology used in the specs. 21 22 Flex basis computation is already covered by the WPT test suite, there is no need for extra tests. This patch 23 fixes the only flex-basis-* test case that was not passing. 24 25 * rendering/RenderFlexibleBox.cpp: 26 (WebCore::RenderFlexibleBox::computeMainAxisExtentForChild): Removed obsolete comment. Added 27 a layoutIfNeeded() as we cannot be sure that the item was already laid out any more. 28 (WebCore::ScopedFlexBasisAsMainSize::ScopedFlexBasisAsChildMainSize): New RAII class. 29 (WebCore::ScopedFlexBasisAsMainSize::~ScopedFlexBasisAsChildMainSize): 30 (WebCore::RenderFlexibleBox::computeFlexBaseSizeForChild): Renamed from computeInnerFlexBaseSizeForChild. 31 (WebCore::RenderFlexibleBox::computeFlexItemMinMaxSizes): Added relayoutChildren parameter. 32 (WebCore::RenderFlexibleBox::constructFlexItem): Moved code to computeFlexItemMinMaxSizes(). 33 (WebCore::RenderFlexibleBox::layoutAndPlaceChildren): 34 (WebCore::RenderFlexibleBox::computeInnerFlexBaseSizeForChild): Deleted. 35 * rendering/RenderFlexibleBox.h: 36 1 37 2021-10-18 Philippe Normand <pnormand@igalia.com> 2 38 -
trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp
r282463 r284359 35 35 #include "HitTestResult.h" 36 36 #include "LayoutRepainter.h" 37 #include "RenderBox.h" 37 38 #include "RenderChildIterator.h" 38 39 #include "RenderLayer.h" 39 40 #include "RenderLayoutState.h" 41 #include "RenderObjectEnums.h" 40 42 #include "RenderStyleConstants.h" 41 43 #include "RenderView.h" … … 629 631 // writing mode. Otherwise we need the logical height. 630 632 if (!mainAxisIsChildInlineAxis(child)) { 631 // We don't have to check for "auto" here - computeContentLogicalHeight 632 // will just return a null Optional for that case anyway. It's safe to access 633 // scrollbarLogicalHeight here because ComputeNextFlexLine will have 634 // already forced layout on the child. We previously did a layout out the child 635 // if necessary (see ComputeNextFlexLine and the call to 636 // childHasIntrinsicMainAxisSize) so we can be sure that the two height 637 // calls here will return up-to-date data. 633 child.layoutIfNeeded(); 638 634 std::optional<LayoutUnit> height = child.computeContentLogicalHeight(sizeType, size, cachedChildIntrinsicContentLogicalHeight(child)); 639 635 if (!height) … … 1001 997 } 1002 998 1003 LayoutUnit RenderFlexibleBox::computeInnerFlexBaseSizeForChild(RenderBox& child, LayoutUnit mainAxisBorderAndPadding) 999 // This is a RAII class that is used to temporarily set the flex basis as the child size in the main axis. 1000 class ScopedFlexBasisAsChildMainSize { 1001 public: 1002 ScopedFlexBasisAsChildMainSize(RenderBox& child, Length flexBasis, bool mainAxisIsInlineAxis) 1003 : m_child(child) 1004 , m_mainAxisIsInlineAxis(mainAxisIsInlineAxis) 1005 { 1006 if (m_mainAxisIsInlineAxis) { 1007 m_originalLength = m_child.style().logicalWidth(); 1008 m_child.mutableStyle().setLogicalWidth(Length(flexBasis)); 1009 return; 1010 } 1011 m_originalLength = m_child.style().logicalHeight(); 1012 m_child.mutableStyle().setLogicalHeight(Length(flexBasis)); 1013 } 1014 ~ScopedFlexBasisAsChildMainSize() 1015 { 1016 if (m_mainAxisIsInlineAxis) 1017 m_child.mutableStyle().setLogicalWidth(Length(m_originalLength)); 1018 else 1019 m_child.mutableStyle().setLogicalHeight(Length(m_originalLength)); 1020 } 1021 private: 1022 RenderBox& m_child; 1023 bool m_mainAxisIsInlineAxis; 1024 Length m_originalLength; 1025 }; 1026 1027 // https://drafts.csswg.org/css-flexbox/#algo-main-item 1028 LayoutUnit RenderFlexibleBox::computeFlexBaseSizeForChild(RenderBox& child, LayoutUnit mainAxisBorderAndPadding) 1004 1029 { 1005 1030 Length flexBasis = flexBasisForChild(child); 1031 // 9.3.2 A. 1006 1032 if (childMainSizeIsDefinite(child, flexBasis)) 1007 1033 return std::max(0_lu, computeMainAxisExtentForChild(child, MainOrPreferredSize, flexBasis).value()); 1008 1034 1035 // 9.3.2 B. 1009 1036 if (childHasComputableAspectRatioAndCrossSizeIsConsideredDefinite(child)) { 1010 1037 const Length& crossSizeLength = crossSizeLengthForChild(MainOrPreferredSize, child); … … 1012 1039 } 1013 1040 1014 // The flex basis is indefinite (=auto), so we need to compute the actual width of the child. 1015 LayoutUnit mainAxisExtent; 1016 if (!mainAxisIsChildInlineAxis(child)) { 1017 ASSERT(!child.needsLayout()); 1018 ASSERT(m_intrinsicSizeAlongMainAxis.contains(&child)); 1019 mainAxisExtent = m_intrinsicSizeAlongMainAxis.get(&child); 1020 } else { 1021 // We don't need to add scrollbarLogicalWidth here because the preferred 1022 // width includes the scrollbar, even for overflow: auto. 1023 mainAxisExtent = child.maxPreferredLogicalWidth(); 1024 } 1025 return mainAxisExtent - mainAxisBorderAndPadding; 1041 // FIXME: implement 9.3.2 C. 1042 // FIXME: implement 9.3.2 D. 1043 1044 // 9.3.2 E. Otherwise, size the item into the available space using its used flex basis in place of its main size. 1045 { 1046 ScopedFlexBasisAsChildMainSize flexBasisScope(child, flexBasis, mainAxisIsChildInlineAxis(child)); 1047 if (mainAxisIsChildInlineAxis(child)) 1048 return child.maxPreferredLogicalWidth() - mainAxisBorderAndPadding; 1049 1050 if (childHasIntrinsicMainAxisSize(child)) 1051 child.setNeedsLayout(MarkOnlyThis); 1052 child.layoutIfNeeded(); 1053 return child.logicalHeight() - mainAxisBorderAndPadding; 1054 } 1026 1055 } 1027 1056 … … 1261 1290 } 1262 1291 1263 std::pair<LayoutUnit, LayoutUnit> RenderFlexibleBox::computeFlexItemMinMaxSizes(RenderBox& child )1292 std::pair<LayoutUnit, LayoutUnit> RenderFlexibleBox::computeFlexItemMinMaxSizes(RenderBox& child, bool relayoutChildren) 1264 1293 { 1265 1294 Length max = mainSizeLengthForChild(MaxSize, child); … … 1280 1309 if (child.isRenderReplaced() && childHasComputableAspectRatio(child) && childCrossSizeIsDefinite(child, childCrossSizeLength)) 1281 1310 contentSize = computeMainSizeFromAspectRatioUsing(child, childCrossSizeLength); 1282 else 1311 else { 1312 if (childHasIntrinsicMainAxisSize(child)) { 1313 // If this condition is true, then computeMainAxisExtentForChild will call 1314 // child.intrinsicContentLogicalHeight() and child.scrollbarLogicalHeight(), 1315 // so if the child has intrinsic min/max/preferred size, run layout on it now to make sure 1316 // its logical height and scroll bars are up to date. 1317 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child); 1318 // Don't resolve percentages in children. This is especially important for the min-height calculation, 1319 // where we want percentages to be treated as auto. 1320 if (child.needsLayout() || !m_intrinsicSizeAlongMainAxis.contains(&child)) { 1321 if (isHorizontalWritingMode() == child.isHorizontalWritingMode()) 1322 child.setOverridingContainingBlockContentLogicalHeight(std::nullopt); 1323 else 1324 child.setOverridingContainingBlockContentLogicalWidth(std::nullopt); 1325 1326 child.clearOverridingContentSize(); 1327 child.setChildNeedsLayout(MarkOnlyThis); 1328 child.layoutIfNeeded(); 1329 cacheChildMainSize(child); 1330 child.clearOverridingContainingBlockContentSize(); 1331 } 1332 } 1283 1333 contentSize = computeMainAxisExtentForChild(child, MinSize, Length(LengthType::MinContent)).value_or(0); 1334 } 1284 1335 if (child.hasIntrinsicAspectRatio() && child.intrinsicSize().height()) 1285 1336 contentSize = adjustChildSizeForAspectRatioCrossAxisMinAndMax(child, contentSize); … … 1368 1419 auto childHadLayout = child.everHadLayout(); 1369 1420 child.clearOverridingContentSize(); 1370 if (childHasIntrinsicMainAxisSize(child)) {1371 // If this condition is true, then computeMainAxisExtentForChild will call1372 // child.intrinsicContentLogicalHeight() and child.scrollbarLogicalHeight(),1373 // so if the child has intrinsic min/max/preferred size, run layout on it now to make sure1374 // its logical height and scroll bars are up to date.1375 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);1376 // Don't resolve percentages in children. This is especially important for the min-height calculation,1377 // where we want percentages to be treated as auto. For flex-basis itself, this is not a problem because1378 // by definition we have an indefinite flex basis here and thus percentages should not resolve.1379 if (child.needsLayout() || !m_intrinsicSizeAlongMainAxis.contains(&child)) {1380 if (isHorizontalWritingMode() == child.isHorizontalWritingMode())1381 child.setOverridingContainingBlockContentLogicalHeight(std::nullopt);1382 else1383 child.setOverridingContainingBlockContentLogicalWidth(std::nullopt);1384 child.clearOverridingContentSize();1385 child.setChildNeedsLayout(MarkOnlyThis);1386 child.layoutIfNeeded();1387 cacheChildMainSize(child);1388 child.clearOverridingContainingBlockContentSize();1389 }1390 }1391 1392 1421 LayoutUnit borderAndPadding = isHorizontalFlow() ? child.horizontalBorderAndPaddingExtent() : child.verticalBorderAndPaddingExtent(); 1393 LayoutUnit child InnerFlexBaseSize = computeInnerFlexBaseSizeForChild(child, borderAndPadding);1422 LayoutUnit childFlexBaseSize = computeFlexBaseSizeForChild(child, borderAndPadding); 1394 1423 LayoutUnit margin = isHorizontalFlow() ? child.horizontalMarginExtent() : child.verticalMarginExtent(); 1395 return FlexItem(child, child InnerFlexBaseSize, borderAndPadding, margin, computeFlexItemMinMaxSizes(child), childHadLayout);1424 return FlexItem(child, childFlexBaseSize, borderAndPadding, margin, computeFlexItemMinMaxSizes(child, relayoutChildren), childHadLayout); 1396 1425 } 1397 1426 … … 1889 1918 } 1890 1919 // We may have already forced relayout for orthogonal flowing children in 1891 // compute InnerFlexBaseSizeForChild.1920 // computeFlexBaseSizeForChild. 1892 1921 bool forceChildRelayout = relayoutChildren && !m_relaidOutChildren.contains(&child); 1893 1922 if (!forceChildRelayout && childHasPercentHeightDescendants(child)) { … … 2144 2173 LayoutUnit childWidth = std::max(0_lu, lineCrossAxisExtent - crossAxisMarginExtentForChild(child)); 2145 2174 childWidth = child.constrainLogicalWidthInFragmentByMinMax(childWidth, crossAxisContentExtent(), *this, nullptr); 2146 2175 2147 2176 if (childWidth != child.logicalWidth()) { 2148 2177 child.setOverridingLogicalWidth(childWidth); -
trunk/Source/WebCore/rendering/RenderFlexibleBox.h
r282463 r284359 151 151 LayoutUnit computeMainSizeFromAspectRatioUsing(const RenderBox& child, Length crossSizeLength) const; 152 152 void setFlowAwareLocationForChild(RenderBox& child, const LayoutPoint&); 153 LayoutUnit compute InnerFlexBaseSizeForChild(RenderBox& child, LayoutUnit mainAxisBorderAndPadding);153 LayoutUnit computeFlexBaseSizeForChild(RenderBox& child, LayoutUnit mainAxisBorderAndPadding); 154 154 void adjustAlignmentForChild(RenderBox& child, LayoutUnit); 155 155 ItemPosition alignmentForChild(const RenderBox& child) const; … … 177 177 LayoutUnit computeChildMarginValue(Length margin); 178 178 void prepareOrderIteratorAndMargins(); 179 std::pair<LayoutUnit, LayoutUnit> computeFlexItemMinMaxSizes(RenderBox& child );179 std::pair<LayoutUnit, LayoutUnit> computeFlexItemMinMaxSizes(RenderBox& child, bool relayoutChildren); 180 180 LayoutUnit adjustChildSizeForAspectRatioCrossAxisMinAndMax(const RenderBox& child, LayoutUnit childSize); 181 181 FlexItem constructFlexItem(RenderBox&, bool relayoutChildren);
Note:
See TracChangeset
for help on using the changeset viewer.