[css-grid] Remove most of the usage of SizingOperation
authorsvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Apr 2017 15:34:40 +0000 (15:34 +0000)
committersvillar@igalia.com <svillar@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Apr 2017 15:34:40 +0000 (15:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171225

Reviewed by Darin Adler.

Source/WebCore:

SizingOperation was added as a way to modify the behaviour of the track sizing algorithm
with the specifics for intrinsic size computations. The problem is that although intrinsic
size computation does imply indefinite sizes, the opposite is not always true. For example,
a grid container with height:auto would compute the row sizes with an indefinite size but is
not part of the intrinsic size (preferred widths) computation.

That's why it was wrongly used in some parts of the current code, in most of the cases is
more than enough to check whether the available space is indefinite or not. In order to do
that we have to keep both available sizes (height & width) around all the time to properly
support orthogonal flows.

This change does not imply any change in behaviour.

* rendering/GridTrackSizingAlgorithm.cpp:
(WebCore::GridTrackSizingAlgorithm::setAvailableSpace):
(WebCore::GridTrackSizingAlgorithm::computeTrackBasedSize):
(WebCore::GridTrackSizingAlgorithm::initialBaseSize):
(WebCore::GridTrackSizingAlgorithm::initialGrowthLimit):
(WebCore::GridTrackSizingAlgorithm::sizeTrackToFitNonSpanningItem):
(WebCore::GridTrackSizingAlgorithm::increaseSizesToAccommodateSpanningItems):
(WebCore::GridTrackSizingAlgorithm::assumedRowsSizeForOrthogonalChild):
(WebCore::GridTrackSizingAlgorithm::gridAreaBreadthForChild):
(WebCore::GridTrackSizingAlgorithm::gridTrackSize):
(WebCore::IndefiniteSizeStrategy::findUsedFlexFraction):
(WebCore::IndefiniteSizeStrategy::recomputeUsedFlexFractionIfNeeded):
(WebCore::GridTrackSizingAlgorithm::initializeTrackSizes):
(WebCore::GridTrackSizingAlgorithm::setup):
(WebCore::GridTrackSizingAlgorithm::reset):
* rendering/GridTrackSizingAlgorithm.h:
(WebCore::GridTrackSizingAlgorithmStrategy::availableSpace):
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::availableSpaceForGutters):
(WebCore::RenderGrid::computeTrackBasedLogicalHeight):
(WebCore::RenderGrid::computeTrackSizesForDefiniteSize):
(WebCore::RenderGrid::layoutBlock):
(WebCore::RenderGrid::gridGap):
(WebCore::RenderGrid::guttersSize):
(WebCore::RenderGrid::computeIntrinsicLogicalWidths):
(WebCore::RenderGrid::computeTrackSizesForIndefiniteSize):
(WebCore::RenderGrid::computeAutoRepeatTracksCount):
(WebCore::RenderGrid::placeItemsOnGrid):
(WebCore::RenderGrid::trackSizesForComputedStyle):
(WebCore::RenderGrid::applyStretchAlignmentToTracksIfNeeded):
(WebCore::RenderGrid::offsetAndBreadthForPositionedChild):
(WebCore::RenderGrid::populateGridPositionsForDirection):
(WebCore::RenderGrid::columnAxisOffsetForChild):
(WebCore::RenderGrid::rowAxisOffsetForChild):
(WebCore::RenderGrid::gridGapForDirection): Deleted.
* rendering/RenderGrid.h:

LayoutTests:

Added a new test case which was working correctly but that was not properly tested before.

* fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows-expected.txt:
* fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@215800 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows-expected.txt
LayoutTests/fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows.html
Source/WebCore/ChangeLog
Source/WebCore/rendering/GridTrackSizingAlgorithm.cpp
Source/WebCore/rendering/GridTrackSizingAlgorithm.h
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h

index 935dd58..7a28fbd 100644 (file)
@@ -1,3 +1,15 @@
+2017-04-24  Sergio Villar Senin  <svillar@igalia.com>
+
+        [css-grid] Remove most of the usage of SizingOperation
+        https://bugs.webkit.org/show_bug.cgi?id=171225
+
+        Reviewed by Darin Adler.
+
+        Added a new test case which was working correctly but that was not properly tested before.
+
+        * fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows-expected.txt:
+        * fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows.html:
+
 2017-04-25  Joseph Pecoraro  <pecoraro@apple.com>
 
         [mac-wk1 Debug] LayoutTest http/tests/inspector/network/resource-sizes-network.html is a flaky failure
index 9dc3fbc..c1388a4 100644 (file)
@@ -17,6 +17,14 @@ body {
     grid-template-columns: 100px 25%;
     grid-template-rows: 50% 150px;
 }
+
+.definiteGridWithPercentageGaps {
+    grid-template: 5px 5px / auto;
+    grid-row-gap: 80%;
+    grid-column-gap: 20%;
+    height: 200px;
+    width: 100px;
+}
 </style>
 <script src="../../resources/check-layout.js"></script>
 <body onload="checkLayout('.grid')">
