Title: [295000] trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp
- Revision
- 295000
- Author
- za...@apple.com
- Date
- 2022-05-28 09:18:55 -0700 (Sat, 28 May 2022)
Log Message
Transition flex-grow computation to flex-basis based
https://bugs.webkit.org/show_bug.cgi?id=241057
Reviewed by Antti Koivisto.
1. Introduce StrechingFlexItem to cache growth related values
2. Use flex-basis as the base for the flex grow computation
3. Compute the final logical width values
(This is very similar to how we compute "shrink values".)
* Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp:
(WebCore::Layout::FlexFormattingContext::computeLogicalWidthForShrinkingFlexItems):
(WebCore::Layout::FlexFormattingContext::computeLogicalWidthForStretchingFlexItems):
Canonical link: https://commits.webkit.org/251098@main
Modified Paths
Diff
Modified: trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp (294999 => 295000)
--- trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp 2022-05-28 13:26:40 UTC (rev 294999)
+++ trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp 2022-05-28 16:18:55 UTC (rev 295000)
@@ -224,8 +224,7 @@
auto computeTotalShrinkAndOverflowingSpace = [&] {
// Collect flex items with non-zero flex-shrink value. flex-shrink: 0 flex items
// don't participate in content flexing.
- for (size_t index = 0; index < logicalFlexItemList.size(); ++index) {
- auto& flexItem = logicalFlexItemList[index];
+ for (auto& flexItem : logicalFlexItemList) {
auto& style = flexItem.layoutBox->style();
auto baseSize = style.flexBasis().isFixed() ? LayoutUnit { style.flexBasis().value() } : flexItem.rect.width();
if (auto shrinkValue = style.flexShrink()) {
@@ -277,64 +276,68 @@
{
auto& formattingState = this->formattingState();
+ auto totalFlexibleSpace = LayoutUnit { };
auto totalGrowth = 0.f;
auto flexGrowBase = 0.f;
- Vector<size_t> stretchingItems;
+ struct StrechingFlexItem {
+ float flexGrow { 0 };
+ LayoutUnit minimumSize;
+ LayoutUnit flexBasis;
+ LogicalFlexItem& flexItem;
+ bool isFrozen { false };
+ };
+ Vector<StrechingFlexItem> stretchingItems;
auto computeTotalGrowthAndFlexibleSpace = [&] {
// Collect flex items with non-zero flex-grow value. flex-grow: 0 (initial) flex items
// don't participate in available space distribution.
- for (size_t index = 0; index < logicalFlexItemList.size(); ++index) {
- auto& logicalFlexItem = logicalFlexItemList[index];
- if (auto flexGrow = logicalFlexItem.layoutBox->style().flexGrow()) {
- stretchingItems.append(index);
+ for (auto& flexItem : logicalFlexItemList) {
+ auto& style = flexItem.layoutBox->style();
+ auto baseSize = style.flexBasis().isFixed() ? LayoutUnit { style.flexBasis().value() } : flexItem.rect.width();
+ if (auto growValue = style.flexGrow()) {
+ auto flexGrow = growValue * baseSize;
+ stretchingItems.append({ flexGrow, formattingState.intrinsicWidthConstraintsForBox(*flexItem.layoutBox)->minimum, baseSize, flexItem, { } });
totalGrowth += flexGrow;
+ totalFlexibleSpace += baseSize;
} else
- availableSpace -= logicalFlexItem.rect.width();
+ availableSpace -= baseSize;
}
if (totalGrowth)
- flexGrowBase = availableSpace / totalGrowth;
+ flexGrowBase = (availableSpace - totalFlexibleSpace) / totalGrowth;
};
computeTotalGrowthAndFlexibleSpace();
if (!totalGrowth)
return;
- auto totalLogicalWidth = [&] {
+ auto adjustGrowthBase = [&] {
// This is where we compute how much space the flexing boxes take up if we just
// let them flex by their flex-grow value. Note that we can't size them below their minimum content width.
// Such flex items are removed from the final overflow distribution.
auto accumulatedWidth = LayoutUnit { };
- for (auto flexItemIndex : stretchingItems) {
- auto& flexItem = logicalFlexItemList[flexItemIndex];
-
- auto flexGrow = flexItem.layoutBox->style().flexGrow();
- auto flexedSize = flexGrow * flexGrowBase;
- auto minimumSize = formattingState.intrinsicWidthConstraintsForBox(*flexItem.layoutBox)->minimum;
- if (minimumSize >= flexedSize) {
- accumulatedWidth += minimumSize;
- totalGrowth -= flexGrow;
- } else
- accumulatedWidth += flexedSize;
+ while (true) {
+ auto didFreeze = false;
+ for (auto& stretchingFlex : stretchingItems) {
+ auto flexedSize = stretchingFlex.flexBasis + stretchingFlex.flexGrow * flexGrowBase;
+ if (stretchingFlex.minimumSize >= flexedSize) {
+ stretchingFlex.isFrozen = true;
+ didFreeze = true;
+ totalGrowth -= stretchingFlex.flexGrow;
+ totalFlexibleSpace -= stretchingFlex.flexBasis;
+ availableSpace -= stretchingFlex.minimumSize;
+ }
+ }
+ if (!didFreeze)
+ break;
+ flexGrowBase = totalGrowth ? (totalFlexibleSpace - availableSpace) / totalGrowth : 0.f;
}
- return accumulatedWidth;
};
- auto overflowWidth = totalLogicalWidth() - availableSpace;
- ASSERT(overflowWidth >= 0);
+ adjustGrowthBase();
auto computeLogicalWidth = [&] {
// Adjust the total grow width by the overflow value (shrink) except when min content with disagrees.
- for (auto flexItemIndex : stretchingItems) {
- auto& flexItem = logicalFlexItemList[flexItemIndex];
-
- auto flexGrow = flexItem.layoutBox->style().flexGrow();
- auto flexedSize = flexGrow * flexGrowBase;
- auto minimumSize = formattingState.intrinsicWidthConstraintsForBox(*flexItem.layoutBox)->minimum;
- if (minimumSize >= flexedSize)
- flexItem.rect.setWidth(minimumSize);
- else {
- auto distributedOverflow = overflowWidth / totalGrowth * flexGrow;
- flexItem.rect.setWidth(std::max(minimumSize, LayoutUnit { flexedSize - distributedOverflow }));
- }
+ for (auto& stretchingFlex : stretchingItems) {
+ auto flexedSize = LayoutUnit { stretchingFlex.flexBasis + (stretchingFlex.flexGrow * flexGrowBase) };
+ stretchingFlex.flexItem.rect.setWidth(std::max(stretchingFlex.minimumSize, flexedSize));
}
};
computeLogicalWidth();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes