Title: [279549] trunk/Source/WebCore
Revision
279549
Author
[email protected]
Date
2021-07-04 08:47:12 -0700 (Sun, 04 Jul 2021)

Log Message

[LFC][TFC] Cleanup computedPreferredWidthForColumns and distributeAvailableSpace functions
https://bugs.webkit.org/show_bug.cgi?id=227669

Reviewed by Antti Koivisto.

Let's create some sub-scopes within these long functions to make them read better.

* layout/formattingContexts/table/TableFormattingContext.cpp:
(WebCore::Layout::TableFormattingContext::computedPreferredWidthForColumns):
* layout/formattingContexts/table/TableLayout.cpp:
(WebCore::Layout::distributeAvailableSpace):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (279548 => 279549)


--- trunk/Source/WebCore/ChangeLog	2021-07-04 14:10:24 UTC (rev 279548)
+++ trunk/Source/WebCore/ChangeLog	2021-07-04 15:47:12 UTC (rev 279549)
@@ -1,3 +1,17 @@
+2021-07-04  Zalan Bujtas  <[email protected]>
+
+        [LFC][TFC] Cleanup computedPreferredWidthForColumns and distributeAvailableSpace functions
+        https://bugs.webkit.org/show_bug.cgi?id=227669
+
+        Reviewed by Antti Koivisto.
+
+        Let's create some sub-scopes within these long functions to make them read better.
+
+        * layout/formattingContexts/table/TableFormattingContext.cpp:
+        (WebCore::Layout::TableFormattingContext::computedPreferredWidthForColumns):
+        * layout/formattingContexts/table/TableLayout.cpp:
+        (WebCore::Layout::distributeAvailableSpace):
+
 2021-07-04  Alan Bujtas  <[email protected]>
 
         [LFC][TFC] 100% percent width column(s) make the table stretch

Modified: trunk/Source/WebCore/layout/formattingContexts/table/TableFormattingContext.cpp (279548 => 279549)


--- trunk/Source/WebCore/layout/formattingContexts/table/TableFormattingContext.cpp	2021-07-04 14:10:24 UTC (rev 279548)
+++ trunk/Source/WebCore/layout/formattingContexts/table/TableFormattingContext.cpp	2021-07-04 15:47:12 UTC (rev 279549)
@@ -324,114 +324,127 @@
     // 2. Collect the fixed width <col>s.
     auto& columnList = grid.columns().list();
     auto& formattingGeometry = this->formattingGeometry();
-    for (auto& column : columnList) {
-        auto fixedWidth = [&] () -> std::optional<LayoutUnit> {
-            auto* columnBox = column.box();
-            if (!columnBox) {
-                // Anonymous columns don't have associated layout boxes and can't have fixed col size.
-                return { };
-            }
-            if (auto width = columnBox->columnWidth())
-                return width;
-            return formattingGeometry.computedColumnWidth(*columnBox);
-        }();
+    auto collectColsFixedWidth = [&] {
+        for (auto& column : columnList) {
+            auto fixedWidth = [&] () -> std::optional<LayoutUnit> {
+                auto* columnBox = column.box();
+                if (!columnBox) {
+                    // Anonymous columns don't have associated layout boxes and can't have fixed col size.
+                    return { };
+                }
+                if (auto width = columnBox->columnWidth())
+                    return width;
+                return formattingGeometry.computedColumnWidth(*columnBox);
+            }();
         if (fixedWidth)
             column.setComputedLogicalWidth({ *fixedWidth, LengthType::Fixed });
-    }
+        }
+    };
+    collectColsFixedWidth();
 
     auto hasColumnWithPercentWidth = false;
     auto hasColumnWithFixedWidth = false;
     Vector<std::optional<LayoutUnit>> maximumFixedColumnWidths(columnList.size());
     Vector<std::optional<float>> maximumPercentColumnWidths(columnList.size());
-    for (auto& cell : grid.cells()) {
-        auto& cellBox = cell->box();
-        ASSERT(cellBox.establishesBlockFormattingContext());
 
-        auto intrinsicWidth = formattingState.intrinsicWidthConstraintsForBox(cellBox);
-        if (!intrinsicWidth) {
-            intrinsicWidth = formattingGeometry.intrinsicWidthConstraintsForCellContent(*cell);
-            formattingState.setIntrinsicWidthConstraintsForBox(cellBox, *intrinsicWidth);
-        }
-        auto cellPosition = cell->position();
-        auto& cellStyle = cellBox.style();
-        // Expand it with border and padding.
-        auto horizontalBorderAndPaddingWidth = formattingGeometry.computedCellBorder(*cell).width()
-            + formattingGeometry.fixedValue(cellStyle.paddingLeft()).value_or(0)
-            + formattingGeometry.fixedValue(cellStyle.paddingRight()).value_or(0);
-        intrinsicWidth->expand(horizontalBorderAndPaddingWidth);
-        // Spanner cells put their intrinsic widths on the initial slots.
-        grid.slot(cellPosition)->setWidthConstraints(*intrinsicWidth);
+    auto collectCellsIntrinsicWidthConstraints = [&] {
+        for (auto& cell : grid.cells()) {
+            auto& cellBox = cell->box();
+            ASSERT(cellBox.establishesBlockFormattingContext());
 
-        auto cellLogicalWidth = cellStyle.logicalWidth();
-        auto columnIndex = cellPosition.column;
-        switch (cellLogicalWidth.type()) {
-        case LengthType::Fixed: {
-            auto fixedWidth = LayoutUnit { cellLogicalWidth.value() } + horizontalBorderAndPaddingWidth;
-            maximumFixedColumnWidths[columnIndex] = std::max(maximumFixedColumnWidths[columnIndex].value_or(0_lu), fixedWidth);
-            hasColumnWithFixedWidth = true;
-            break;
+            auto intrinsicWidth = formattingState.intrinsicWidthConstraintsForBox(cellBox);
+            if (!intrinsicWidth) {
+                intrinsicWidth = formattingGeometry.intrinsicWidthConstraintsForCellContent(*cell);
+                formattingState.setIntrinsicWidthConstraintsForBox(cellBox, *intrinsicWidth);
+            }
+            auto cellPosition = cell->position();
+            auto& cellStyle = cellBox.style();
+            // Expand it with border and padding.
+            auto horizontalBorderAndPaddingWidth = formattingGeometry.computedCellBorder(*cell).width()
+                + formattingGeometry.fixedValue(cellStyle.paddingLeft()).value_or(0)
+                + formattingGeometry.fixedValue(cellStyle.paddingRight()).value_or(0);
+            intrinsicWidth->expand(horizontalBorderAndPaddingWidth);
+            // Spanner cells put their intrinsic widths on the initial slots.
+            grid.slot(cellPosition)->setWidthConstraints(*intrinsicWidth);
+
+            auto cellLogicalWidth = cellStyle.logicalWidth();
+            auto columnIndex = cellPosition.column;
+            switch (cellLogicalWidth.type()) {
+            case LengthType::Fixed: {
+                auto fixedWidth = LayoutUnit { cellLogicalWidth.value() } + horizontalBorderAndPaddingWidth;
+                maximumFixedColumnWidths[columnIndex] = std::max(maximumFixedColumnWidths[columnIndex].value_or(0_lu), fixedWidth);
+                hasColumnWithFixedWidth = true;
+                break;
+            }
+            case LengthType::Percent: {
+                maximumPercentColumnWidths[columnIndex] = std::max(maximumPercentColumnWidths[columnIndex].value_or(0.f), cellLogicalWidth.percent());
+                hasColumnWithPercentWidth = true;
+                break;
+            }
+            case LengthType::Relative:
+                ASSERT_NOT_IMPLEMENTED_YET();
+                break;
+            default:
+                break;
+            }
         }
-        case LengthType::Percent: {
-            maximumPercentColumnWidths[columnIndex] = std::max(maximumPercentColumnWidths[columnIndex].value_or(0.f), cellLogicalWidth.percent());
-            hasColumnWithPercentWidth = true;
-            break;
-        }
-        case LengthType::Relative:
-            ASSERT_NOT_IMPLEMENTED_YET();
-            break;
-        default:
-            break;
-        }
-    }
+    };
+    collectCellsIntrinsicWidthConstraints();
 
     Vector<IntrinsicWidthConstraints> columnIntrinsicWidths(columnList.size());
-    // 3. Collect he min/max width for each column but ignore column spans for now.
     Vector<SlotPosition> spanningCellPositionList;
     size_t numberOfActualColumns = 0;
-    for (size_t columnIndex = 0; columnIndex < columnList.size(); ++columnIndex) {
-        auto columnHasNonSpannedCell = false;
-        for (size_t rowIndex = 0; rowIndex < grid.rows().size(); ++rowIndex) {
-            auto& slot = *grid.slot({ columnIndex, rowIndex });
-            if (slot.isColumnSpanned())
-                continue;
-            columnHasNonSpannedCell = true;
-            if (slot.hasColumnSpan()) {
-                spanningCellPositionList.append({ columnIndex, rowIndex });
-                continue;
+    auto computeColumnsIntrinsicWidthConstraints = [&] {
+        // 3. Collect he min/max width for each column but ignore column spans for now.
+        for (size_t columnIndex = 0; columnIndex < columnList.size(); ++columnIndex) {
+            auto columnHasNonSpannedCell = false;
+            for (size_t rowIndex = 0; rowIndex < grid.rows().size(); ++rowIndex) {
+                auto& slot = *grid.slot({ columnIndex, rowIndex });
+                if (slot.isColumnSpanned())
+                    continue;
+                columnHasNonSpannedCell = true;
+                if (slot.hasColumnSpan()) {
+                    spanningCellPositionList.append({ columnIndex, rowIndex });
+                    continue;
+                }
+                auto widthConstraints = slot.widthConstraints();
+                if (auto fixedColumnWidth = maximumFixedColumnWidths[columnIndex])
+                    widthConstraints.maximum = std::max(*fixedColumnWidth, widthConstraints.minimum);
+
+                columnIntrinsicWidths[columnIndex].minimum = std::max(widthConstraints.minimum, columnIntrinsicWidths[columnIndex].minimum);
+                columnIntrinsicWidths[columnIndex].maximum = std::max(widthConstraints.maximum, columnIntrinsicWidths[columnIndex].maximum);
             }
-            auto widthConstraints = slot.widthConstraints();
-            if (auto fixedColumnWidth = maximumFixedColumnWidths[columnIndex])
-                widthConstraints.maximum = std::max(*fixedColumnWidth, widthConstraints.minimum);
-
-            columnIntrinsicWidths[columnIndex].minimum = std::max(widthConstraints.minimum, columnIntrinsicWidths[columnIndex].minimum);
-            columnIntrinsicWidths[columnIndex].maximum = std::max(widthConstraints.maximum, columnIntrinsicWidths[columnIndex].maximum);
+            if (columnHasNonSpannedCell)
+                ++numberOfActualColumns;
         }
-        if (columnHasNonSpannedCell)
-            ++numberOfActualColumns;
-    }
+    };
+    computeColumnsIntrinsicWidthConstraints();
 
-    // 4. Distribute the spanning min/max widths.
-    for (auto spanningCellPosition : spanningCellPositionList) {
-        auto& slot = *grid.slot(spanningCellPosition);
-        auto& cell = slot.cell();
-        ASSERT(slot.hasColumnSpan());
-        auto widthConstraintsToDistribute = slot.widthConstraints();
-        for (size_t columnSpanIndex = cell.startColumn(); columnSpanIndex < cell.endColumn(); ++columnSpanIndex)
-            widthConstraintsToDistribute -= columnIntrinsicWidths[columnSpanIndex];
-        // <table style="border-spacing: 50px"><tr><td colspan=2>long long text</td></tr><tr><td>lo</td><td>xt</td><tr></table>
-        // [long long text]
-        // [lo]        [xt]
-        // While it looks like the spanning cell has to distribute all its spanning width, the border-spacing takes most of the space and
-        // no distribution is needed at all.
-        widthConstraintsToDistribute -= (cell.columnSpan() - 1) * grid.horizontalSpacing();
-        // FIXME: Check if fixed width columns should be skipped here.
-        widthConstraintsToDistribute.minimum = std::max(LayoutUnit { }, widthConstraintsToDistribute.minimum / cell.columnSpan());
-        widthConstraintsToDistribute.maximum = std::max(LayoutUnit { }, widthConstraintsToDistribute.maximum / cell.columnSpan());
-        if (widthConstraintsToDistribute.minimum || widthConstraintsToDistribute.maximum) {
+    auto resolveSpanningCells = [&] {
+        // 4. Distribute the spanning min/max widths.
+        for (auto spanningCellPosition : spanningCellPositionList) {
+            auto& slot = *grid.slot(spanningCellPosition);
+            auto& cell = slot.cell();
+            ASSERT(slot.hasColumnSpan());
+            auto widthConstraintsToDistribute = slot.widthConstraints();
             for (size_t columnSpanIndex = cell.startColumn(); columnSpanIndex < cell.endColumn(); ++columnSpanIndex)
-                columnIntrinsicWidths[columnSpanIndex] += widthConstraintsToDistribute;
+                widthConstraintsToDistribute -= columnIntrinsicWidths[columnSpanIndex];
+            // <table style="border-spacing: 50px"><tr><td colspan=2>long long text</td></tr><tr><td>lo</td><td>xt</td><tr></table>
+            // [long long text]
+            // [lo]        [xt]
+            // While it looks like the spanning cell has to distribute all its spanning width, the border-spacing takes most of the space and
+            // no distribution is needed at all.
+            widthConstraintsToDistribute -= (cell.columnSpan() - 1) * grid.horizontalSpacing();
+            // FIXME: Check if fixed width columns should be skipped here.
+            widthConstraintsToDistribute.minimum = std::max(LayoutUnit { }, widthConstraintsToDistribute.minimum / cell.columnSpan());
+            widthConstraintsToDistribute.maximum = std::max(LayoutUnit { }, widthConstraintsToDistribute.maximum / cell.columnSpan());
+            if (widthConstraintsToDistribute.minimum || widthConstraintsToDistribute.maximum) {
+                for (size_t columnSpanIndex = cell.startColumn(); columnSpanIndex < cell.endColumn(); ++columnSpanIndex)
+                    columnIntrinsicWidths[columnSpanIndex] += widthConstraintsToDistribute;
+            }
         }
-    }
+    };
+    resolveSpanningCells();
 
     // 5. The table min/max widths is just the accumulated column constraints with the percent adjustment.
     auto tableWidthConstraints = IntrinsicWidthConstraints { };
@@ -438,13 +451,19 @@
     for (auto& columnIntrinsicWidth : columnIntrinsicWidths)
         tableWidthConstraints += columnIntrinsicWidth;
 
-    // 6. Adjust the table max width with the percent column values if applicable.
-    if (hasColumnWithFixedWidth && !hasColumnWithPercentWidth) {
-        for (size_t columnIndex = 0; columnIndex < columnList.size(); ++columnIndex) {
-            if (auto fixedWidth = maximumFixedColumnWidths[columnIndex])
-                columnList[columnIndex].setComputedLogicalWidth({ *fixedWidth, LengthType::Fixed });
-        }
-    } else if (hasColumnWithPercentWidth) {
+    auto adjustColumnsWithPercentAndFixedWidthValues = [&] {
+        // 6. Adjust the table max width with the percent column values if applicable.
+        if (!hasColumnWithFixedWidth && !hasColumnWithPercentWidth)
+            return;
+
+        if (hasColumnWithFixedWidth && !hasColumnWithPercentWidth) {
+            for (size_t columnIndex = 0; columnIndex < columnList.size(); ++columnIndex) {
+                if (auto fixedWidth = maximumFixedColumnWidths[columnIndex])
+                    columnList[columnIndex].setComputedLogicalWidth({ *fixedWidth, LengthType::Fixed });
+            }
+            return;
+        } 
+
         auto remainingPercent = 100.0f;
         auto percentMaximumWidth = LayoutUnit { };
         auto nonPercentColumnsWidth = LayoutUnit { };
@@ -480,9 +499,10 @@
             // It may very well be an ancient bug we need to support (it maps to the epsilon value in AutoTableLayout::computeIntrinsicLogicalWidths which is to avoid division by zero).
             adjustedMaximumWidth = LayoutUnit::max();
         }
+        tableWidthConstraints.maximum = std::max(tableWidthConstraints.maximum, adjustedMaximumWidth);
+    };
+    adjustColumnsWithPercentAndFixedWidthValues();
 
-        tableWidthConstraints.maximum = std::max(tableWidthConstraints.maximum, adjustedMaximumWidth);
-    }
     // Expand the preferred width with leading and trailing cell spacing (note that column spanners count as one cell).
     tableWidthConstraints += (numberOfActualColumns + 1) * grid.horizontalSpacing();
     return tableWidthConstraints;

Modified: trunk/Source/WebCore/layout/formattingContexts/table/TableLayout.cpp (279548 => 279549)


--- trunk/Source/WebCore/layout/formattingContexts/table/TableLayout.cpp	2021-07-04 14:10:24 UTC (rev 279548)
+++ trunk/Source/WebCore/layout/formattingContexts/table/TableLayout.cpp	2021-07-04 15:47:12 UTC (rev 279549)
@@ -119,206 +119,219 @@
 {
     auto& columns = grid.columns();
     auto& rows = grid.rows();
-    // 1. Collect the non-spanning spaces first. They are used for the final distribution as well as for distributing the spanning space.
     Vector<std::optional<GridSpace>> resolvedItems(SpanType::size(grid));
-    for (size_t columnIndex = 0; columnIndex < columns.size(); ++columnIndex) {
-        for (size_t rowIndex = 0; rowIndex < rows.size(); ++rowIndex) {
-            auto& slot = *grid.slot({ columnIndex, rowIndex });
-            if (SpanType::hasSpan(slot) || SpanType::isSpanned(slot))
-                continue;
-            auto index = SpanType::index(columnIndex, rowIndex);
-            auto currentSpace = slotSpace(slot, index);
-            if (!resolvedItems[index]) {
-                resolvedItems[index] = currentSpace;
-                continue;
+    auto collectNonSpanningCells = [&] {
+        // 1. Collect the non-spanning spaces first. They are used for the final distribution as well as for distributing the spanning space.
+        for (size_t columnIndex = 0; columnIndex < columns.size(); ++columnIndex) {
+            for (size_t rowIndex = 0; rowIndex < rows.size(); ++rowIndex) {
+                auto& slot = *grid.slot({ columnIndex, rowIndex });
+                if (SpanType::hasSpan(slot) || SpanType::isSpanned(slot))
+                    continue;
+                auto index = SpanType::index(columnIndex, rowIndex);
+                auto currentSpace = slotSpace(slot, index);
+                if (!resolvedItems[index]) {
+                    resolvedItems[index] = currentSpace;
+                    continue;
+                }
+                auto& resolvedItem = resolvedItems[index];
+                // FIXME: Add support for mixed column/row types e.g. first row first column is fixed, while second row first column is percent.
+                ASSERT(resolvedItem->type == currentSpace.type);
+                resolvedItem->preferredSize = std::max(resolvedItem->preferredSize, currentSpace.preferredSize);
+                resolvedItem->flexBase = std::max(resolvedItem->flexBase, currentSpace.flexBase);
             }
-            auto& resolvedItem = resolvedItems[index];
-            // FIXME: Add support for mixed column/row types e.g. first row first column is fixed, while second row first column is percent.
-            ASSERT(resolvedItem->type == currentSpace.type);
-            resolvedItem->preferredSize = std::max(resolvedItem->preferredSize, currentSpace.preferredSize);
-            resolvedItem->flexBase = std::max(resolvedItem->flexBase, currentSpace.flexBase);
         }
-    }
+    };
+    collectNonSpanningCells();
 
-    // 2. Collect the spanning cells.
-    struct SpanningCell {
-        SlotPosition position;
-        GridSpace unresolvedSpace;
-    };
-    Vector<SpanningCell> spanningCells;
-    for (size_t rowIndex = 0; rowIndex < rows.size(); ++rowIndex) {
-        for (size_t columnIndex = 0; columnIndex < columns.size(); ++columnIndex) {
-            auto& slot = *grid.slot({ columnIndex, rowIndex });
-            if (SpanType::hasSpan(slot))
-                spanningCells.append({ { columnIndex, rowIndex }, slotSpace(slot, SpanType::index(columnIndex, rowIndex)) });
+    auto collectAndDistributeSpanningCells = [&] {
+        // 2. Collect the spanning cells.
+        struct SpanningCell {
+            SlotPosition position;
+            GridSpace unresolvedSpace;
+        };
+        Vector<SpanningCell> spanningCells;
+        for (size_t rowIndex = 0; rowIndex < rows.size(); ++rowIndex) {
+            for (size_t columnIndex = 0; columnIndex < columns.size(); ++columnIndex) {
+                auto& slot = *grid.slot({ columnIndex, rowIndex });
+                if (SpanType::hasSpan(slot))
+                    spanningCells.append({ { columnIndex, rowIndex }, slotSpace(slot, SpanType::index(columnIndex, rowIndex)) });
+            }
         }
-    }
-    // We need these spanning cells in the order of the number of columns/rows they span so that
-    // we can resolve overlapping spans starting with the shorter ones e.g.
-    // <td colspan=4>#a</td><td>#b</td>
-    // <td colspan=2>#c</td><td colspan=3>#d</td>
-    std::sort(spanningCells.begin(), spanningCells.end(), [&] (auto& a, auto& b) {
-        return SpanType::spanCount(grid.slot(a.position)->cell()) < SpanType::spanCount(grid.slot(b.position)->cell());
-    });
+        // We need these spanning cells in the order of the number of columns/rows they span so that
+        // we can resolve overlapping spans starting with the shorter ones e.g.
+        // <td colspan=4>#a</td><td>#b</td>
+        // <td colspan=2>#c</td><td colspan=3>#d</td>
+        std::sort(spanningCells.begin(), spanningCells.end(), [&] (auto& a, auto& b) {
+            return SpanType::spanCount(grid.slot(a.position)->cell()) < SpanType::spanCount(grid.slot(b.position)->cell());
+        });
 
-    // 3. Distribute the spanning cells' mimimum space across the columns/rows using the non-spanning spaces.
-    // e.g. [ 1 ][ 5 ][ 1 ]
-    //      [    9   ][ 1 ]
-    // The initial widths are: [ 2 ][ 7 ][ 1 ]
-    for (auto spanningCell : spanningCells) {
-        auto& cell = grid.slot(spanningCell.position)->cell();
-        auto unresolvedSpanningSpace = spanningCell.unresolvedSpace;
-        if (!resolvedItems[SpanType::startSpan(cell)] || !resolvedItems[SpanType::endSpan(cell) - 1]) {
-            // <td colspan=4>#a</td><td>#b</td>
-            // <td colspan=2>#c</td><td colspan=3>#d</td>
-            // Unresolved columns are: 1 2 3 4
-            // 1. Take colspan=2 (shortest span) and resolve column 1 and 2
-            // 2. Take colspan=3 and resolve column 3 and 4 (5 is resolved because it already has a non-spanning cell).
-            // 3. colspan=4 needs no resolving because all the spanned columns (1 2 3 4) have already been resolved.
-            auto unresolvedColumnCount = cell.columnSpan();
-            for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex) {
-                if (!resolvedItems[spanIndex])
-                    continue;
+        // 3. Distribute the spanning cells' mimimum space across the columns/rows using the non-spanning spaces.
+        // e.g. [ 1 ][ 5 ][ 1 ]
+        //      [    9   ][ 1 ]
+        // The initial widths are: [ 2 ][ 7 ][ 1 ]
+        for (auto spanningCell : spanningCells) {
+            auto& cell = grid.slot(spanningCell.position)->cell();
+            auto unresolvedSpanningSpace = spanningCell.unresolvedSpace;
+            if (!resolvedItems[SpanType::startSpan(cell)] || !resolvedItems[SpanType::endSpan(cell) - 1]) {
+                // <td colspan=4>#a</td><td>#b</td>
+                // <td colspan=2>#c</td><td colspan=3>#d</td>
+                // Unresolved columns are: 1 2 3 4
+                // 1. Take colspan=2 (shortest span) and resolve column 1 and 2
+                // 2. Take colspan=3 and resolve column 3 and 4 (5 is resolved because it already has a non-spanning cell).
+                // 3. colspan=4 needs no resolving because all the spanned columns (1 2 3 4) have already been resolved.
+                auto unresolvedColumnCount = cell.columnSpan();
+                for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex) {
+                    if (!resolvedItems[spanIndex])
+                        continue;
+                    ASSERT(unresolvedColumnCount);
+                    --unresolvedColumnCount;
+                    unresolvedSpanningSpace -= *resolvedItems[spanIndex];
+                }
                 ASSERT(unresolvedColumnCount);
-                --unresolvedColumnCount;
-                unresolvedSpanningSpace -= *resolvedItems[spanIndex];
-            }
-            ASSERT(unresolvedColumnCount);
-            auto equalSpaceForSpannedColumns = unresolvedSpanningSpace / unresolvedColumnCount;
-            for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex) {
-                if (resolvedItems[spanIndex])
+                auto equalSpaceForSpannedColumns = unresolvedSpanningSpace / unresolvedColumnCount;
+                for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex) {
+                    if (resolvedItems[spanIndex])
+                        continue;
+                    resolvedItems[spanIndex] = equalSpaceForSpannedColumns;
+                }
+            } else {
+                // 1. Collect the non-spanning resolved spaces.
+                // 2. Distribute the extra space among the spanned columns/rows based on the resolved space values.
+                // e.g. spanning width: [   9   ]. Resolved widths for the spanned columns: [ 1 ] [ 2 ]
+                // New resolved widths: [ 3 ] [ 6 ].
+                auto resolvedSpanningSpace = GridSpace { };
+                for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex)
+                    resolvedSpanningSpace += *resolvedItems[spanIndex];
+                if (resolvedSpanningSpace.preferredSize >= unresolvedSpanningSpace.preferredSize) {
+                    // The spanning cell fits the spanned columns/rows just fine. Nothing to distribute.
                     continue;
-                resolvedItems[spanIndex] = equalSpaceForSpannedColumns;
+                }
+                auto spacing = SpanType::spacing(grid) * (SpanType::spanCount(cell) - 1);
+                auto spaceToDistribute = unresolvedSpanningSpace - GridSpace { { }, spacing, spacing } - resolvedSpanningSpace;
+                if (!spaceToDistribute.isEmpty()) {
+                    auto columnsFlexBase = spaceToDistribute.flexBase / resolvedSpanningSpace.flexBase;
+                    for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex)
+                        *resolvedItems[spanIndex] += GridSpace { resolvedItems[spanIndex]->type, resolvedItems[spanIndex]->preferredSize * columnsFlexBase, resolvedItems[spanIndex]->flexBase * columnsFlexBase };
+                }
             }
-        } else {
-            // 1. Collect the non-spaning resolved spaces.
-            // 2. Distribute the extra space among the spanned columns/rows based on the resolved space values.
-            // e.g. spanning width: [   9   ]. Resolved widths for the spanned columns: [ 1 ] [ 2 ]
-            // New resolved widths: [ 3 ] [ 6 ].
-            auto resolvedSpanningSpace = GridSpace { };
-            for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex)
-                resolvedSpanningSpace += *resolvedItems[spanIndex];
-            if (resolvedSpanningSpace.preferredSize >= unresolvedSpanningSpace.preferredSize) {
-                // The spanning cell fits the spanned columns/rows just fine. Nothing to distribute.
-                continue;
-            }
-            auto spacing = SpanType::spacing(grid) * (SpanType::spanCount(cell) - 1);
-            auto spaceToDistribute = unresolvedSpanningSpace - GridSpace { { }, spacing, spacing } - resolvedSpanningSpace;
-            if (!spaceToDistribute.isEmpty()) {
-                auto columnsFlexBase = spaceToDistribute.flexBase / resolvedSpanningSpace.flexBase;
-                for (auto spanIndex = SpanType::startSpan(cell); spanIndex < SpanType::endSpan(cell); ++spanIndex)
-                    *resolvedItems[spanIndex] += GridSpace { resolvedItems[spanIndex]->type, resolvedItems[spanIndex]->preferredSize * columnsFlexBase, resolvedItems[spanIndex]->flexBase * columnsFlexBase };
-            }
         }
-    }
-    // 4. Distribute the extra space using the final resolved sizes.
+    };
+    collectAndDistributeSpanningCells();
+
     Vector<LayoutUnit> distributedSpaces(resolvedItems.size());
-    float spaceToDistribute = availableSpace - (resolvedItems.size() + 1) * SpanType::spacing(grid);
-    auto adjustabledSpace = GridSpace { };
-    for (auto& resolvedItem : resolvedItems) {
-        ASSERT(resolvedItem);
-        adjustabledSpace += *resolvedItem;
-    }
-    spaceToDistribute -= adjustabledSpace.preferredSize;
+    auto spaceToDistribute = 0.f;
+    auto computeSpaceToDistribute = [&] {
+        // 4. Distribute the extra space using the final resolved sizes.
+        spaceToDistribute = availableSpace - (resolvedItems.size() + 1) * SpanType::spacing(grid);
+        auto adjustabledSpace = GridSpace { };
+        for (auto& resolvedItem : resolvedItems) {
+            ASSERT(resolvedItem);
+            adjustabledSpace += *resolvedItem;
+        }
+        spaceToDistribute -= adjustabledSpace.preferredSize;
+    };
+    computeSpaceToDistribute();
+
     // Let's start with the preferred size for each column.
     for (size_t columnIndex = 0; columnIndex < resolvedItems.size(); ++columnIndex)
         distributedSpaces[columnIndex] = LayoutUnit { resolvedItems[columnIndex]->preferredSize };
 
-    if (!spaceToDistribute) {
-        // Preferred size covers the spaces. There's nothing extra spaace to distribute.
-        return distributedSpaces;
-    }
+    auto distributeSpace = [&] {
+        if (!spaceToDistribute)
+            return;
+        // Setup the priority lists. We use these when expanding/shrinking slots.
+        Vector<size_t> autoColumnIndexes;
+        Vector<size_t> relativeColumnIndexes;
+        Vector<size_t> fixedColumnIndexes;
+        Vector<size_t> percentColumnIndexes;
 
-    // Setup the priority lists. We use these when expanding/shrinking slots.
-    Vector<size_t> autoColumnIndexes;
-    Vector<size_t> relativeColumnIndexes;
-    Vector<size_t> fixedColumnIndexes;
-    Vector<size_t> percentColumnIndexes;
+        for (size_t columnIndex = 0; columnIndex < resolvedItems.size(); ++columnIndex) {
+            switch (resolvedItems[columnIndex]->type) {
+            case GridSpace::Type::Percent:
+                percentColumnIndexes.append(columnIndex);
+                break;
+            case GridSpace::Type::Fixed:
+                fixedColumnIndexes.append(columnIndex);
+                break;
+            case GridSpace::Type::Relative:
+                relativeColumnIndexes.append(columnIndex);
+                break;
+            case GridSpace::Type::Auto:
+                autoColumnIndexes.append(columnIndex);
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+                break;
+            }
+        }
 
-    for (size_t columnIndex = 0; columnIndex < resolvedItems.size(); ++columnIndex) {
-        switch (resolvedItems[columnIndex]->type) {
-        case GridSpace::Type::Percent:
-            percentColumnIndexes.append(columnIndex);
-            break;
-        case GridSpace::Type::Fixed:
-            fixedColumnIndexes.append(columnIndex);
-            break;
-        case GridSpace::Type::Relative:
-            relativeColumnIndexes.append(columnIndex);
-            break;
-        case GridSpace::Type::Auto:
-            autoColumnIndexes.append(columnIndex);
-            break;
-        default:
-            ASSERT_NOT_REACHED();
-            break;
+        if (spaceToDistribute > 0) {
+            // Each column can get some extra space.
+            auto hasSpaceToDistribute = [&] {
+                ASSERT(spaceToDistribute > -LayoutUnit::epsilon());
+                return spaceToDistribute > LayoutUnit::epsilon();
+            };
+
+            auto expandSpace = [&](const auto& columnIndexes) {
+                auto adjustabledSpace = GridSpace { };
+                for (auto& columnIndex : columnIndexes)
+                    adjustabledSpace += *resolvedItems[columnIndex];
+
+                auto columnsFlexBase = adjustabledSpace.flexBase ? spaceToDistribute / adjustabledSpace.flexBase : 0.f;
+                for (auto& columnIndex : columnIndexes) {
+                    auto extraSpace = columnsFlexBase * resolvedItems[columnIndex]->flexBase;
+                    distributedSpaces[columnIndex] += LayoutUnit { extraSpace };
+                    spaceToDistribute -= extraSpace;
+                    if (!hasSpaceToDistribute())
+                        return;
+                }
+            };
+            // We distribute the extra space among columns in the priority order as follows:
+            expandSpace(fixedColumnIndexes);
+            if (hasSpaceToDistribute())
+                expandSpace(percentColumnIndexes);
+            if (hasSpaceToDistribute())
+                expandSpace(relativeColumnIndexes);
+            if (hasSpaceToDistribute())
+                expandSpace(autoColumnIndexes);
+            ASSERT(!hasSpaceToDistribute());
+            return;
         }
-    }
+        // Can't accommodate the preferred width. Let's use the priority list to shrink columns.
+        auto spaceNeeded = -spaceToDistribute;
 
-    if (spaceToDistribute > 0) {
-        // Each column can get some extra space.
-        auto hasSpaceToDistribute = [&] {
-            ASSERT(spaceToDistribute > -LayoutUnit::epsilon());
-            return spaceToDistribute > LayoutUnit::epsilon();
+        auto needsMoreSpace = [&] {
+            ASSERT(spaceNeeded > -LayoutUnit::epsilon());
+            return spaceNeeded > LayoutUnit::epsilon();
         };
 
-        auto expandSpace = [&](const auto& columnIndexes) {
+        auto shrinkSpace = [&](const auto& columnIndexes) {
             auto adjustabledSpace = GridSpace { };
             for (auto& columnIndex : columnIndexes)
                 adjustabledSpace += *resolvedItems[columnIndex];
 
-            auto columnsFlexBase = adjustabledSpace.flexBase ? spaceToDistribute / adjustabledSpace.flexBase : 0.f;
+            auto columnsFlexBase = adjustabledSpace.flexBase ? spaceNeeded / adjustabledSpace.flexBase : 0.f;
             for (auto& columnIndex : columnIndexes) {
-                auto extraSpace = columnsFlexBase * resolvedItems[columnIndex]->flexBase;
-                distributedSpaces[columnIndex] += LayoutUnit { extraSpace };
-                spaceToDistribute -= extraSpace;
-                if (!hasSpaceToDistribute())
+                auto& resolvedItem = *resolvedItems[columnIndex];
+                auto spaceToRemove = std::min(resolvedItem.preferredSize - resolvedItem.minimumSize, columnsFlexBase * resolvedItem.flexBase);
+                spaceToRemove = std::min(spaceToRemove, spaceNeeded);
+                distributedSpaces[columnIndex] -= spaceToRemove;
+                spaceNeeded -= spaceToRemove;
+                if (!needsMoreSpace())
                     return;
             }
         };
-        // We distribute the extra space among columns in the priority order as follows:
-        expandSpace(fixedColumnIndexes);
-        if (hasSpaceToDistribute())
-            expandSpace(percentColumnIndexes);
-        if (hasSpaceToDistribute())
-            expandSpace(relativeColumnIndexes);
-        if (hasSpaceToDistribute())
-            expandSpace(autoColumnIndexes);
-        ASSERT(!hasSpaceToDistribute());
-        return distributedSpaces;
-    }
-    // Can't accomodate the preferred width. Let's use the priority list to shrink columns.
-    auto spaceNeeded = -spaceToDistribute;
-
-    auto needsMoreSpace = [&] {
-        ASSERT(spaceNeeded > -LayoutUnit::epsilon());
-        return spaceNeeded > LayoutUnit::epsilon();
+        shrinkSpace(autoColumnIndexes);
+        if (needsMoreSpace())
+            shrinkSpace(relativeColumnIndexes);
+        if (needsMoreSpace())
+            shrinkSpace(fixedColumnIndexes);
+        if (needsMoreSpace())
+            shrinkSpace(percentColumnIndexes);
+        ASSERT(!needsMoreSpace());
     };
+    distributeSpace();
 
-    auto shrinkSpace = [&](const auto& columnIndexes) {
-        auto adjustabledSpace = GridSpace { };
-        for (auto& columnIndex : columnIndexes)
-            adjustabledSpace += *resolvedItems[columnIndex];
-
-        auto columnsFlexBase = adjustabledSpace.flexBase ? spaceNeeded / adjustabledSpace.flexBase : 0.f;
-        for (auto& columnIndex : columnIndexes) {
-            auto& resolvedItem = *resolvedItems[columnIndex];
-            auto spaceToRemove = std::min(resolvedItem.preferredSize - resolvedItem.minimumSize, columnsFlexBase * resolvedItem.flexBase);
-            spaceToRemove = std::min(spaceToRemove, spaceNeeded);
-            distributedSpaces[columnIndex] -= spaceToRemove;
-            spaceNeeded -= spaceToRemove;
-            if (!needsMoreSpace())
-                return;
-        }
-    };
-    shrinkSpace(autoColumnIndexes);
-    if (needsMoreSpace())
-        shrinkSpace(relativeColumnIndexes);
-    if (needsMoreSpace())
-        shrinkSpace(fixedColumnIndexes);
-    if (needsMoreSpace())
-        shrinkSpace(percentColumnIndexes);
-    ASSERT(!needsMoreSpace());
     return distributedSpaces;
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to