@@ -61,4 +69,10 @@ body {
         <div class="secondRowSecondColumn horizontalTB" data-offset-x="0" data-offset-y="100" data-expected-width="150" data-expected-height="20">X X X X X X X X X X X X</div>
     </div>
 </div>
+
+<p>HORIZONTAL-TB container with VERTICAL-LR item with percentage gaps.</p>
+<div class="grid definiteGridWithPercentageGaps contentStart" data-expected-width="100" data-expected-height="200">
+    <div class="bothRowFirstColumn verticalLR" style="background: cyan;" data-expected-width="10" data-expected-height="170">XXXX XXXXX</div>
+</div>
+
 </body>
index 6bd966c..4a57971 100644 (file)
@@ -1,3 +1,60 @@
+2017-04-24  Sergio Villar Senin  <svillar@igalia.com>
+
+        [css-grid] Remove most of the usage of SizingOperation
+        https://bugs.webkit.org/show_bug.cgi?id=171225
+
+        Reviewed by Darin Adler.
+
+        SizingOperation was added as a way to modify the behaviour of the track sizing algorithm
+        with the specifics for intrinsic size computations. The problem is that although intrinsic
+        size computation does imply indefinite sizes, the opposite is not always true. For example,
+        a grid container with height:auto would compute the row sizes with an indefinite size but is
+        not part of the intrinsic size (preferred widths) computation.
+
+        That's why it was wrongly used in some parts of the current code, in most of the cases is
+        more than enough to check whether the available space is indefinite or not. In order to do
+        that we have to keep both available sizes (height & width) around all the time to properly
+        support orthogonal flows.
+
+        This change does not imply any change in behaviour.
+
+        * rendering/GridTrackSizingAlgorithm.cpp:
+        (WebCore::GridTrackSizingAlgorithm::setAvailableSpace):
+        (WebCore::GridTrackSizingAlgorithm::computeTrackBasedSize):
+        (WebCore::GridTrackSizingAlgorithm::initialBaseSize):
+        (WebCore::GridTrackSizingAlgorithm::initialGrowthLimit):
+        (WebCore::GridTrackSizingAlgorithm::sizeTrackToFitNonSpanningItem):
+        (WebCore::GridTrackSizingAlgorithm::increaseSizesToAccommodateSpanningItems):
+        (WebCore::GridTrackSizingAlgorithm::assumedRowsSizeForOrthogonalChild):
+        (WebCore::GridTrackSizingAlgorithm::gridAreaBreadthForChild):
+        (WebCore::GridTrackSizingAlgorithm::gridTrackSize):
+        (WebCore::IndefiniteSizeStrategy::findUsedFlexFraction):
+        (WebCore::IndefiniteSizeStrategy::recomputeUsedFlexFractionIfNeeded):
+        (WebCore::GridTrackSizingAlgorithm::initializeTrackSizes):
+        (WebCore::GridTrackSizingAlgorithm::setup):
+        (WebCore::GridTrackSizingAlgorithm::reset):
+        * rendering/GridTrackSizingAlgorithm.h:
+        (WebCore::GridTrackSizingAlgorithmStrategy::availableSpace):
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::availableSpaceForGutters):
+        (WebCore::RenderGrid::computeTrackBasedLogicalHeight):
+        (WebCore::RenderGrid::computeTrackSizesForDefiniteSize):
+        (WebCore::RenderGrid::layoutBlock):
+        (WebCore::RenderGrid::gridGap):
+        (WebCore::RenderGrid::guttersSize):
+        (WebCore::RenderGrid::computeIntrinsicLogicalWidths):
+        (WebCore::RenderGrid::computeTrackSizesForIndefiniteSize):
+        (WebCore::RenderGrid::computeAutoRepeatTracksCount):
+        (WebCore::RenderGrid::placeItemsOnGrid):
+        (WebCore::RenderGrid::trackSizesForComputedStyle):
+        (WebCore::RenderGrid::applyStretchAlignmentToTracksIfNeeded):
+        (WebCore::RenderGrid::offsetAndBreadthForPositionedChild):
+        (WebCore::RenderGrid::populateGridPositionsForDirection):
+        (WebCore::RenderGrid::columnAxisOffsetForChild):
+        (WebCore::RenderGrid::rowAxisOffsetForChild):
+        (WebCore::RenderGrid::gridGapForDirection): Deleted.
+        * rendering/RenderGrid.h:
+
 2017-04-26  Frederic Wang  <fwang@igalia.com>
 
         Remove Document::*FrameElementsShouldIgnoreScrolling
index 15efb7e..570b21a 100644 (file)
@@ -162,6 +162,14 @@ void GridTrackSizingAlgorithm::setFreeSpace(GridTrackSizingDirection direction,
         m_freeSpaceRows = freeSpace;
 }
 
+void GridTrackSizingAlgorithm::setAvailableSpace(GridTrackSizingDirection direction, std::optional<LayoutUnit> availableSpace)
+{
+    if (direction == ForColumns)
+        m_availableSpaceColumns = availableSpace;
+    else
+        m_availableSpaceRows = availableSpace;
+}
+
 const GridTrackSize& GridTrackSizingAlgorithm::rawGridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex) const
 {
     bool isRowAxis = direction == ForColumns;
@@ -209,7 +217,7 @@ LayoutUnit GridTrackSizingAlgorithm::computeTrackBasedSize() const
     for (auto& track : allTracks)
         size += track.baseSize();
 
-    size += m_renderGrid->guttersSize(m_grid, m_direction, 0, allTracks.size(), m_sizingOperation);
+    size += m_renderGrid->guttersSize(m_grid, m_direction, 0, allTracks.size(), availableSpace());
 
     return size;
 }
