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

Reply via email to