@@ -222,7 +230,7 @@ LayoutUnit GridTrackSizingAlgorithm::initialBaseSize(const GridTrackSize& trackS
 
     const Length& trackLength = gridLength.length();
     if (trackLength.isSpecified())
-        return valueForLength(trackLength, std::max<LayoutUnit>(m_availableSpace.value_or(0), 0));
+        return valueForLength(trackLength, std::max<LayoutUnit>(availableSpace().value_or(0), 0));
 
     ASSERT(trackLength.isMinContent() || trackLength.isAuto() || trackLength.isMaxContent());
     return 0;
@@ -236,7 +244,7 @@ LayoutUnit GridTrackSizingAlgorithm::initialGrowthLimit(const GridTrackSize& tra
 
     const Length& trackLength = gridLength.length();
     if (trackLength.isSpecified())
-        return valueForLength(trackLength, std::max<LayoutUnit>(m_availableSpace.value_or(0), 0));
+        return valueForLength(trackLength, std::max<LayoutUnit>(availableSpace().value_or(0), 0));
 
     ASSERT(trackLength.isMinContent() || trackLength.isAuto() || trackLength.isMaxContent());
     return infinity;
@@ -259,7 +267,7 @@ void GridTrackSizingAlgorithm::sizeTrackToFitNonSpanningItem(const GridSpan& spa
     } else if (trackSize.hasMaxContentOrAutoMaxTrackBreadth()) {
         LayoutUnit growthLimit = m_strategy->maxContentForChild(gridItem);
         if (trackSize.isFitContent())
-            growthLimit = std::min(growthLimit, valueForLength(trackSize.fitContentTrackBreadth().length(), m_availableSpace.value_or(0)));
+            growthLimit = std::min(growthLimit, valueForLength(trackSize.fitContentTrackBreadth().length(), availableSpace().value_or(0)));
         track.setGrowthLimit(std::max(track.growthLimit(), growthLimit));
     }
 }
@@ -460,7 +468,7 @@ void GridTrackSizingAlgorithm::increaseSizesToAccommodateSpanningItems(const Gri
         if (filteredTracks.isEmpty())
             continue;
 
-        spanningTracksSize += m_renderGrid->guttersSize(m_grid, m_direction, itemSpan.startLine(), itemSpan.integerSpan(), m_sizingOperation);
+        spanningTracksSize += m_renderGrid->guttersSize(m_grid, m_direction, itemSpan.startLine(), itemSpan.integerSpan(), availableSpace());
 
         LayoutUnit extraSpace = itemSizeForTrackSizeComputationPhase(phase, gridItemWithSpan.gridItem()) - spanningTracksSize;
         extraSpace = std::max<LayoutUnit>(extraSpace, 0);
@@ -569,7 +577,7 @@ LayoutUnit GridTrackSizingAlgorithm::assumedRowsSizeForOrthogonalChild(const Ren
             gridAreaSize += valueForLength(maxTrackSize.length(), containingBlockAvailableSize);
     }
 
-    gridAreaSize += m_renderGrid->guttersSize(m_grid, ForRows, span.startLine(), span.integerSpan(), m_sizingOperation);
+    gridAreaSize += m_renderGrid->guttersSize(m_grid, ForRows, span.startLine(), span.integerSpan(), availableSpace(ForRows));
 
     return gridAreaIsIndefinite ? std::max(child.maxPreferredLogicalWidth(), gridAreaSize) : gridAreaSize;
 }
@@ -588,12 +596,12 @@ LayoutUnit GridTrackSizingAlgorithm::gridAreaBreadthForChild(const RenderBox& ch
     for (auto trackPosition : span)
         gridAreaBreadth += allTracks[trackPosition].baseSize();
 
-    gridAreaBreadth += m_renderGrid->guttersSize(m_grid, direction, span.startLine(), span.integerSpan(), m_sizingOperation);
+    gridAreaBreadth += m_renderGrid->guttersSize(m_grid, direction, span.startLine(), span.integerSpan(), availableSpace(direction));
 
     return gridAreaBreadth;
 }
 
-GridTrackSize GridTrackSizingAlgorithm::gridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex, SizingOperation sizingOperation) const
+GridTrackSize GridTrackSizingAlgorithm::gridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex) const
 {
     // Collapse empty auto repeat tracks if auto-fit.
     if (m_grid.hasAutoRepeatEmptyTracks(direction) && m_grid.isEmptyAutoRepeatTrack(direction, translatedIndex))
@@ -609,10 +617,10 @@ GridTrackSize GridTrackSizingAlgorithm::gridTrackSize(GridTrackSizingDirection d
     // FIXME: Ensure this condition for determining whether a size is indefinite or not is working
     // correctly for orthogonal flows.
     if (minTrackBreadth.isPercentage() || maxTrackBreadth.isPercentage()) {
-        // If the logical width/height of the grid container is indefinite, percentage values are
-        // treated as <auto>. For the inline axis this only happens when we're computing the
-        // intrinsic sizes (IntrinsicSizeComputation).
-        if (sizingOperation == IntrinsicSizeComputation || (direction == ForRows && !m_renderGrid->hasDefiniteLogicalHeight())) {
+        // FIXME: we should remove the second check later. We need it because during the second
+        // iteration of the algorithm we set definite sizes in the grid container so percents would
+        // not resolve properly (it would think that the height is definite when it is not).
+        if (!availableSpace(direction) || (direction == ForRows && !m_renderGrid->hasDefiniteLogicalHeight())) {
             if (minTrackBreadth.isPercentage())
                 minTrackBreadth = Length(Auto);
             if (maxTrackBreadth.isPercentage())
@@ -872,7 +880,7 @@ double IndefiniteSizeStrategy::findUsedFlexFraction(Vector<unsigned>& flexibleSi
     for (const auto& trackIndex : flexibleSizedTracksIndex) {
         // FIXME: we pass TrackSizing to gridTrackSize() because it does not really matter
         // as we know the track is a flex sized track. It'd be nice not to have to do that.
-        flexFraction = std::max(flexFraction, normalizedFlexFraction(allTracks[trackIndex], m_algorithm.gridTrackSize(direction, trackIndex, TrackSizing).maxTrackBreadth().flex()));
+        flexFraction = std::max(flexFraction, normalizedFlexFraction(allTracks[trackIndex], m_algorithm.gridTrackSize(direction, trackIndex).maxTrackBreadth().flex()));
     }
 
     const Grid& grid = m_algorithm.grid();
@@ -915,7 +923,7 @@ bool IndefiniteSizeStrategy::recomputeUsedFlexFractionIfNeeded(double& flexFract
 
     LayoutUnit freeSpace = checkMaxSize ? maxSize.value() : LayoutUnit(-1);
     const Grid& grid = m_algorithm.grid();
-    freeSpace = std::max(freeSpace, minSize.value()) - renderGrid->guttersSize(grid, ForRows, 0, grid.numTracks(ForRows), IntrinsicSizeComputation);
+    freeSpace = std::max(freeSpace, minSize.value()) - renderGrid->guttersSize(grid, ForRows, 0, grid.numTracks(ForRows), availableSpace());
 
     size_t numberOfTracks = m_algorithm.tracks(ForRows).size();
     flexFraction = findFrUnitSize(GridSpan::translatedDefiniteGridSpan(0, numberOfTracks), freeSpace);
@@ -988,8 +996,8 @@ void GridTrackSizingAlgorithm::initializeTrackSizes()
     ASSERT(m_flexibleSizedTracksIndex.isEmpty());
 
     Vector<GridTrack>& allTracks = tracks(m_direction);
-    const bool hasDefiniteFreeSpace = !!m_availableSpace;
-    LayoutUnit maxSize = std::max(LayoutUnit(), m_availableSpace.value_or(LayoutUnit()));
+    const bool hasDefiniteFreeSpace = !!availableSpace();
+    LayoutUnit maxSize = std::max(LayoutUnit(), availableSpace().value_or(LayoutUnit()));
     // 1. Initialize per Grid track variables.
     for (unsigned i = 0; i < allTracks.size(); ++i) {
         GridTrack& track = allTracks[i];
@@ -1119,7 +1127,7 @@ void GridTrackSizingAlgorithm::setup(GridTrackSizingDirection direction, unsigne
 {
     ASSERT(m_needsSetup);
     m_direction = direction;
-    m_availableSpace = availableSpace;
+    setAvailableSpace(direction, availableSpace);
 
     m_sizingOperation = sizingOperation;
     switch (m_sizingOperation) {
@@ -1180,6 +1188,8 @@ void GridTrackSizingAlgorithm::reset()
     m_rows.shrink(0);
     m_contentSizedTracksIndex.shrink(0);
     m_flexibleSizedTracksIndex.shrink(0);
+    setAvailableSpace(ForRows, std::nullopt);
+    setAvailableSpace(ForColumns, std::nullopt);
 }
 
 #ifndef NDEBUG
index da66e1f..dce627d 100644 (file)
@@ -102,7 +102,7 @@ public:
 
     // Required by RenderGrid. Try to minimize the exposed surface.
     const Grid& grid() const { return m_grid; }
-    GridTrackSize gridTrackSize(GridTrackSizingDirection, unsigned translatedIndex, SizingOperation) const;
+    GridTrackSize gridTrackSize(GridTrackSizingDirection, unsigned translatedIndex) const;
 
     LayoutUnit minContentSize() const { return m_minContentSize; };
     LayoutUnit maxContentSize() const { return m_maxContentSize; };
@@ -113,12 +113,15 @@ public:
     std::optional<LayoutUnit> freeSpace(GridTrackSizingDirection direction) const { return direction == ForColumns ? m_freeSpaceColumns : m_freeSpaceRows; }
     void setFreeSpace(GridTrackSizingDirection, std::optional<LayoutUnit>);
 
+    std::optional<LayoutUnit> availableSpace(GridTrackSizingDirection direction) const { return direction == ForColumns ? m_availableSpaceColumns : m_availableSpaceRows; }
+    void setAvailableSpace(GridTrackSizingDirection, std::optional<LayoutUnit>);
+
 #ifndef NDEBUG
     bool tracksAreWiderThanMinTrackBreadth() const;
 #endif
 
 private:
-    GridTrackSize gridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex) const { return gridTrackSize(direction, translatedIndex, m_sizingOperation); }
+    std::optional<LayoutUnit> availableSpace() const { return availableSpace(m_direction); }
     const GridTrackSize& rawGridTrackSize(GridTrackSizingDirection, unsigned translatedIndex) const;
     LayoutUnit assumedRowsSizeForOrthogonalChild(const RenderBox&) const;
     LayoutUnit computeTrackBasedSize() const;
@@ -156,7 +159,8 @@ private:
     bool isValidTransition() const;
 
     bool m_needsSetup { true };
-    std::optional<LayoutUnit> m_availableSpace;
+    std::optional<LayoutUnit> m_availableSpaceRows;
+    std::optional<LayoutUnit> m_availableSpaceColumns;
 
     std::optional<LayoutUnit> m_freeSpaceColumns;
     std::optional<LayoutUnit> m_freeSpaceRows;
@@ -234,6 +238,7 @@ protected:
     double findFrUnitSize(const GridSpan& tracksSpan, LayoutUnit leftOverSpace) const { return m_algorithm.findFrUnitSize(tracksSpan, leftOverSpace); }
     void distributeSpaceToTracks(Vector<GridTrack*>& tracks, LayoutUnit& availableLogicalSpace) const { m_algorithm.distributeSpaceToTracks<MaximizeTracks>(tracks, nullptr, availableLogicalSpace); }
     const RenderGrid* renderGrid() const { return m_algorithm.m_renderGrid; }
+    std::optional<LayoutUnit> availableSpace() const { return m_algorithm.availableSpace(); }
 
     GridTrackSizingAlgorithm& m_algorithm;
 };
index d888b6d..e35dc46 100644 (file)
@@ -120,6 +120,18 @@ bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle& oldStyle)
         || oldStyle.namedGridColumnLines() != style().namedGridColumnLines();
 }
 
+// This method optimizes the gutters computation by skiping the available size
+// call if gaps are fixed size (it's only needed for percentages).
+std::optional<LayoutUnit> RenderGrid::availableSpaceForGutters(GridTrackSizingDirection direction) const
+{
+    bool isRowAxis = direction == ForColumns;
+    const Length& gap = isRowAxis ? style().gridColumnGap() : style().gridRowGap();
+    if (!gap.isPercent())
+        return std::nullopt;
+
+    return isRowAxis ? availableLogicalWidth() : availableLogicalHeightForPercentageComputation();
+}
+
 LayoutUnit RenderGrid::computeTrackBasedLogicalHeight() const
 {
     LayoutUnit logicalHeight;
@@ -128,14 +140,14 @@ LayoutUnit RenderGrid::computeTrackBasedLogicalHeight() const
     for (const auto& row : allRows)
         logicalHeight += row.baseSize();
 
-    logicalHeight += guttersSize(m_grid, ForRows, 0, allRows.size(), TrackSizing);
+    logicalHeight += guttersSize(m_grid, ForRows, 0, allRows.size(), availableSpaceForGutters(ForRows));
 
     return logicalHeight;
 }
 
 void RenderGrid::computeTrackSizesForDefiniteSize(GridTrackSizingDirection direction, LayoutUnit availableSpace)
 {
-    LayoutUnit totalGuttersSize = guttersSize(m_grid, direction, 0, m_grid.numTracks(direction), TrackSizing);
+    LayoutUnit totalGuttersSize = guttersSize(m_grid, direction, 0, m_grid.numTracks(direction), availableSpace);
     LayoutUnit freeSpace = availableSpace - totalGuttersSize;
 
     m_trackSizingAlgorithm.setup(direction, numTracks(direction, m_grid), TrackSizing, availableSpace, freeSpace);
@@ -183,6 +195,9 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
     preparePaginationBeforeBlockLayout(relayoutChildren);
 
     LayoutSize previousSize = size();
+    // FIXME: We should use RenderBlock::hasDefiniteLogicalHeight() but it does not work for positioned stuff.
+    // FIXME: Consider caching the hasDefiniteLogicalHeight value throughout the layout.
+    bool hasDefiniteLogicalHeight = hasOverrideLogicalContentHeight() || computeContentLogicalHeight(MainOrPreferredSize, style().logicalHeight(), std::nullopt);
 
     // We need to clear both own and containingBlock override sizes of orthogonal items to ensure we get the
     // same result when grid's intrinsic size is computed again in the updateLogicalWidth call bellow.
@@ -205,18 +220,15 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
     // It doesn't get included in the normal layout process but is instead skipped.
     layoutExcludedChildren(relayoutChildren);
 
-    placeItemsOnGrid(m_grid, TrackSizing);
+    LayoutUnit availableSpaceForColumns = availableLogicalWidth();
+    placeItemsOnGrid(m_grid, availableSpaceForColumns);
 
     // At this point the logical width is always definite as the above call to updateLogicalWidth()
     // properly resolves intrinsic sizes. We cannot do the same for heights though because many code
     // paths inside updateLogicalHeight() require a previous call to setLogicalHeight() to resolve
     // heights properly (like for positioned items for example).
-    LayoutUnit availableSpaceForColumns = availableLogicalWidth();
     computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
 
-    // FIXME: We should use RenderBlock::hasDefiniteLogicalHeight() but it does not work for positioned stuff.
-    // FIXME: Consider caching the hasDefiniteLogicalHeight value throughout the layout.
-    bool hasDefiniteLogicalHeight = hasOverrideLogicalContentHeight() || computeContentLogicalHeight(MainOrPreferredSize, style().logicalHeight(), std::nullopt);
     if (!hasDefiniteLogicalHeight) {
         m_minContentHeight = LayoutUnit();
         m_maxContentHeight = LayoutUnit();
@@ -279,27 +291,23 @@ void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
     clearNeedsLayout();
 }
 
-LayoutUnit RenderGrid::gridGapForDirection(GridTrackSizingDirection direction, SizingOperation sizingOperation) const
+LayoutUnit RenderGrid::gridGap(GridTrackSizingDirection direction, std::optional<LayoutUnit> availableSize) const
 {
-    LayoutUnit availableSize;
     const Length& gap = direction == ForColumns ? style().gridColumnGap() : style().gridRowGap();
-    
-    // FIXME: Figure out what to do when availableLogicalHeightForPercentageComputation has
-    // no value.
-    if (sizingOperation == TrackSizing && gap.isPercent())
-        availableSize = direction == ForColumns ? availableLogicalWidth() : availableLogicalHeightForPercentageComputation().value_or(LayoutUnit());
-    
-    // FIXME: Maybe we could cache the computed percentage as a performance
-    // improvement.
-    return valueForLength(gap, availableSize);
+    return valueForLength(gap, availableSize.value_or(0));
 }
 
-LayoutUnit RenderGrid::guttersSize(const Grid& grid, GridTrackSizingDirection direction, unsigned startLine, unsigned span, SizingOperation sizingOperation) const
+LayoutUnit RenderGrid::gridGap(GridTrackSizingDirection direction) const
+{
+    return gridGap(direction, availableSpaceForGutters(direction));
+}
+
+LayoutUnit RenderGrid::guttersSize(const Grid& grid, GridTrackSizingDirection direction, unsigned startLine, unsigned span, std::optional<LayoutUnit> availableSize) const
 {
     if (span <= 1)
         return { };
 
-    LayoutUnit gap = gridGapForDirection(direction, sizingOperation);
+    LayoutUnit gap = gridGap(direction, availableSize);
 
     // Fast path, no collapsing tracks.
     if (!grid.hasAutoRepeatEmptyTracks(direction))
@@ -360,9 +368,9 @@ void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Layo
     LayoutUnit childMinWidth;
     LayoutUnit childMaxWidth;
     bool hadExcludedChildren = computePreferredWidthsForExcludedChildren(childMinWidth, childMaxWidth);
-    
+
     Grid grid(const_cast<RenderGrid&>(*this));
-    placeItemsOnGrid(grid, IntrinsicSizeComputation);
+    placeItemsOnGrid(grid, std::nullopt);
 
     GridTrackSizingAlgorithm algorithm(this, grid);
     computeTrackSizesForIndefiniteSize(algorithm, ForColumns, grid, minLogicalWidth, maxLogicalWidth);
@@ -383,7 +391,7 @@ void RenderGrid::computeTrackSizesForIndefiniteSize(GridTrackSizingAlgorithm& al
     algorithm.run();
 
     size_t numberOfTracks = algorithm.tracks(direction).size();
-    LayoutUnit totalGuttersSize = guttersSize(grid, direction, 0, numberOfTracks, IntrinsicSizeComputation);
+    LayoutUnit totalGuttersSize = guttersSize(grid, direction, 0, numberOfTracks, std::nullopt);
 
     minIntrinsicSize = algorithm.minContentSize() + totalGuttersSize;
     maxIntrinsicSize = algorithm.maxContentSize() + totalGuttersSize;
@@ -428,8 +436,9 @@ GridTrackSizingDirection RenderGrid::flowAwareDirectionForChild(const RenderBox&
     return !isOrthogonalChild(child) ? direction : (direction == ForColumns ? ForRows : ForColumns);
 }
 
-unsigned RenderGrid::computeAutoRepeatTracksCount(GridTrackSizingDirection direction, SizingOperation sizingOperation) const
+unsigned RenderGrid::computeAutoRepeatTracksCount(GridTrackSizingDirection direction, std::optional<LayoutUnit> availableSize) const
 {
+    ASSERT(!availableSize || availableSize.value() != -1);
     bool isRowAxis = direction == ForColumns;
     const auto& autoRepeatTracks = isRowAxis ? style().gridAutoRepeatColumns() : style().gridAutoRepeatRows();
     unsigned autoRepeatTrackListLength = autoRepeatTracks.size();
@@ -437,19 +446,13 @@ unsigned RenderGrid::computeAutoRepeatTracksCount(GridTrackSizingDirection direc
     if (!autoRepeatTrackListLength)
         return 0;
 
-    std::optional<LayoutUnit> availableSize;
-    if (isRowAxis) {
-        if (sizingOperation != IntrinsicSizeComputation)
-            availableSize = availableLogicalWidth();
-    } else {
-        availableSize = computeContentLogicalHeight(MainOrPreferredSize, style().logicalHeight(), std::nullopt);
-        if (!availableSize) {
-            const Length& maxLength = style().logicalMaxHeight();
-            if (!maxLength.isUndefined())
-                availableSize = computeContentLogicalHeight(MaxSize, maxLength, std::nullopt);
+    if (!isRowAxis && !availableSize) {
+        const Length& maxLength = style().logicalMaxHeight();
+        if (!maxLength.isUndefined()) {
+            availableSize = computeContentLogicalHeight(MaxSize, maxLength, std::nullopt);
+            if (availableSize)
+                availableSize = constrainContentBoxLogicalHeightByMinMax(availableSize.value(), std::nullopt);
         }
-        if (availableSize)
-            availableSize = constrainContentBoxLogicalHeightByMinMax(availableSize.value(), std::nullopt);
     }
 
     bool needsToFulfillMinimumSize = false;
@@ -487,7 +490,7 @@ unsigned RenderGrid::computeAutoRepeatTracksCount(GridTrackSizingDirection direc
 
     // Add gutters as if there where only 1 auto repeat track. Gaps between auto repeat tracks will be added later when
     // computing the repetitions.
-    LayoutUnit gapSize = gridGapForDirection(direction, sizingOperation);
+    LayoutUnit gapSize = gridGap(direction, availableSize);
     tracksSize += gapSize * trackSizes.size();
 
     LayoutUnit freeSpace = availableSize.value() - tracksSize;
@@ -552,10 +555,14 @@ unsigned RenderGrid::clampAutoRepeatTracks(GridTrackSizingDirection direction, u
     return std::min(autoRepeatTracks, maxTracks - insertionPoint);
 }
 
-void RenderGrid::placeItemsOnGrid(Grid& grid, SizingOperation sizingOperation) const
+// FIXME): We shouldn't have to pass the available logical width as argument. The problem is that
+// availableLogicalWidth() does always return a value even if we cannot resolve it like when
+// computing the intrinsic size (preferred widths). That's why we pass the responsibility to the
+// caller who does know whether the available logical width is indefinite or not.
+void RenderGrid::placeItemsOnGrid(Grid& grid, std::optional<LayoutUnit> availableSpace) const
 {
-    unsigned autoRepeatColumns = computeAutoRepeatTracksCount(ForColumns, sizingOperation);
-    unsigned autoRepeatRows = computeAutoRepeatTracksCount(ForRows, sizingOperation);
+    unsigned autoRepeatColumns = computeAutoRepeatTracksCount(ForColumns, availableSpace);
+    unsigned autoRepeatRows = computeAutoRepeatTracksCount(ForRows, availableLogicalHeightForPercentageComputation());
 
     autoRepeatRows = clampAutoRepeatTracks(ForRows, autoRepeatRows);
     autoRepeatColumns = clampAutoRepeatTracks(ForColumns, autoRepeatColumns);
@@ -807,7 +814,7 @@ Vector<LayoutUnit> RenderGrid::trackSizesForComputedStyle(GridTrackSizingDirecti
 
     ASSERT(!m_grid.needsItemsPlacement());
     bool hasCollapsedTracks = m_grid.hasAutoRepeatEmptyTracks(direction);
-    LayoutUnit gap = !hasCollapsedTracks ? gridGapForDirection(direction, TrackSizing) : LayoutUnit();
+    LayoutUnit gap = !hasCollapsedTracks ? gridGap(direction) : LayoutUnit();
     tracks.reserveCapacity(numPositions - 1);
     for (size_t i = 0; i < numPositions - 2; ++i)
         tracks.append(positions[i + 1] - positions[i] - offsetBetweenTracks - gap);
@@ -818,7 +825,7 @@ Vector<LayoutUnit> RenderGrid::trackSizesForComputedStyle(GridTrackSizingDirecti
 
     size_t remainingEmptyTracks = m_grid.autoRepeatEmptyTracks(direction)->size();
     size_t lastLine = tracks.size();
-    gap = gridGapForDirection(direction, TrackSizing);
+    gap = gridGap(direction);
     for (size_t i = 1; i < lastLine; ++i) {
         if (m_grid.isEmptyAutoRepeatTrack(direction, i - 1))
             --remainingEmptyTracks;
@@ -853,7 +860,7 @@ void RenderGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection
     Vector<GridTrack>& allTracks = m_trackSizingAlgorithm.tracks(direction);
     Vector<unsigned> autoSizedTracksIndex;
     for (unsigned i = 0; i < allTracks.size(); ++i) {
-        const GridTrackSize& trackSize = m_trackSizingAlgorithm.gridTrackSize(direction, i, TrackSizing);
+        const GridTrackSize& trackSize = m_trackSizingAlgorithm.gridTrackSize(direction, i);
         if (trackSize.hasAutoMaxTrackBreadth())
             autoSizedTracksIndex.append(i);
     }
@@ -1000,6 +1007,7 @@ void RenderGrid::offsetAndBreadthForPositionedChild(const RenderBox& child, Grid
             start = m_rowPositions[startLine] - borderBefore();
     }
 
+    std::optional<LayoutUnit> availableSizeForGutters = availableSpaceForGutters(direction);
     LayoutUnit end = isRowAxis ? clientLogicalWidth() : clientLogicalHeight();
     if (!endIsAuto) {
         if (isRowAxis) {
@@ -1013,7 +1021,7 @@ void RenderGrid::offsetAndBreadthForPositionedChild(const RenderBox& child, Grid
         // These vectors store line positions including gaps, but we shouldn't consider them for the edges of the grid.
         if (endLine > 0 && endLine < lastLine) {
             ASSERT(!m_grid.needsItemsPlacement());
-            end -= guttersSize(m_grid, direction, endLine - 1, 2, TrackSizing);
+            end -= guttersSize(m_grid, direction, endLine - 1, 2, availableSizeForGutters);
             end -= isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
         }
     }
@@ -1031,7 +1039,7 @@ void RenderGrid::offsetAndBreadthForPositionedChild(const RenderBox& child, Grid
 
             if (endLine > 0 && endLine < lastLine) {
                 ASSERT(!m_grid.needsItemsPlacement());
-                offset += guttersSize(m_grid, direction, endLine - 1, 2, TrackSizing);
+                offset += guttersSize(m_grid, direction, endLine - 1, 2, availableSizeForGutters);
                 offset += isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
             }
         }
@@ -1077,7 +1085,7 @@ void RenderGrid::populateGridPositionsForDirection(GridTrackSizingDirection dire
         // If we have collapsed tracks we just ignore gaps here and add them later as we might not
         // compute the gap between two consecutive tracks without examining the surrounding ones.
         bool hasCollapsedTracks = m_grid.hasAutoRepeatEmptyTracks(direction);
-        LayoutUnit gap = !hasCollapsedTracks ? gridGapForDirection(direction, TrackSizing) : LayoutUnit();
+        LayoutUnit gap = !hasCollapsedTracks ? gridGap(direction) : LayoutUnit();
         unsigned nextToLastLine = numberOfLines - 2;
         for (unsigned i = 0; i < nextToLastLine; ++i)
             positions[i + 1] = positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap;
@@ -1086,7 +1094,7 @@ void RenderGrid::populateGridPositionsForDirection(GridTrackSizingDirection dire
         // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to collapse (they
         // coincide exactly) except on the edges of the grid where they become 0.
         if (hasCollapsedTracks) {
-            gap = gridGapForDirection(direction, TrackSizing);
+            gap = gridGap(direction);
             unsigned remainingEmptyTracks = m_grid.autoRepeatEmptyTracks(direction)->size();
             LayoutUnit gapAccumulator;
             for (unsigned i = 1; i < lastLine; ++i) {
@@ -1482,7 +1490,7 @@ LayoutUnit RenderGrid::columnAxisOffsetForChild(const RenderBox& child) const
         // so we need to subtract them to get the actual end position for a given row
         // (this does not have to be done for the last track as there are no more m_rowPositions after it).
         if (childEndLine < m_rowPositions.size() - 1)
-            endOfRow -= gridGapForDirection(ForRows, TrackSizing) + m_offsetBetweenRows;
+            endOfRow -= gridGap(ForRows) + m_offsetBetweenRows;
         LayoutUnit columnAxisChildSize = isOrthogonalChild(child) ? child.logicalWidth() + child.marginLogicalWidth() : child.logicalHeight() + child.marginLogicalHeight();
         auto overflow = alignSelfForChild(child).overflow();
         LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(overflow, endOfRow - startOfRow, columnAxisChildSize);
@@ -1514,7 +1522,7 @@ LayoutUnit RenderGrid::rowAxisOffsetForChild(const RenderBox& child) const
         // so we need to subtract them to get the actual end position for a given column
         // (this does not have to be done for the last track as there are no more m_columnPositions after it).
         if (childEndLine < m_columnPositions.size() - 1)
-            endOfColumn -= gridGapForDirection(ForColumns, TrackSizing) + m_offsetBetweenColumns;
+            endOfColumn -= gridGap(ForColumns) + m_offsetBetweenColumns;
         LayoutUnit rowAxisChildSize = isOrthogonalChild(child) ? child.logicalHeight() + child.marginLogicalHeight() : child.logicalWidth() + child.marginLogicalWidth();
         auto overflow = justifySelfForChild(child).overflow();
         LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(overflow, endOfColumn - startOfColumn, rowAxisChildSize);
index bcdf2b0..f7732c9 100644 (file)
@@ -62,7 +62,7 @@ public:
 
     // Required by GridTrackSizingAlgorithm. Keep them under control.
     bool isOrthogonalChild(const RenderBox&) const;
-    LayoutUnit guttersSize(const Grid&, GridTrackSizingDirection, unsigned startLine, unsigned span, SizingOperation) const;
+    LayoutUnit guttersSize(const Grid&, GridTrackSizingDirection, unsigned startLine, unsigned span, std::optional<LayoutUnit> availableSize) const;
 
 protected:
     ItemPosition selfAlignmentNormalBehavior(const RenderBox* child = nullptr) const override
@@ -79,18 +79,20 @@ private:
     void addChild(RenderObject* newChild, RenderObject* beforeChild) final;
     void removeChild(RenderObject&) final;
 
+    std::optional<LayoutUnit> availableSpaceForGutters(GridTrackSizingDirection) const;
+
     bool explicitGridDidResize(const RenderStyle&) const;
     bool namedGridLinesDefinitionDidChange(const RenderStyle&) const;
 
     std::optional<LayoutUnit> computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, std::optional<LayoutUnit> intrinsicContentHeight, LayoutUnit borderAndPadding) const override;
 
-    unsigned computeAutoRepeatTracksCount(GridTrackSizingDirection, SizingOperation) const;
+    unsigned computeAutoRepeatTracksCount(GridTrackSizingDirection, std::optional<LayoutUnit> availableSize) const;
 
     unsigned clampAutoRepeatTracks(GridTrackSizingDirection, unsigned autoRepeatTracks) const;
 
     std::unique_ptr<OrderedTrackIndexSet> computeEmptyTracksForAutoRepeat(Grid&, GridTrackSizingDirection) const;
 
-    void placeItemsOnGrid(Grid&, SizingOperation) const;
+    void placeItemsOnGrid(Grid&, std::optional<LayoutUnit> availableSpaceForColumns) const;
     void populateExplicitGridAndOrderIterator(Grid&) const;
     std::unique_ptr<GridArea> createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(Grid&, const RenderBox&, GridTrackSizingDirection, const GridSpan&) const;
     void placeSpecifiedMajorAxisItemsOnGrid(Grid&, const Vector<RenderBox*>&) const;
@@ -149,7 +151,8 @@ private:
     std::optional<int> inlineBlockBaseline(LineDirectionMode) const final;
     bool isInlineBaselineAlignedChild(const RenderBox&) const;
 
-    LayoutUnit gridGapForDirection(GridTrackSizingDirection, SizingOperation) const;
+    LayoutUnit gridGap(GridTrackSizingDirection) const;
+    LayoutUnit gridGap(GridTrackSizingDirection, std::optional<LayoutUnit> availableSize) const;
 
     unsigned numTracks(GridTrackSizingDirection, const Grid&) const;