[css-grid] Remove compilation flag ENABLE_CSS_GRID_LAYOUT
[WebKit-https.git] / Source / WebCore / rendering / RenderGrid.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2013, 2014 Igalia S.L.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "RenderGrid.h"
29
30 #include "GridArea.h"
31 #include "GridPositionsResolver.h"
32 #include "LayoutRepainter.h"
33 #include "RenderLayer.h"
34 #include "RenderView.h"
35 #include <cstdlib>
36
37 namespace WebCore {
38
39 static const int infinity = -1;
40 static constexpr ItemPosition selfAlignmentNormalBehavior = ItemPositionStretch;
41
42 enum TrackSizeRestriction {
43     AllowInfinity,
44     ForbidInfinity,
45 };
46
47 class GridTrack {
48 public:
49     GridTrack() {}
50
51     const LayoutUnit& baseSize() const
52     {
53         ASSERT(isGrowthLimitBiggerThanBaseSize());
54         return m_baseSize;
55     }
56
57     const LayoutUnit& growthLimit() const
58     {
59         ASSERT(isGrowthLimitBiggerThanBaseSize());
60         ASSERT(!m_growthLimitCap || m_growthLimitCap.value() >= m_growthLimit || m_baseSize >= m_growthLimitCap.value());
61         return m_growthLimit;
62     }
63
64     void setBaseSize(LayoutUnit baseSize)
65     {
66         m_baseSize = baseSize;
67         ensureGrowthLimitIsBiggerThanBaseSize();
68     }
69
70     void setGrowthLimit(LayoutUnit growthLimit)
71     {
72         m_growthLimit = growthLimit == infinity ? growthLimit : std::min(growthLimit, m_growthLimitCap.value_or(growthLimit));
73         ensureGrowthLimitIsBiggerThanBaseSize();
74     }
75
76     bool infiniteGrowthPotential() const { return growthLimitIsInfinite() || m_infinitelyGrowable; }
77
78     const LayoutUnit& growthLimitIfNotInfinite() const
79     {
80         ASSERT(isGrowthLimitBiggerThanBaseSize());
81         return (m_growthLimit == infinity) ? m_baseSize : m_growthLimit;
82     }
83
84     const LayoutUnit& plannedSize() const { return m_plannedSize; }
85
86     void setPlannedSize(LayoutUnit plannedSize)
87     {
88         m_plannedSize = plannedSize;
89     }
90
91     const LayoutUnit& tempSize() const { return m_tempSize; }
92
93     void setTempSize(const LayoutUnit& tempSize)
94     {
95         ASSERT(tempSize >= 0);
96         ASSERT(growthLimitIsInfinite() || growthLimit() >= tempSize);
97         m_tempSize = tempSize;
98     }
99
100     void growTempSize(const LayoutUnit& tempSize)
101     {
102         ASSERT(tempSize >= 0);
103         m_tempSize += tempSize;
104     }
105
106     bool infinitelyGrowable() const { return m_infinitelyGrowable; }
107     void setInfinitelyGrowable(bool infinitelyGrowable) { m_infinitelyGrowable = infinitelyGrowable; }
108
109     void setGrowthLimitCap(std::optional<LayoutUnit> growthLimitCap)
110     {
111         ASSERT(!growthLimitCap || growthLimitCap.value() >= 0);
112         m_growthLimitCap = growthLimitCap;
113     }
114
115     std::optional<LayoutUnit> growthLimitCap() const { return m_growthLimitCap; }
116
117 private:
118     bool growthLimitIsInfinite() const { return m_growthLimit == infinity; }
119     bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite() || m_growthLimit >= m_baseSize; }
120
121     void ensureGrowthLimitIsBiggerThanBaseSize()
122     {
123         if (m_growthLimit != infinity && m_growthLimit < m_baseSize)
124             m_growthLimit = m_baseSize;
125     }
126
127     LayoutUnit m_baseSize { 0 };
128     LayoutUnit m_growthLimit { 0 };
129     LayoutUnit m_plannedSize { 0 };
130     LayoutUnit m_tempSize { 0 };
131     std::optional<LayoutUnit> m_growthLimitCap;
132     bool m_infinitelyGrowable { false };
133 };
134
135 struct ContentAlignmentData {
136     WTF_MAKE_FAST_ALLOCATED;
137 public:
138     bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; }
139     static ContentAlignmentData defaultOffsets() { return {-1, -1}; }
140
141     LayoutUnit positionOffset;
142     LayoutUnit distributionOffset;
143 };
144
145 class RenderGrid::GridSizingData {
146     WTF_MAKE_NONCOPYABLE(GridSizingData);
147 public:
148     GridSizingData(unsigned gridColumnCount, unsigned gridRowCount, Grid& grid)
149         : columnTracks(gridColumnCount)
150         , rowTracks(gridRowCount)
151         , m_grid(grid)
152     {
153     }
154
155     Vector<GridTrack> columnTracks;
156     Vector<GridTrack> rowTracks;
157     Vector<unsigned> contentSizedTracksIndex;
158
159     // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free.
160     Vector<GridTrack*> filteredTracks;
161     Vector<GridTrack*> growBeyondGrowthLimitsTracks;
162     Vector<GridItemWithSpan> itemsSortedByIncreasingSpan;
163
164     std::optional<LayoutUnit> freeSpace(GridTrackSizingDirection direction) { return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; }
165     void setFreeSpace(GridTrackSizingDirection, std::optional<LayoutUnit> freeSpace);
166
167     std::optional<LayoutUnit> availableSpace() const { return m_availableSpace; }
168     void setAvailableSpace(std::optional<LayoutUnit> availableSpace) { m_availableSpace = availableSpace; }
169
170     SizingOperation sizingOperation { TrackSizing };
171
172     enum SizingState { ColumnSizingFirstIteration, RowSizingFirstIteration, ColumnSizingSecondIteration, RowSizingSecondIteration};
173     SizingState sizingState { ColumnSizingFirstIteration };
174     void advanceNextState()
175     {
176         switch (sizingState) {
177         case ColumnSizingFirstIteration:
178             sizingState = RowSizingFirstIteration;
179             return;
180         case RowSizingFirstIteration:
181             sizingState = ColumnSizingSecondIteration;
182             return;
183         case ColumnSizingSecondIteration:
184             sizingState = RowSizingSecondIteration;
185             return;
186         case RowSizingSecondIteration:
187             sizingState = ColumnSizingFirstIteration;
188             return;
189         }
190         ASSERT_NOT_REACHED();
191         sizingState = ColumnSizingFirstIteration;
192     }
193     bool isValidTransition(GridTrackSizingDirection direction) const
194     {
195         switch (sizingState) {
196         case ColumnSizingFirstIteration:
197         case ColumnSizingSecondIteration:
198             return direction == ForColumns;
199         case RowSizingFirstIteration:
200         case RowSizingSecondIteration:
201             return direction == ForRows;
202         }
203         ASSERT_NOT_REACHED();
204         return false;
205     }
206
207     Grid& grid() const { return m_grid; }
208
209 private:
210     std::optional<LayoutUnit> freeSpaceForColumns;
211     std::optional<LayoutUnit> freeSpaceForRows;
212     // No need to store one per direction as it will be only used for computations during each axis
213     // track sizing. It's cached here because we need it to compute relative sizes.
214     std::optional<LayoutUnit> m_availableSpace;
215
216     Grid& m_grid;
217 };
218
219 void RenderGrid::GridSizingData::setFreeSpace(GridTrackSizingDirection direction, std::optional<LayoutUnit> freeSpace)
220 {
221     if (direction == ForColumns)
222         freeSpaceForColumns = freeSpace;
223     else
224         freeSpaceForRows = freeSpace;
225 }
226
227 RenderGrid::RenderGrid(Element& element, RenderStyle&& style)
228     : RenderBlock(element, WTFMove(style), 0)
229     , m_grid(*this)
230 {
231     // All of our children must be block level.
232     setChildrenInline(false);
233 }
234
235 RenderGrid::~RenderGrid()
236 {
237 }
238
239 static inline bool defaultAlignmentIsStretch(ItemPosition position)
240 {
241     return position == ItemPositionStretch || position == ItemPositionAuto;
242 }
243
244 static inline bool defaultAlignmentChangedToStretchInRowAxis(const RenderStyle& oldStyle, const RenderStyle& newStyle)
245 {
246     return !defaultAlignmentIsStretch(oldStyle.justifyItems().position()) && defaultAlignmentIsStretch(newStyle.justifyItems().position());
247 }
248
249 static inline bool defaultAlignmentChangedFromStretchInRowAxis(const RenderStyle& oldStyle, const RenderStyle& newStyle)
250 {
251     return defaultAlignmentIsStretch(oldStyle.justifyItems().position()) && !defaultAlignmentIsStretch(newStyle.justifyItems().position());
252 }
253
254 static inline bool defaultAlignmentChangedFromStretchInColumnAxis(const RenderStyle& oldStyle, const RenderStyle& newStyle)
255 {
256     return defaultAlignmentIsStretch(oldStyle.alignItems().position()) && !defaultAlignmentIsStretch(newStyle.alignItems().position());
257 }
258
259 static inline bool selfAlignmentChangedToStretchInRowAxis(const RenderStyle& oldStyle, const RenderStyle& newStyle, const RenderStyle& childStyle)
260 {
261     return childStyle.resolvedJustifySelf(oldStyle, selfAlignmentNormalBehavior).position() != ItemPositionStretch
262         && childStyle.resolvedJustifySelf(newStyle, selfAlignmentNormalBehavior).position() == ItemPositionStretch;
263 }
264
265 static inline bool selfAlignmentChangedFromStretchInRowAxis(const RenderStyle& oldStyle, const RenderStyle& newStyle, const RenderStyle& childStyle)
266 {
267     return childStyle.resolvedJustifySelf(oldStyle, selfAlignmentNormalBehavior).position() == ItemPositionStretch
268         && childStyle.resolvedJustifySelf(newStyle, selfAlignmentNormalBehavior).position() != ItemPositionStretch;
269 }
270
271 static inline bool selfAlignmentChangedFromStretchInColumnAxis(const RenderStyle& oldStyle, const RenderStyle& newStyle, const RenderStyle& childStyle)
272 {
273     return childStyle.resolvedAlignSelf(oldStyle, selfAlignmentNormalBehavior).position() == ItemPositionStretch
274         && childStyle.resolvedAlignSelf(newStyle, selfAlignmentNormalBehavior).position() != ItemPositionStretch;
275 }
276
277 void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
278 {
279     RenderBlock::addChild(newChild, beforeChild);
280
281     // The grid needs to be recomputed as it might contain auto-placed items that
282     // will change their position.
283     dirtyGrid();
284 }
285
286 void RenderGrid::removeChild(RenderObject& child)
287 {
288     RenderBlock::removeChild(child);
289
290     // The grid needs to be recomputed as it might contain auto-placed items that
291     // will change their position.
292     dirtyGrid();
293 }
294
295 void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
296 {
297     RenderBlock::styleDidChange(diff, oldStyle);
298     if (!oldStyle || diff != StyleDifferenceLayout)
299         return;
300
301     const RenderStyle& newStyle = style();
302     if (defaultAlignmentChangedToStretchInRowAxis(*oldStyle, newStyle) || defaultAlignmentChangedFromStretchInRowAxis(*oldStyle, newStyle)
303         || defaultAlignmentChangedFromStretchInColumnAxis(*oldStyle, newStyle)) {
304         // Grid items that were not previously stretched in row-axis need to be relayed out so we can compute new available space.
305         // Grid items that were previously stretching in column-axis need to be relayed out so we can compute new available space.
306         // This is only necessary for stretching since other alignment values don't change the size of the box.
307         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
308             if (child->isOutOfFlowPositioned())
309                 continue;
310             if (selfAlignmentChangedToStretchInRowAxis(*oldStyle, newStyle, child->style()) || selfAlignmentChangedFromStretchInRowAxis(*oldStyle, newStyle, child->style())
311                 || selfAlignmentChangedFromStretchInColumnAxis(*oldStyle, newStyle, child->style())) {
312                 child->setChildNeedsLayout(MarkOnlyThis);
313             }
314         }
315     }
316
317     if (explicitGridDidResize(*oldStyle) || namedGridLinesDefinitionDidChange(*oldStyle) || oldStyle->gridAutoFlow() != style().gridAutoFlow()
318         || (style().gridAutoRepeatColumns().size() || style().gridAutoRepeatRows().size()))
319         dirtyGrid();
320 }
321
322 bool RenderGrid::explicitGridDidResize(const RenderStyle& oldStyle) const
323 {
324     return oldStyle.gridColumns().size() != style().gridColumns().size()
325         || oldStyle.gridRows().size() != style().gridRows().size()
326         || oldStyle.namedGridAreaColumnCount() != style().namedGridAreaColumnCount()
327         || oldStyle.namedGridAreaRowCount() != style().namedGridAreaRowCount()
328         || oldStyle.gridAutoRepeatColumns().size() != style().gridAutoRepeatColumns().size()
329         || oldStyle.gridAutoRepeatRows().size() != style().gridAutoRepeatRows().size();
330 }
331
332 bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle& oldStyle) const
333 {
334     return oldStyle.namedGridRowLines() != style().namedGridRowLines()
335         || oldStyle.namedGridColumnLines() != style().namedGridColumnLines();
336 }
337
338 LayoutUnit RenderGrid::computeTrackBasedLogicalHeight(const GridSizingData& sizingData) const
339 {
340     LayoutUnit logicalHeight;
341
342     for (const auto& row : sizingData.rowTracks)
343         logicalHeight += row.baseSize();
344
345     logicalHeight += guttersSize(sizingData.grid(), ForRows, 0, sizingData.rowTracks.size());
346
347     return logicalHeight;
348 }
349
350 void RenderGrid::computeTrackSizesForDirection(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit availableSpace)
351 {
352     ASSERT(sizingData.isValidTransition(direction));
353     LayoutUnit totalGuttersSize = guttersSize(sizingData.grid(), direction, 0, m_grid.numTracks(direction));
354     sizingData.setAvailableSpace(availableSpace);
355     sizingData.setFreeSpace(direction, availableSpace - totalGuttersSize);
356     sizingData.sizingOperation = TrackSizing;
357
358     LayoutUnit baseSizes, growthLimits;
359     computeUsedBreadthOfGridTracks(direction, sizingData, baseSizes, growthLimits);
360     ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData));
361     sizingData.advanceNextState();
362 }
363
364 void RenderGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows)
365 {
366     ASSERT(!sizingData.grid().needsItemsPlacement());
367     ASSERT(sizingData.sizingState > GridSizingData::RowSizingFirstIteration);
368
369     // In orthogonal flow cases column track's size is determined by using the computed
370     // row track's size, which it was estimated during the first cycle of the sizing
371     // algorithm. Hence we need to repeat computeUsedBreadthOfGridTracks for both,
372     // columns and rows, to determine the final values.
373     // TODO (lajava): orthogonal flows is just one of the cases which may require
374     // a new cycle of the sizing algorithm; there may be more. In addition, not all the
375     // cases with orthogonal flows require this extra cycle; we need a more specific
376     // condition to detect whether child's min-content contribution has changed or not.
377     if (sizingData.grid().hasAnyOrthogonalGridItem()) {
378         computeTrackSizesForDirection(ForColumns, sizingData, availableSpaceForColumns);
379         computeTrackSizesForDirection(ForRows, sizingData, availableSpaceForRows);
380     }
381 }
382
383 bool RenderGrid::canPerformSimplifiedLayout() const
384 {
385     // We cannot perform a simplified layout if we need to position the items and we have some
386     // positioned items to be laid out.
387     if (m_grid.needsItemsPlacement() && posChildNeedsLayout())
388         return false;
389
390     return RenderBlock::canPerformSimplifiedLayout();
391 }
392
393 void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
394 {
395     ASSERT(needsLayout());
396
397     if (!relayoutChildren && simplifiedLayout())
398         return;
399
400     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
401     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
402
403     preparePaginationBeforeBlockLayout(relayoutChildren);
404
405     LayoutSize previousSize = size();
406
407     // We need to clear both own and containingBlock override sizes of orthogonal items to ensure we get the
408     // same result when grid's intrinsic size is computed again in the updateLogicalWidth call bellow.
409     if (sizesLogicalWidthToFitContent(MaxSize) || style().logicalWidth().isIntrinsicOrAuto()) {
410         for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
411             if (child->isOutOfFlowPositioned() || !isOrthogonalChild(*child))
412                 continue;
413             child->clearOverrideSize();
414             child->clearContainingBlockOverrideSize();
415             child->setNeedsLayout();
416             child->layoutIfNeeded();
417         }
418     }
419
420     setLogicalHeight(0);
421     updateLogicalWidth();
422
423     placeItemsOnGrid(m_grid, TrackSizing);
424
425     GridSizingData sizingData(numTracks(ForColumns, m_grid), numTracks(ForRows, m_grid), m_grid);
426
427     // At this point the logical width is always definite as the above call to updateLogicalWidth()
428     // properly resolves intrinsic sizes. We cannot do the same for heights though because many code
429     // paths inside updateLogicalHeight() require a previous call to setLogicalHeight() to resolve
430     // heights properly (like for positioned items for example).
431     LayoutUnit availableSpaceForColumns = availableLogicalWidth();
432     computeTrackSizesForDirection(ForColumns, sizingData, availableSpaceForColumns);
433
434     // FIXME: We should use RenderBlock::hasDefiniteLogicalHeight() but it does not work for positioned stuff.
435     // FIXME: Consider caching the hasDefiniteLogicalHeight value throughout the layout.
436     bool hasDefiniteLogicalHeight = hasOverrideLogicalContentHeight() || computeContentLogicalHeight(MainOrPreferredSize, style().logicalHeight(), std::nullopt);
437     if (!hasDefiniteLogicalHeight)
438         computeIntrinsicLogicalHeight(sizingData);
439     else
440         computeTrackSizesForDirection(ForRows, sizingData, availableLogicalHeight(ExcludeMarginBorderPadding));
441     LayoutUnit trackBasedLogicalHeight = computeTrackBasedLogicalHeight(sizingData) + borderAndPaddingLogicalHeight() + scrollbarLogicalHeight();
442     setLogicalHeight(trackBasedLogicalHeight);
443
444     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
445     updateLogicalHeight();
446
447     // Once grid's indefinite height is resolved, we can compute the
448     // available free space for Content Alignment.
449     if (!hasDefiniteLogicalHeight)
450         sizingData.setFreeSpace(ForRows, logicalHeight() - trackBasedLogicalHeight);
451
452     // 3- If the min-content contribution of any grid items have changed based on the row
453     // sizes calculated in step 2, steps 1 and 2 are repeated with the new min-content
454     // contribution (once only).
455     repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, contentLogicalHeight());
456
457     // Grid container should have the minimum height of a line if it's editable. That does not affect track sizing though.
458     if (hasLineIfEmpty()) {
459         LayoutUnit minHeightForEmptyLine = borderAndPaddingLogicalHeight()
460             + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)
461             + scrollbarLogicalHeight();
462         setLogicalHeight(std::max(logicalHeight(), minHeightForEmptyLine));
463     }
464
465     applyStretchAlignmentToTracksIfNeeded(ForColumns, sizingData);
466     applyStretchAlignmentToTracksIfNeeded(ForRows, sizingData);
467
468     layoutGridItems(sizingData);
469
470     if (size() != previousSize)
471         relayoutChildren = true;
472
473     layoutPositionedObjects(relayoutChildren || isDocumentElementRenderer());
474
475     computeOverflow(oldClientAfterEdge);
476     statePusher.pop();
477
478     updateLayerTransform();
479
480     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
481     // we overflow or not.
482     updateScrollInfoAfterLayout();
483
484     repainter.repaintAfterLayout();
485
486     clearNeedsLayout();
487 }
488
489 LayoutUnit RenderGrid::gridGapForDirection(GridTrackSizingDirection direction) const
490 {
491     return valueForLength(direction == ForColumns ? style().gridColumnGap() : style().gridRowGap(), LayoutUnit());
492 }
493
494 LayoutUnit RenderGrid::guttersSize(const Grid& grid, GridTrackSizingDirection direction, unsigned startLine, unsigned span) const
495 {
496     if (span <= 1)
497         return { };
498
499     LayoutUnit gap = gridGapForDirection(direction);
500
501     // Fast path, no collapsing tracks.
502     if (!grid.hasAutoRepeatEmptyTracks(direction))
503         return gap * (span - 1);
504
505     // If there are collapsing tracks we need to be sure that gutters are properly collapsed. Apart
506     // from that, if we have a collapsed track in the edges of the span we're considering, we need
507     // to move forward (or backwards) in order to know whether the collapsed tracks reach the end of
508     // the grid (so the gap becomes 0) or there is a non empty track before that.
509
510     LayoutUnit gapAccumulator;
511     unsigned endLine = startLine + span;
512
513     for (unsigned line = startLine; line < endLine - 1; ++line) {
514         if (!grid.isEmptyAutoRepeatTrack(direction, line))
515             gapAccumulator += gap;
516     }
517
518     // The above loop adds one extra gap for trailing collapsed tracks.
519     if (gapAccumulator && grid.isEmptyAutoRepeatTrack(direction, endLine - 1)) {
520         ASSERT(gapAccumulator >= gap);
521         gapAccumulator -= gap;
522     }
523
524     // If the startLine is the start line of a collapsed track we need to go backwards till we reach
525     // a non collapsed track. If we find a non collapsed track we need to add that gap.
526     if (startLine && grid.isEmptyAutoRepeatTrack(direction, startLine)) {
527         unsigned nonEmptyTracksBeforeStartLine = startLine;
528         auto begin = grid.autoRepeatEmptyTracks(direction)->begin();
529         for (auto it = begin; *it != startLine; ++it) {
530             ASSERT(nonEmptyTracksBeforeStartLine);
531             --nonEmptyTracksBeforeStartLine;
532         }
533         if (nonEmptyTracksBeforeStartLine)
534             gapAccumulator += gap;
535     }
536
537     // If the endLine is the end line of a collapsed track we need to go forward till we reach a non
538     // collapsed track. If we find a non collapsed track we need to add that gap.
539     if (grid.isEmptyAutoRepeatTrack(direction, endLine - 1)) {
540         unsigned nonEmptyTracksAfterEndLine = grid.numTracks(direction) - endLine;
541         auto currentEmptyTrack = grid.autoRepeatEmptyTracks(direction)->find(endLine - 1);
542         auto endEmptyTrack = grid.autoRepeatEmptyTracks(direction)->end();
543         // HashSet iterators do not implement operator- so we have to manually iterate to know the number of remaining empty tracks.
544         for (auto it = ++currentEmptyTrack; it != endEmptyTrack; ++it) {
545             ASSERT(nonEmptyTracksAfterEndLine >= 1);
546             --nonEmptyTracksAfterEndLine;
547         }
548         if (nonEmptyTracksAfterEndLine)
549             gapAccumulator += gap;
550     }
551
552     return gapAccumulator;
553 }
554
555 void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
556 {
557     Grid grid(const_cast<RenderGrid&>(*this));
558     placeItemsOnGrid(grid, IntrinsicSizeComputation);
559
560     GridSizingData sizingData(numTracks(ForColumns, grid), numTracks(ForRows, grid), grid);
561     sizingData.setAvailableSpace(std::nullopt);
562     sizingData.setFreeSpace(ForColumns, std::nullopt);
563     sizingData.sizingOperation = IntrinsicSizeComputation;
564     computeUsedBreadthOfGridTracks(ForColumns, sizingData, minLogicalWidth, maxLogicalWidth);
565
566     LayoutUnit totalGuttersSize = guttersSize(sizingData.grid(), ForColumns, 0, sizingData.columnTracks.size());
567     minLogicalWidth += totalGuttersSize;
568     maxLogicalWidth += totalGuttersSize;
569
570     LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth();
571     minLogicalWidth += scrollbarWidth;
572     maxLogicalWidth += scrollbarWidth;
573 }
574
575 void RenderGrid::computeIntrinsicLogicalHeight(GridSizingData& sizingData)
576 {
577     ASSERT(sizingData.isValidTransition(ForRows));
578     sizingData.setAvailableSpace(std::nullopt);
579     sizingData.setFreeSpace(ForRows, std::nullopt);
580     sizingData.sizingOperation = IntrinsicSizeComputation;
581     LayoutUnit minHeight, maxHeight;
582     computeUsedBreadthOfGridTracks(ForRows, sizingData, minHeight, maxHeight);
583
584     // FIXME: This should be really added to the intrinsic height in RenderBox::computeContentAndScrollbarLogicalHeightUsing().
585     // Remove this when that is fixed.
586     LayoutUnit scrollbarHeight = scrollbarLogicalHeight();
587     minHeight += scrollbarHeight;
588     maxHeight += scrollbarHeight;
589
590     LayoutUnit totalGuttersSize = guttersSize(sizingData.grid(), ForRows, 0, m_grid.numTracks(ForRows));
591     minHeight += totalGuttersSize;
592     maxHeight += totalGuttersSize;
593
594     m_minContentHeight = minHeight;
595     m_maxContentHeight = maxHeight;
596
597     ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData));
598     sizingData.advanceNextState();
599     sizingData.sizingOperation = TrackSizing;
600 }
601
602 std::optional<LayoutUnit> RenderGrid::computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, std::optional<LayoutUnit> intrinsicLogicalHeight, LayoutUnit borderAndPadding) const
603 {
604     if (!intrinsicLogicalHeight)
605         return std::nullopt;
606
607     if (logicalHeightLength.isMinContent())
608         return m_minContentHeight;
609
610     if (logicalHeightLength.isMaxContent())
611         return m_maxContentHeight;
612
613     if (logicalHeightLength.isFitContent()) {
614         LayoutUnit fillAvailableExtent = containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding);
615         return std::min(m_maxContentHeight.value_or(0), std::max(m_minContentHeight.value_or(0), fillAvailableExtent));
616     }
617
618     if (logicalHeightLength.isFillAvailable())
619         return containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding) - borderAndPadding;
620     ASSERT_NOT_REACHED();
621     return std::nullopt;
622 }
623
624 static inline double normalizedFlexFraction(const GridTrack& track, double flexFactor)
625 {
626     return track.baseSize() / std::max<double>(1, flexFactor);
627 }
628
629 void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization) const
630 {
631     const std::optional<LayoutUnit> initialFreeSpace = sizingData.freeSpace(direction);
632     Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
633     Vector<unsigned> flexibleSizedTracksIndex;
634     sizingData.contentSizedTracksIndex.shrink(0);
635
636     // Grid gutters were removed from freeSpace by the caller (if freeSpace is definite),
637     // but we must use them to compute relative (i.e. percentages) sizes.
638     LayoutUnit maxSize = std::max(LayoutUnit(), sizingData.availableSpace().value_or(LayoutUnit()));
639     const bool hasDefiniteFreeSpace = sizingData.sizingOperation == TrackSizing;
640
641     // 1. Initialize per Grid track variables.
642     for (unsigned i = 0; i < tracks.size(); ++i) {
643         GridTrack& track = tracks[i];
644         const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData);
645
646         track.setBaseSize(computeUsedBreadthOfMinLength(trackSize, maxSize));
647         track.setGrowthLimit(computeUsedBreadthOfMaxLength(trackSize, track.baseSize(), maxSize));
648         track.setInfinitelyGrowable(false);
649
650         if (trackSize.isFitContent()) {
651             GridLength gridLength = trackSize.fitContentTrackBreadth();
652             if (!gridLength.isPercentage() || hasDefiniteFreeSpace)
653                 track.setGrowthLimitCap(valueForLength(gridLength.length(), maxSize));
654         }
655         if (trackSize.isContentSized())
656             sizingData.contentSizedTracksIndex.append(i);
657         if (trackSize.maxTrackBreadth().isFlex())
658             flexibleSizedTracksIndex.append(i);
659     }
660
661     // 2. Resolve content-based TrackSizingFunctions.
662     if (!sizingData.contentSizedTracksIndex.isEmpty())
663         resolveContentBasedTrackSizingFunctions(direction, sizingData);
664
665     baseSizesWithoutMaximization = growthLimitsWithoutMaximization = 0;
666
667     for (auto& track : tracks) {
668         ASSERT(!track.infiniteGrowthPotential());
669         baseSizesWithoutMaximization += track.baseSize();
670         growthLimitsWithoutMaximization += track.growthLimit();
671         // The growth limit caps must be cleared now in order to properly sort tracks by growth
672         // potential on an eventual "Maximize Tracks".
673         track.setGrowthLimitCap(std::nullopt);
674     }
675     LayoutUnit freeSpace = initialFreeSpace ? initialFreeSpace.value() - baseSizesWithoutMaximization : LayoutUnit(0);
676
677     if (hasDefiniteFreeSpace && freeSpace <= 0) {
678         sizingData.setFreeSpace(direction, freeSpace);
679         return;
680     }
681
682     // 3. Grow all Grid tracks in GridTracks from their UsedBreadth up to their MaxBreadth value until freeSpace is exhausted.
683     if (hasDefiniteFreeSpace) {
684         const unsigned tracksSize = tracks.size();
685         Vector<GridTrack*> tracksForDistribution(tracksSize);
686         for (unsigned i = 0; i < tracksSize; ++i) {
687             tracksForDistribution[i] = tracks.data() + i;
688             tracksForDistribution[i]->setPlannedSize(tracksForDistribution[i]->baseSize());
689         }
690
691         distributeSpaceToTracks<MaximizeTracks>(tracksForDistribution, nullptr, freeSpace);
692
693         for (auto* track : tracksForDistribution)
694             track->setBaseSize(track->plannedSize());
695     } else {
696         for (auto& track : tracks)
697             track.setBaseSize(track.growthLimit());
698     }
699
700     if (flexibleSizedTracksIndex.isEmpty()) {
701         sizingData.setFreeSpace(direction, freeSpace);
702         return;
703     }
704
705     // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
706     double flexFraction = 0;
707     if (hasDefiniteFreeSpace)
708         flexFraction = findFlexFactorUnitSize(tracks, GridSpan::translatedDefiniteGridSpan(0, tracks.size()), direction, initialFreeSpace.value(), sizingData);
709     else {
710         for (const auto& trackIndex : flexibleSizedTracksIndex)
711             flexFraction = std::max(flexFraction, normalizedFlexFraction(tracks[trackIndex], gridTrackSize(direction, trackIndex, sizingData).maxTrackBreadth().flex()));
712
713         Grid& grid = sizingData.grid();
714         if (grid.hasGridItems()) {
715             for (unsigned i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
716                 GridIterator iterator(grid, direction, flexibleSizedTracksIndex[i]);
717                 while (auto* gridItem = iterator.nextGridItem()) {
718                     const GridSpan& span = grid.gridItemSpan(*gridItem, direction);
719
720                     // Do not include already processed items.
721                     if (i > 0 && span.startLine() <= flexibleSizedTracksIndex[i - 1])
722                         continue;
723
724                     flexFraction = std::max(flexFraction, findFlexFactorUnitSize(tracks, span, direction, maxContentForChild(*gridItem, direction, sizingData), sizingData));
725                 }
726             }
727         }
728     }
729     LayoutUnit totalGrowth;
730     Vector<LayoutUnit> increments;
731     increments.grow(flexibleSizedTracksIndex.size());
732     computeFlexSizedTracksGrowth(direction, sizingData, tracks, flexibleSizedTracksIndex, flexFraction, increments, totalGrowth);
733
734     // We only need to redo the flex fraction computation for indefinite heights (definite sizes are
735     // already constrained by min/max sizes). Regarding widths, they are always definite at layout
736     // time so we shouldn't ever have to do this.
737     if (!hasDefiniteFreeSpace && direction == ForRows) {
738         auto minSize = computeContentLogicalHeight(MinSize, style().logicalMinHeight(), LayoutUnit(-1));
739         auto maxSize = computeContentLogicalHeight(MaxSize, style().logicalMaxHeight(), LayoutUnit(-1));
740
741         // Redo the flex fraction computation using min|max-height as definite available space in
742         // case the total height is smaller than min-height or larger than max-height.
743         LayoutUnit rowsSize = totalGrowth + computeTrackBasedLogicalHeight(sizingData);
744         bool checkMinSize = minSize && rowsSize < minSize.value();
745         bool checkMaxSize = maxSize && rowsSize > maxSize.value();
746         if (checkMinSize || checkMaxSize) {
747             LayoutUnit constrainedFreeSpace = checkMaxSize ? maxSize.value() : LayoutUnit(-1);
748             constrainedFreeSpace = std::max(constrainedFreeSpace, minSize.value()) - guttersSize(sizingData.grid(), ForRows, 0, sizingData.grid().numTracks(ForRows));
749             flexFraction = findFlexFactorUnitSize(tracks, GridSpan::translatedDefiniteGridSpan(0, tracks.size()), ForRows, constrainedFreeSpace, sizingData);
750
751             totalGrowth = LayoutUnit(0);
752             computeFlexSizedTracksGrowth(ForRows, sizingData, tracks, flexibleSizedTracksIndex, flexFraction, increments, totalGrowth);
753         }
754     }
755
756     for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
757         if (LayoutUnit increment = increments[i]) {
758             auto& track = tracks[flexibleSizedTracksIndex[i]];
759             track.setBaseSize(track.baseSize() + increment);
760         }
761     }
762     freeSpace -= totalGrowth;
763     growthLimitsWithoutMaximization += totalGrowth;
764     sizingData.setFreeSpace(direction, freeSpace);
765 }
766
767 void RenderGrid::computeFlexSizedTracksGrowth(GridTrackSizingDirection direction, const GridSizingData& sizingData, Vector<GridTrack>& tracks, const Vector<unsigned>& flexibleSizedTracksIndex, double flexFraction, Vector<LayoutUnit>& increments, LayoutUnit& totalGrowth) const
768 {
769     size_t numFlexTracks = flexibleSizedTracksIndex.size();
770     ASSERT(increments.size() == numFlexTracks);
771     for (size_t i = 0; i < numFlexTracks; ++i) {
772         unsigned trackIndex = flexibleSizedTracksIndex[i];
773         auto trackSize = gridTrackSize(direction, trackIndex, sizingData);
774         ASSERT(trackSize.maxTrackBreadth().isFlex());
775         LayoutUnit oldBaseSize = tracks[trackIndex].baseSize();
776         LayoutUnit newBaseSize = std::max(oldBaseSize, LayoutUnit(flexFraction * trackSize.maxTrackBreadth().flex()));
777         increments[i] = newBaseSize - oldBaseSize;
778         totalGrowth += increments[i];
779     }
780 }
781
782 LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(const GridTrackSize& trackSize, LayoutUnit maxSize) const
783 {
784     const GridLength& gridLength = trackSize.minTrackBreadth();
785     if (gridLength.isFlex())
786         return 0;
787
788     const Length& trackLength = gridLength.length();
789     if (trackLength.isSpecified())
790         return valueForLength(trackLength, maxSize);
791
792     ASSERT(trackLength.isMinContent() || trackLength.isAuto() || trackLength.isMaxContent());
793     return 0;
794 }
795
796 LayoutUnit RenderGrid::computeUsedBreadthOfMaxLength(const GridTrackSize& trackSize, LayoutUnit usedBreadth, LayoutUnit maxSize) const
797 {
798     const GridLength& gridLength = trackSize.maxTrackBreadth();
799     if (gridLength.isFlex())
800         return usedBreadth;
801
802     const Length& trackLength = gridLength.length();
803     if (trackLength.isSpecified())
804         return valueForLength(trackLength, maxSize);
805
806     ASSERT(trackLength.isMinContent() || trackLength.isAuto() || trackLength.isMaxContent());
807     return infinity;
808 }
809
810 double RenderGrid::computeFlexFactorUnitSize(const Vector<GridTrack>& tracks, GridTrackSizingDirection direction, const GridSizingData& sizingData, double flexFactorSum, LayoutUnit leftOverSpace, const Vector<unsigned, 8>& flexibleTracksIndexes, std::unique_ptr<TrackIndexSet> tracksToTreatAsInflexible) const
811 {
812     // We want to avoid the effect of flex factors sum below 1 making the factor unit size to grow exponentially.
813     double hypotheticalFactorUnitSize = leftOverSpace / std::max<double>(1, flexFactorSum);
814
815     // product of the hypothetical "flex factor unit" and any flexible track's "flex factor" must be grater than such track's "base size".
816     bool validFlexFactorUnit = true;
817     for (auto index : flexibleTracksIndexes) {
818         if (tracksToTreatAsInflexible && tracksToTreatAsInflexible->contains(index))
819             continue;
820         LayoutUnit baseSize = tracks[index].baseSize();
821         double flexFactor = gridTrackSize(direction, index, sizingData).maxTrackBreadth().flex();
822         // treating all such tracks as inflexible.
823         if (baseSize > hypotheticalFactorUnitSize * flexFactor) {
824             leftOverSpace -= baseSize;
825             flexFactorSum -= flexFactor;
826             if (!tracksToTreatAsInflexible)
827                 tracksToTreatAsInflexible = std::unique_ptr<TrackIndexSet>(new TrackIndexSet());
828             tracksToTreatAsInflexible->add(index);
829             validFlexFactorUnit = false;
830         }
831     }
832     if (!validFlexFactorUnit)
833         return computeFlexFactorUnitSize(tracks, direction, sizingData, flexFactorSum, leftOverSpace, flexibleTracksIndexes, WTFMove(tracksToTreatAsInflexible));
834     return hypotheticalFactorUnitSize;
835 }
836
837 double RenderGrid::findFlexFactorUnitSize(const Vector<GridTrack>& tracks, const GridSpan& tracksSpan, GridTrackSizingDirection direction, LayoutUnit leftOverSpace, const GridSizingData& sizingData) const
838 {
839     if (leftOverSpace <= 0)
840         return 0;
841
842     double flexFactorSum = 0;
843     Vector<unsigned, 8> flexibleTracksIndexes;
844     for (auto trackIndex : tracksSpan) {
845         GridTrackSize trackSize = gridTrackSize(direction, trackIndex, sizingData);
846         if (!trackSize.maxTrackBreadth().isFlex())
847             leftOverSpace -= tracks[trackIndex].baseSize();
848         else {
849             double flexFactor = trackSize.maxTrackBreadth().flex();
850             flexibleTracksIndexes.append(trackIndex);
851             flexFactorSum += flexFactor;
852         }
853     }
854
855     // The function is not called if we don't have <flex> grid tracks
856     ASSERT(!flexibleTracksIndexes.isEmpty());
857
858     return computeFlexFactorUnitSize(tracks, direction, sizingData, flexFactorSum, leftOverSpace, flexibleTracksIndexes);
859 }
860
861 static bool hasOverrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
862 {
863     return direction == ForColumns ? child.hasOverrideContainingBlockLogicalWidth() : child.hasOverrideContainingBlockLogicalHeight();
864 }
865
866 static std::optional<LayoutUnit> overrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
867 {
868     return direction == ForColumns ? child.overrideContainingBlockContentLogicalWidth() : child.overrideContainingBlockContentLogicalHeight();
869 }
870
871 static void setOverrideContainingBlockContentSizeForChild(RenderBox& child, GridTrackSizingDirection direction, std::optional<LayoutUnit> size)
872 {
873     if (direction == ForColumns)
874         child.setOverrideContainingBlockContentLogicalWidth(size);
875     else
876         child.setOverrideContainingBlockContentLogicalHeight(size);
877 }
878
879 static bool shouldClearOverrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
880 {
881     if (direction == ForColumns)
882         return child.hasRelativeLogicalWidth() || child.style().logicalWidth().isIntrinsicOrAuto();
883     return child.hasRelativeLogicalHeight() || child.style().logicalHeight().isIntrinsicOrAuto();
884 }
885
886 const GridTrackSize& RenderGrid::rawGridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex, const GridSizingData& sizingData) const
887 {
888     bool isRowAxis = direction == ForColumns;
889     auto& trackStyles = isRowAxis ? style().gridColumns() : style().gridRows();
890     auto& autoRepeatTrackStyles = isRowAxis ? style().gridAutoRepeatColumns() : style().gridAutoRepeatRows();
891     auto& autoTrackStyles = isRowAxis ? style().gridAutoColumns() : style().gridAutoRows();
892     unsigned insertionPoint = isRowAxis ? style().gridAutoRepeatColumnsInsertionPoint() : style().gridAutoRepeatRowsInsertionPoint();
893     unsigned autoRepeatTracksCount = sizingData.grid().autoRepeatTracks(direction);
894
895     // We should not use GridPositionsResolver::explicitGridXXXCount() for this because the
896     // explicit grid might be larger than the number of tracks in grid-template-rows|columns (if
897     // grid-template-areas is specified for example).
898     unsigned explicitTracksCount = trackStyles.size() + autoRepeatTracksCount;
899
900     int untranslatedIndexAsInt = translatedIndex + sizingData.grid().smallestTrackStart(direction);
901     unsigned autoTrackStylesSize = autoTrackStyles.size();
902     if (untranslatedIndexAsInt < 0) {
903         int index = untranslatedIndexAsInt % static_cast<int>(autoTrackStylesSize);
904         // We need to traspose the index because the first negative implicit line will get the last defined auto track and so on.
905         index += index ? autoTrackStylesSize : 0;
906         return autoTrackStyles[index];
907     }
908
909     unsigned untranslatedIndex = static_cast<unsigned>(untranslatedIndexAsInt);
910     if (untranslatedIndex >= explicitTracksCount)
911         return autoTrackStyles[(untranslatedIndex - explicitTracksCount) % autoTrackStylesSize];
912
913     if (!autoRepeatTracksCount || untranslatedIndex < insertionPoint)
914         return trackStyles[untranslatedIndex];
915
916     if (untranslatedIndex < (insertionPoint + autoRepeatTracksCount)) {
917         unsigned autoRepeatLocalIndex = untranslatedIndexAsInt - insertionPoint;
918         return autoRepeatTrackStyles[autoRepeatLocalIndex % autoRepeatTrackStyles.size()];
919     }
920
921     return trackStyles[untranslatedIndex - autoRepeatTracksCount];
922 }
923
924 GridTrackSize RenderGrid::gridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex, const GridSizingData& sizingData) const
925 {
926     // Collapse empty auto repeat tracks if auto-fit.
927     if (sizingData.grid().hasAutoRepeatEmptyTracks(direction) && sizingData.grid().isEmptyAutoRepeatTrack(direction, translatedIndex))
928         return { Length(Fixed), LengthTrackSizing };
929
930     auto& trackSize = rawGridTrackSize(direction, translatedIndex, sizingData);
931     if (trackSize.isFitContent())
932         return trackSize;
933
934     GridLength minTrackBreadth = trackSize.minTrackBreadth();
935     GridLength maxTrackBreadth = trackSize.maxTrackBreadth();
936
937     // FIXME: Ensure this condition for determining whether a size is indefinite or not is working correctly for orthogonal flows.
938     if (minTrackBreadth.isPercentage() || maxTrackBreadth.isPercentage()) {
939         // If the logical width/height of the grid container is indefinite, percentage values are treated as <auto>.
940         // For the inline axis this only happens when we're computing the intrinsic sizes (IntrinsicSizeComputation).
941         if (sizingData.sizingOperation == IntrinsicSizeComputation || (direction == ForRows && !hasDefiniteLogicalHeight())) {
942             if (minTrackBreadth.isPercentage())
943                 minTrackBreadth = Length(Auto);
944             if (maxTrackBreadth.isPercentage())
945                 maxTrackBreadth = Length(Auto);
946         }
947     }
948
949     // Flex sizes are invalid as a min sizing function. However we still can have a flexible |minTrackBreadth|
950     // if the track size is just a flex size (e.g. "1fr"), the spec says that in this case it implies an automatic minimum.
951     if (minTrackBreadth.isFlex())
952         minTrackBreadth = Length(Auto);
953
954     return GridTrackSize(minTrackBreadth, maxTrackBreadth);
955 }
956
957 bool RenderGrid::isOrthogonalChild(const RenderBox& child) const
958 {
959     return child.isHorizontalWritingMode() != isHorizontalWritingMode();
960 }
961
962 GridTrackSizingDirection RenderGrid::flowAwareDirectionForChild(const RenderBox& child, GridTrackSizingDirection direction) const
963 {
964     return !isOrthogonalChild(child) ? direction : (direction == ForColumns ? ForRows : ForColumns);
965 }
966
967 LayoutUnit RenderGrid::logicalHeightForChild(RenderBox& child) const
968 {
969     GridTrackSizingDirection childBlockDirection = flowAwareDirectionForChild(child, ForRows);
970     // If |child| has a relative logical height, we shouldn't let it override its intrinsic height, which is
971     // what we are interested in here. Thus we need to set the block-axis override size to -1 (no possible resolution).
972     if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForRows)) {
973         setOverrideContainingBlockContentSizeForChild(child, childBlockDirection, std::nullopt);
974         child.setNeedsLayout(MarkOnlyThis);
975     }
976
977     // We need to clear the stretched height to properly compute logical height during layout.
978     if (child.needsLayout())
979         child.clearOverrideLogicalContentHeight();
980
981     child.layoutIfNeeded();
982     return child.logicalHeight() + child.marginLogicalHeight();
983 }
984
985 LayoutUnit RenderGrid::minSizeForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
986 {
987     GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
988     bool isRowAxis = direction == childInlineDirection;
989     const Length& childMinSize = isRowAxis ? child.style().logicalMinWidth() : child.style().logicalMinHeight();
990     const Length& childSize = isRowAxis ? child.style().logicalWidth() : child.style().logicalHeight();
991     if (!childSize.isAuto() || childMinSize.isAuto())
992         return minContentForChild(child, direction, sizingData);
993
994     bool overrideSizeHasChanged = updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData);
995     if (isRowAxis) {
996         LayoutUnit marginLogicalWidth = sizingData.sizingOperation == TrackSizing ? computeMarginLogicalSizeForChild(childInlineDirection, child) : marginIntrinsicLogicalWidthForChild(child);
997         return child.computeLogicalWidthInRegionUsing(MinSize, childMinSize, overrideContainingBlockContentSizeForChild(child, childInlineDirection).value_or(0), *this, nullptr) + marginLogicalWidth;
998     }
999
1000     if (overrideSizeHasChanged && (direction != ForColumns || sizingData.sizingOperation != IntrinsicSizeComputation))
1001         child.setNeedsLayout(MarkOnlyThis);
1002     child.layoutIfNeeded();
1003     return child.computeLogicalHeightUsing(MinSize, childMinSize, std::nullopt).value_or(0) + child.marginLogicalHeight() + child.scrollbarLogicalHeight();
1004 }
1005
1006 bool RenderGrid::updateOverrideContainingBlockContentSizeForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
1007 {
1008     LayoutUnit overrideSize = gridAreaBreadthForChild(child, direction, sizingData);
1009     if (hasOverrideContainingBlockContentSizeForChild(child, direction) && overrideContainingBlockContentSizeForChild(child, direction) == overrideSize)
1010         return false;
1011
1012     setOverrideContainingBlockContentSizeForChild(child, direction, overrideSize);
1013     return true;
1014 }
1015
1016 LayoutUnit RenderGrid::minContentForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
1017 {
1018     GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
1019     if (direction == childInlineDirection) {
1020         // If |child| has a relative logical width, we shouldn't let it override its intrinsic width, which is
1021         // what we are interested in here. Thus we need to set the override logical width to std::nullopt (no possible resolution).
1022         if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForColumns))
1023             setOverrideContainingBlockContentSizeForChild(child, childInlineDirection, std::nullopt);
1024
1025         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
1026         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
1027         return child.minPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
1028     }
1029
1030     // All orthogonal flow boxes were already laid out during an early layout phase performed in FrameView::performLayout.
1031     // It's true that grid track sizing was not completed at that time and it may afffect the final height of a
1032     // grid item, but since it's forbidden to perform a layout during intrinsic width computation, we have to use
1033     // that computed height for now.
1034     if (direction == ForColumns && sizingData.sizingOperation == IntrinsicSizeComputation) {
1035         ASSERT(isOrthogonalChild(child));
1036         return child.logicalHeight() + child.marginLogicalHeight();
1037     }
1038
1039     if (updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData))
1040         child.setNeedsLayout(MarkOnlyThis);
1041     return logicalHeightForChild(child);
1042 }
1043
1044 LayoutUnit RenderGrid::maxContentForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
1045 {
1046     GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
1047     if (direction == childInlineDirection) {
1048         // If |child| has a relative logical width, we shouldn't let it override its intrinsic width, which is
1049         // what we are interested in here. Thus we need to set the inline-axis override size to -1 (no possible resolution).
1050         if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForColumns))
1051             setOverrideContainingBlockContentSizeForChild(child, childInlineDirection, std::nullopt);
1052
1053         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
1054         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
1055         return child.maxPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
1056     }
1057
1058     // All orthogonal flow boxes were already laid out during an early layout phase performed in FrameView::performLayout.
1059     // It's true that grid track sizing was not completed at that time and it may afffect the final height of a
1060     // grid item, but since it's forbidden to perform a layout during intrinsic width computation, we have to use
1061     // that computed height for now.
1062     if (direction == ForColumns && sizingData.sizingOperation == IntrinsicSizeComputation) {
1063         ASSERT(isOrthogonalChild(child));
1064         return child.logicalHeight() + child.marginLogicalHeight();
1065     }
1066
1067     if (updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData))
1068         child.setNeedsLayout(MarkOnlyThis);
1069     return logicalHeightForChild(child);
1070 }
1071
1072 class GridItemWithSpan {
1073 public:
1074     GridItemWithSpan(RenderBox& gridItem, GridSpan span)
1075         : m_gridItem(gridItem)
1076         , m_span(span)
1077     {
1078     }
1079
1080     RenderBox& gridItem() const { return m_gridItem; }
1081     GridSpan span() const { return m_span; }
1082
1083     bool operator<(const GridItemWithSpan other) const
1084     {
1085         return m_span.integerSpan() < other.m_span.integerSpan();
1086     }
1087
1088 private:
1089     std::reference_wrapper<RenderBox> m_gridItem;
1090     GridSpan m_span;
1091 };
1092
1093 bool RenderGrid::spanningItemCrossesFlexibleSizedTracks(const GridSpan& itemSpan, GridTrackSizingDirection direction, const GridSizingData& sizingData) const
1094 {
1095     for (auto trackPosition : itemSpan) {
1096         const GridTrackSize& trackSize = gridTrackSize(direction, trackPosition, sizingData);
1097         if (trackSize.minTrackBreadth().isFlex() || trackSize.maxTrackBreadth().isFlex())
1098             return true;
1099     }
1100
1101     return false;
1102 }
1103
1104 struct GridItemsSpanGroupRange {
1105     Vector<GridItemWithSpan>::iterator rangeStart;
1106     Vector<GridItemWithSpan>::iterator rangeEnd;
1107 };
1108
1109 void RenderGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection direction, GridSizingData& sizingData) const
1110 {
1111     sizingData.itemsSortedByIncreasingSpan.shrink(0);
1112     HashSet<RenderBox*> itemsSet;
1113     Grid& grid = sizingData.grid();
1114     if (grid.hasGridItems()) {
1115         for (auto trackIndex : sizingData.contentSizedTracksIndex) {
1116             GridIterator iterator(grid, direction, trackIndex);
1117             GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex];
1118
1119             while (auto* gridItem = iterator.nextGridItem()) {
1120                 if (itemsSet.add(gridItem).isNewEntry) {
1121                     const GridSpan& span = grid.gridItemSpan(*gridItem, direction);
1122                     if (span.integerSpan() == 1)
1123                         resolveContentBasedTrackSizingFunctionsForNonSpanningItems(direction, span, *gridItem, track, sizingData);
1124                     else if (!spanningItemCrossesFlexibleSizedTracks(span, direction, sizingData))
1125                         sizingData.itemsSortedByIncreasingSpan.append(GridItemWithSpan(*gridItem, span));
1126                 }
1127             }
1128         }
1129         std::sort(sizingData.itemsSortedByIncreasingSpan.begin(), sizingData.itemsSortedByIncreasingSpan.end());
1130     }
1131
1132     auto it = sizingData.itemsSortedByIncreasingSpan.begin();
1133     auto end = sizingData.itemsSortedByIncreasingSpan.end();
1134     while (it != end) {
1135         GridItemsSpanGroupRange spanGroupRange = { it, std::upper_bound(it, end, *it) };
1136         resolveContentBasedTrackSizingFunctionsForItems<ResolveIntrinsicMinimums>(direction, sizingData, spanGroupRange);
1137         resolveContentBasedTrackSizingFunctionsForItems<ResolveContentBasedMinimums>(direction, sizingData, spanGroupRange);
1138         resolveContentBasedTrackSizingFunctionsForItems<ResolveMaxContentMinimums>(direction, sizingData, spanGroupRange);
1139         resolveContentBasedTrackSizingFunctionsForItems<ResolveIntrinsicMaximums>(direction, sizingData, spanGroupRange);
1140         resolveContentBasedTrackSizingFunctionsForItems<ResolveMaxContentMaximums>(direction, sizingData, spanGroupRange);
1141         it = spanGroupRange.rangeEnd;
1142     }
1143
1144     for (auto trackIndex : sizingData.contentSizedTracksIndex) {
1145         GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex];
1146         if (track.growthLimit() == infinity)
1147             track.setGrowthLimit(track.baseSize());
1148     }
1149 }
1150
1151 void RenderGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection direction, const GridSpan& span, RenderBox& gridItem, GridTrack& track, GridSizingData& sizingData) const
1152 {
1153     unsigned trackPosition = span.startLine();
1154     GridTrackSize trackSize = gridTrackSize(direction, trackPosition, sizingData);
1155
1156     if (trackSize.hasMinContentMinTrackBreadth())
1157         track.setBaseSize(std::max(track.baseSize(), minContentForChild(gridItem, direction, sizingData)));
1158     else if (trackSize.hasMaxContentMinTrackBreadth())
1159         track.setBaseSize(std::max(track.baseSize(), maxContentForChild(gridItem, direction, sizingData)));
1160     else if (trackSize.hasAutoMinTrackBreadth())
1161         track.setBaseSize(std::max(track.baseSize(), minSizeForChild(gridItem, direction, sizingData)));
1162
1163     if (trackSize.hasMinContentMaxTrackBreadth()) {
1164         track.setGrowthLimit(std::max(track.growthLimit(), minContentForChild(gridItem, direction, sizingData)));
1165     } else if (trackSize.hasMaxContentOrAutoMaxTrackBreadth()) {
1166         LayoutUnit growthLimit = maxContentForChild(gridItem, direction, sizingData);
1167         if (trackSize.isFitContent())
1168             growthLimit = std::min(growthLimit, valueForLength(trackSize.fitContentTrackBreadth().length(), sizingData.availableSpace().value_or(0)));
1169         track.setGrowthLimit(std::max(track.growthLimit(), growthLimit));
1170     }
1171 }
1172
1173 static LayoutUnit trackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, GridTrack& track, TrackSizeRestriction restriction)
1174 {
1175     switch (phase) {
1176     case ResolveIntrinsicMinimums:
1177     case ResolveContentBasedMinimums:
1178     case ResolveMaxContentMinimums:
1179     case MaximizeTracks:
1180         return track.baseSize();
1181     case ResolveIntrinsicMaximums:
1182     case ResolveMaxContentMaximums:
1183         return restriction == AllowInfinity ? track.growthLimit() : track.growthLimitIfNotInfinite();
1184     }
1185
1186     ASSERT_NOT_REACHED();
1187     return track.baseSize();
1188 }
1189
1190 bool RenderGrid::shouldProcessTrackForTrackSizeComputationPhase(TrackSizeComputationPhase phase, const GridTrackSize& trackSize)
1191 {
1192     switch (phase) {
1193     case ResolveIntrinsicMinimums:
1194         return trackSize.hasIntrinsicMinTrackBreadth();
1195     case ResolveContentBasedMinimums:
1196         return trackSize.hasMinOrMaxContentMinTrackBreadth();
1197     case ResolveMaxContentMinimums:
1198         return trackSize.hasMaxContentMinTrackBreadth();
1199     case ResolveIntrinsicMaximums:
1200         return trackSize.hasIntrinsicMaxTrackBreadth();
1201     case ResolveMaxContentMaximums:
1202         return trackSize.hasMaxContentOrAutoMaxTrackBreadth();
1203     case MaximizeTracks:
1204         ASSERT_NOT_REACHED();
1205         return false;
1206     }
1207
1208     ASSERT_NOT_REACHED();
1209     return false;
1210 }
1211
1212 bool RenderGrid::trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(TrackSizeComputationPhase phase, const GridTrackSize& trackSize)
1213 {
1214     switch (phase) {
1215     case ResolveIntrinsicMinimums:
1216     case ResolveContentBasedMinimums:
1217         return trackSize.hasAutoOrMinContentMinTrackBreadthAndIntrinsicMaxTrackBreadth();
1218     case ResolveMaxContentMinimums:
1219         return trackSize.hasMaxContentMinTrackBreadthAndMaxContentMaxTrackBreadth();
1220     case ResolveIntrinsicMaximums:
1221     case ResolveMaxContentMaximums:
1222         return true;
1223     case MaximizeTracks:
1224         ASSERT_NOT_REACHED();
1225         return false;
1226     }
1227
1228     ASSERT_NOT_REACHED();
1229     return false;
1230 }
1231
1232 void RenderGrid::markAsInfinitelyGrowableForTrackSizeComputationPhase(TrackSizeComputationPhase phase, GridTrack& track)
1233 {
1234     switch (phase) {
1235     case ResolveIntrinsicMinimums:
1236     case ResolveContentBasedMinimums:
1237     case ResolveMaxContentMinimums:
1238         return;
1239     case ResolveIntrinsicMaximums:
1240         if (trackSizeForTrackSizeComputationPhase(phase, track, AllowInfinity) == infinity  && track.plannedSize() != infinity)
1241             track.setInfinitelyGrowable(true);
1242         return;
1243     case ResolveMaxContentMaximums:
1244         if (track.infinitelyGrowable())
1245             track.setInfinitelyGrowable(false);
1246         return;
1247     case MaximizeTracks:
1248         ASSERT_NOT_REACHED();
1249         return;
1250     }
1251
1252     ASSERT_NOT_REACHED();
1253 }
1254
1255 void RenderGrid::updateTrackSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, GridTrack& track)
1256 {
1257     switch (phase) {
1258     case ResolveIntrinsicMinimums:
1259     case ResolveContentBasedMinimums:
1260     case ResolveMaxContentMinimums:
1261         track.setBaseSize(track.plannedSize());
1262         return;
1263     case ResolveIntrinsicMaximums:
1264     case ResolveMaxContentMaximums:
1265         track.setGrowthLimit(track.plannedSize());
1266         return;
1267     case MaximizeTracks:
1268         ASSERT_NOT_REACHED();
1269         return;
1270     }
1271
1272     ASSERT_NOT_REACHED();
1273 }
1274
1275 LayoutUnit RenderGrid::currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, RenderBox& gridItem, GridTrackSizingDirection direction, GridSizingData& sizingData) const
1276 {
1277     switch (phase) {
1278     case ResolveIntrinsicMinimums:
1279     case ResolveIntrinsicMaximums:
1280         return minSizeForChild(gridItem, direction, sizingData);
1281     case ResolveContentBasedMinimums:
1282         return minContentForChild(gridItem, direction, sizingData);
1283     case ResolveMaxContentMinimums:
1284     case ResolveMaxContentMaximums:
1285         return maxContentForChild(gridItem, direction, sizingData);
1286     case MaximizeTracks:
1287         ASSERT_NOT_REACHED();
1288         return 0;
1289     }
1290
1291     ASSERT_NOT_REACHED();
1292     return 0;
1293 }
1294
1295 template <TrackSizeComputationPhase phase>
1296 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, const GridItemsSpanGroupRange& gridItemsWithSpan) const
1297 {
1298     Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
1299     for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
1300         GridTrack& track = tracks[trackIndex];
1301         track.setPlannedSize(trackSizeForTrackSizeComputationPhase(phase, track, AllowInfinity));
1302     }
1303
1304     for (auto it = gridItemsWithSpan.rangeStart; it != gridItemsWithSpan.rangeEnd; ++it) {
1305         GridItemWithSpan& gridItemWithSpan = *it;
1306         ASSERT(gridItemWithSpan.span().integerSpan() > 1);
1307         const GridSpan& itemSpan = gridItemWithSpan.span();
1308
1309         sizingData.filteredTracks.shrink(0);
1310         sizingData.growBeyondGrowthLimitsTracks.shrink(0);
1311         LayoutUnit spanningTracksSize;
1312         for (auto trackPosition : itemSpan) {
1313             const GridTrackSize& trackSize = gridTrackSize(direction, trackPosition, sizingData);
1314             GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackPosition] : sizingData.rowTracks[trackPosition];
1315             spanningTracksSize += trackSizeForTrackSizeComputationPhase(phase, track, ForbidInfinity);
1316             if (!shouldProcessTrackForTrackSizeComputationPhase(phase, trackSize))
1317                 continue;
1318
1319             sizingData.filteredTracks.append(&track);
1320
1321             if (trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(phase, trackSize))
1322                 sizingData.growBeyondGrowthLimitsTracks.append(&track);
1323         }
1324
1325         if (sizingData.filteredTracks.isEmpty())
1326             continue;
1327
1328         spanningTracksSize += guttersSize(sizingData.grid(), direction, itemSpan.startLine(), itemSpan.integerSpan());
1329
1330         LayoutUnit extraSpace = currentItemSizeForTrackSizeComputationPhase(phase, gridItemWithSpan.gridItem(), direction, sizingData) - spanningTracksSize;
1331         extraSpace = std::max<LayoutUnit>(extraSpace, 0);
1332         auto& tracksToGrowBeyondGrowthLimits = sizingData.growBeyondGrowthLimitsTracks.isEmpty() ? sizingData.filteredTracks : sizingData.growBeyondGrowthLimitsTracks;
1333         distributeSpaceToTracks<phase>(sizingData.filteredTracks, &tracksToGrowBeyondGrowthLimits, extraSpace);
1334     }
1335
1336     for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
1337         GridTrack& track = tracks[trackIndex];
1338         markAsInfinitelyGrowableForTrackSizeComputationPhase(phase, track);
1339         updateTrackSizeForTrackSizeComputationPhase(phase, track);
1340     }
1341 }
1342
1343 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTrack* track2)
1344 {
1345     // This check ensures that we respect the irreflexivity property of the strict weak ordering required by std::sort
1346     // (forall x: NOT x < x).
1347     bool track1HasInfiniteGrowthPotentialWithoutCap = track1->infiniteGrowthPotential() && !track1->growthLimitCap();
1348     bool track2HasInfiniteGrowthPotentialWithoutCap = track2->infiniteGrowthPotential() && !track2->growthLimitCap();
1349
1350     if (track1HasInfiniteGrowthPotentialWithoutCap && track2HasInfiniteGrowthPotentialWithoutCap)
1351         return false;
1352
1353     if (track1HasInfiniteGrowthPotentialWithoutCap || track2HasInfiniteGrowthPotentialWithoutCap)
1354         return track2HasInfiniteGrowthPotentialWithoutCap;
1355
1356     LayoutUnit track1Limit = track1->growthLimitCap().value_or(track1->growthLimit());
1357     LayoutUnit track2Limit = track2->growthLimitCap().value_or(track2->growthLimit());
1358     return (track1Limit - track1->baseSize()) < (track2Limit - track2->baseSize());
1359 }
1360
1361 static void clampGrowthShareIfNeeded(TrackSizeComputationPhase phase, const GridTrack& track, LayoutUnit& growthShare)
1362 {
1363     if (phase != ResolveMaxContentMaximums || !track.growthLimitCap())
1364         return;
1365
1366     LayoutUnit distanceToCap = track.growthLimitCap().value() - track.tempSize();
1367     if (distanceToCap <= 0)
1368         return;
1369
1370     growthShare = std::min(growthShare, distanceToCap);
1371 }
1372
1373 template <TrackSizeComputationPhase phase>
1374 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* growBeyondGrowthLimitsTracks, LayoutUnit& freeSpace) const
1375 {
1376     ASSERT(freeSpace >= 0);
1377
1378     for (auto* track : tracks)
1379         track->setTempSize(trackSizeForTrackSizeComputationPhase(phase, *track, ForbidInfinity));
1380
1381     if (freeSpace > 0) {
1382         std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
1383
1384         unsigned tracksSize = tracks.size();
1385         for (unsigned i = 0; i < tracksSize; ++i) {
1386             GridTrack& track = *tracks[i];
1387             const LayoutUnit& trackBreadth = trackSizeForTrackSizeComputationPhase(phase, track, ForbidInfinity);
1388             bool infiniteGrowthPotential = track.infiniteGrowthPotential();
1389             LayoutUnit trackGrowthPotential = infiniteGrowthPotential ? track.growthLimit() : track.growthLimit() - trackBreadth;
1390             // Let's avoid computing availableLogicalSpaceShare as much as possible as it's a hot spot in performance tests.
1391             if (trackGrowthPotential > 0 || infiniteGrowthPotential) {
1392                 LayoutUnit availableLogicalSpaceShare = freeSpace / (tracksSize - i);
1393                 LayoutUnit growthShare = infiniteGrowthPotential ? availableLogicalSpaceShare : std::min(availableLogicalSpaceShare, trackGrowthPotential);
1394                 clampGrowthShareIfNeeded(phase, track, growthShare);
1395                 ASSERT_WITH_MESSAGE(growthShare >= 0, "We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function. We can still have 0 as growthShare if the amount of tracks greatly exceeds the freeSpace.");
1396                 track.growTempSize(growthShare);
1397                 freeSpace -= growthShare;
1398             }
1399         }
1400     }
1401
1402     if (freeSpace > 0 && growBeyondGrowthLimitsTracks) {
1403         // We need to sort them because there might be tracks with growth limit caps (like the ones
1404         // with fit-content()) which cannot indefinitely grow over the limits.
1405         if (phase == ResolveMaxContentMaximums)
1406             std::sort(growBeyondGrowthLimitsTracks->begin(), growBeyondGrowthLimitsTracks->end(), sortByGridTrackGrowthPotential);
1407
1408         unsigned tracksGrowingBeyondGrowthLimitsSize = growBeyondGrowthLimitsTracks->size();
1409         for (unsigned i = 0; i < tracksGrowingBeyondGrowthLimitsSize; ++i) {
1410             GridTrack* track = growBeyondGrowthLimitsTracks->at(i);
1411             LayoutUnit growthShare = freeSpace / (tracksGrowingBeyondGrowthLimitsSize - i);
1412             clampGrowthShareIfNeeded(phase, *track, growthShare);
1413             track->growTempSize(growthShare);
1414             freeSpace -= growthShare;
1415         }
1416     }
1417
1418     for (auto* track : tracks)
1419         track->setPlannedSize(track->plannedSize() == infinity ? track->tempSize() : std::max(track->plannedSize(), track->tempSize()));
1420 }
1421
1422 #ifndef NDEBUG
1423 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection direction, GridSizingData& sizingData)
1424 {
1425     const Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
1426     const LayoutUnit maxSize = sizingData.availableSpace().value_or(0);
1427     for (unsigned i = 0; i < tracks.size(); ++i) {
1428         const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData);
1429         if (computeUsedBreadthOfMinLength(trackSize, maxSize) > tracks[i].baseSize())
1430             return false;
1431     }
1432     return true;
1433 }
1434 #endif
1435
1436 unsigned RenderGrid::computeAutoRepeatTracksCount(GridTrackSizingDirection direction, SizingOperation sizingOperation) const
1437 {
1438     bool isRowAxis = direction == ForColumns;
1439     const auto& autoRepeatTracks = isRowAxis ? style().gridAutoRepeatColumns() : style().gridAutoRepeatRows();
1440     unsigned autoRepeatTrackListLength = autoRepeatTracks.size();
1441
1442     if (!autoRepeatTrackListLength)
1443         return 0;
1444
1445     std::optional<LayoutUnit> availableSize;
1446     if (isRowAxis) {
1447         if (sizingOperation != IntrinsicSizeComputation)
1448             availableSize =  availableLogicalWidth();
1449     } else {
1450         availableSize = computeContentLogicalHeight(MainOrPreferredSize, style().logicalHeight(), std::nullopt);
1451         if (!availableSize) {
1452             const Length& maxLength = style().logicalMaxHeight();
1453             if (!maxLength.isUndefined())
1454                 availableSize = computeContentLogicalHeight(MaxSize, maxLength, std::nullopt);
1455         }
1456         if (availableSize)
1457             availableSize = constrainContentBoxLogicalHeightByMinMax(availableSize.value(), std::nullopt);
1458     }
1459
1460     bool needsToFulfillMinimumSize = false;
1461     if (!availableSize) {
1462         const Length& minSize = isRowAxis ? style().logicalMinWidth() : style().logicalMinHeight();
1463         if (!minSize.isSpecified())
1464             return autoRepeatTrackListLength;
1465
1466         LayoutUnit containingBlockAvailableSize = isRowAxis ? containingBlockLogicalWidthForContent() : containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
1467         availableSize = valueForLength(minSize, containingBlockAvailableSize);
1468         needsToFulfillMinimumSize = true;
1469     }
1470
1471     LayoutUnit autoRepeatTracksSize;
1472     for (auto& autoTrackSize : autoRepeatTracks) {
1473         ASSERT(autoTrackSize.minTrackBreadth().isLength());
1474         ASSERT(!autoTrackSize.minTrackBreadth().isFlex());
1475         bool hasDefiniteMaxTrackSizingFunction = autoTrackSize.maxTrackBreadth().isLength() && !autoTrackSize.maxTrackBreadth().isContentSized();
1476         auto trackLength = hasDefiniteMaxTrackSizingFunction ? autoTrackSize.maxTrackBreadth().length() : autoTrackSize.minTrackBreadth().length();
1477         autoRepeatTracksSize += valueForLength(trackLength, availableSize.value());
1478     }
1479     // For the purpose of finding the number of auto-repeated tracks, the UA must floor the track size to a UA-specified
1480     // value to avoid division by zero. It is suggested that this floor be 1px.
1481     autoRepeatTracksSize = std::max<LayoutUnit>(LayoutUnit(1), autoRepeatTracksSize);
1482
1483     // There will be always at least 1 auto-repeat track, so take it already into account when computing the total track size.
1484     LayoutUnit tracksSize = autoRepeatTracksSize;
1485     auto& trackSizes = isRowAxis ? style().gridColumns() : style().gridRows();
1486
1487     for (const auto& track : trackSizes) {
1488         bool hasDefiniteMaxTrackBreadth = track.maxTrackBreadth().isLength() && !track.maxTrackBreadth().isContentSized();
1489         ASSERT(hasDefiniteMaxTrackBreadth || (track.minTrackBreadth().isLength() && !track.minTrackBreadth().isContentSized()));
1490         tracksSize += valueForLength(hasDefiniteMaxTrackBreadth ? track.maxTrackBreadth().length() : track.minTrackBreadth().length(), availableSize.value());
1491     }
1492
1493     // Add gutters as if there where only 1 auto repeat track. Gaps between auto repeat tracks will be added later when
1494     // computing the repetitions.
1495     LayoutUnit gapSize = gridGapForDirection(direction);
1496     tracksSize += gapSize * trackSizes.size();
1497
1498     LayoutUnit freeSpace = availableSize.value() - tracksSize;
1499     if (freeSpace <= 0)
1500         return autoRepeatTrackListLength;
1501
1502     unsigned repetitions = 1 + (freeSpace / (autoRepeatTracksSize + gapSize)).toInt();
1503
1504     // Provided the grid container does not have a definite size or max-size in the relevant axis,
1505     // if the min size is definite then the number of repetitions is the largest possible positive
1506     // integer that fulfills that minimum requirement.
1507     if (needsToFulfillMinimumSize)
1508         ++repetitions;
1509
1510     return repetitions * autoRepeatTrackListLength;
1511 }
1512
1513
1514 std::unique_ptr<OrderedTrackIndexSet> RenderGrid::computeEmptyTracksForAutoRepeat(Grid& grid, GridTrackSizingDirection direction) const
1515 {
1516     bool isRowAxis = direction == ForColumns;
1517     if ((isRowAxis && style().gridAutoRepeatColumnsType() != AutoFit)
1518         || (!isRowAxis && style().gridAutoRepeatRowsType() != AutoFit))
1519         return nullptr;
1520
1521     std::unique_ptr<OrderedTrackIndexSet> emptyTrackIndexes;
1522     unsigned insertionPoint = isRowAxis ? style().gridAutoRepeatColumnsInsertionPoint() : style().gridAutoRepeatRowsInsertionPoint();
1523     unsigned firstAutoRepeatTrack = insertionPoint + std::abs(grid.smallestTrackStart(direction));
1524     unsigned lastAutoRepeatTrack = firstAutoRepeatTrack + grid.autoRepeatTracks(direction);
1525
1526     if (!grid.hasGridItems()) {
1527         emptyTrackIndexes = std::make_unique<OrderedTrackIndexSet>();
1528         for (unsigned trackIndex = firstAutoRepeatTrack; trackIndex < lastAutoRepeatTrack; ++trackIndex)
1529             emptyTrackIndexes->add(trackIndex);
1530     } else {
1531         for (unsigned trackIndex = firstAutoRepeatTrack; trackIndex < lastAutoRepeatTrack; ++trackIndex) {
1532             GridIterator iterator(grid, direction, trackIndex);
1533             if (!iterator.nextGridItem()) {
1534                 if (!emptyTrackIndexes)
1535                     emptyTrackIndexes = std::make_unique<OrderedTrackIndexSet>();
1536                 emptyTrackIndexes->add(trackIndex);
1537             }
1538         }
1539     }
1540     return emptyTrackIndexes;
1541 }
1542
1543 void RenderGrid::placeItemsOnGrid(Grid& grid, SizingOperation sizingOperation) const
1544 {
1545     unsigned autoRepeatColumns = computeAutoRepeatTracksCount(ForColumns, sizingOperation);
1546     unsigned autoRepeatRows = computeAutoRepeatTracksCount(ForRows, sizingOperation);
1547     if (autoRepeatColumns != grid.autoRepeatTracks(ForColumns) || autoRepeatRows != grid.autoRepeatTracks(ForRows)) {
1548         grid.setNeedsItemsPlacement(true);
1549         grid.setAutoRepeatTracks(autoRepeatRows, autoRepeatColumns);
1550     }
1551
1552     if (!grid.needsItemsPlacement())
1553         return;
1554
1555     ASSERT(!grid.hasGridItems());
1556     populateExplicitGridAndOrderIterator(grid);
1557
1558     Vector<RenderBox*> autoMajorAxisAutoGridItems;
1559     Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
1560     bool hasAnyOrthogonalGridItem = false;
1561     for (auto* child = grid.orderIterator().first(); child; child = grid.orderIterator().next()) {
1562         if (child->isOutOfFlowPositioned())
1563             continue;
1564
1565         hasAnyOrthogonalGridItem = hasAnyOrthogonalGridItem || isOrthogonalChild(*child);
1566
1567         GridArea area = grid.gridItemArea(*child);
1568         if (!area.rows.isIndefinite())
1569             area.rows.translate(std::abs(grid.smallestTrackStart(ForRows)));
1570         if (!area.columns.isIndefinite())
1571             area.columns.translate(std::abs(grid.smallestTrackStart(ForColumns)));
1572
1573         if (area.rows.isIndefinite() || area.columns.isIndefinite()) {
1574             grid.setGridItemArea(*child, area);
1575             bool majorAxisDirectionIsForColumns = autoPlacementMajorAxisDirection() == ForColumns;
1576             if ((majorAxisDirectionIsForColumns && area.columns.isIndefinite())
1577                 || (!majorAxisDirectionIsForColumns && area.rows.isIndefinite()))
1578                 autoMajorAxisAutoGridItems.append(child);
1579             else
1580                 specifiedMajorAxisAutoGridItems.append(child);
1581             continue;
1582         }
1583         grid.insert(*child, { area.rows, area.columns });
1584     }
1585     grid.setHasAnyOrthogonalGridItem(hasAnyOrthogonalGridItem);
1586
1587 #if ENABLE(ASSERT)
1588     if (grid.hasGridItems()) {
1589         ASSERT(grid.numTracks(ForRows) >= GridPositionsResolver::explicitGridRowCount(style(), grid.autoRepeatTracks(ForRows)));
1590         ASSERT(grid.numTracks(ForColumns) >= GridPositionsResolver::explicitGridColumnCount(style(), grid.autoRepeatTracks(ForColumns)));
1591     }
1592 #endif
1593
1594     placeSpecifiedMajorAxisItemsOnGrid(grid, specifiedMajorAxisAutoGridItems);
1595     placeAutoMajorAxisItemsOnGrid(grid, autoMajorAxisAutoGridItems);
1596
1597     // Compute collapsible tracks for auto-fit.
1598     grid.setAutoRepeatEmptyColumns(computeEmptyTracksForAutoRepeat(grid, ForColumns));
1599     grid.setAutoRepeatEmptyRows(computeEmptyTracksForAutoRepeat(grid, ForRows));
1600
1601     grid.setNeedsItemsPlacement(false);
1602
1603 #if ENABLE(ASSERT)
1604     for (auto* child = grid.orderIterator().first(); child; child = grid.orderIterator().next()) {
1605         if (child->isOutOfFlowPositioned())
1606             continue;
1607
1608         GridArea area = grid.gridItemArea(*child);
1609         ASSERT(area.rows.isTranslatedDefinite() && area.columns.isTranslatedDefinite());
1610     }
1611 #endif
1612 }
1613
1614 void RenderGrid::populateExplicitGridAndOrderIterator(Grid& grid) const
1615 {
1616     OrderIteratorPopulator populator(grid.orderIterator());
1617     int smallestRowStart = 0;
1618     int smallestColumnStart = 0;
1619     unsigned autoRepeatRows = grid.autoRepeatTracks(ForRows);
1620     unsigned autoRepeatColumns = grid.autoRepeatTracks(ForColumns);
1621     unsigned maximumRowIndex = GridPositionsResolver::explicitGridRowCount(style(), autoRepeatRows);
1622     unsigned maximumColumnIndex = GridPositionsResolver::explicitGridColumnCount(style(), autoRepeatColumns);
1623
1624     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1625         if (child->isOutOfFlowPositioned())
1626             continue;
1627
1628         populator.collectChild(*child);
1629
1630         GridSpan rowPositions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), *child, ForRows, autoRepeatRows);
1631         if (!rowPositions.isIndefinite()) {
1632             smallestRowStart = std::min(smallestRowStart, rowPositions.untranslatedStartLine());
1633             maximumRowIndex = std::max<int>(maximumRowIndex, rowPositions.untranslatedEndLine());
1634         } else {
1635             // Grow the grid for items with a definite row span, getting the largest such span.
1636             unsigned spanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), *child, ForRows);
1637             maximumRowIndex = std::max(maximumRowIndex, spanSize);
1638         }
1639
1640         GridSpan columnPositions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), *child, ForColumns, autoRepeatColumns);
1641         if (!columnPositions.isIndefinite()) {
1642             smallestColumnStart = std::min(smallestColumnStart, columnPositions.untranslatedStartLine());
1643             maximumColumnIndex = std::max<int>(maximumColumnIndex, columnPositions.untranslatedEndLine());
1644         } else {
1645             // Grow the grid for items with a definite column span, getting the largest such span.
1646             unsigned spanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), *child, ForColumns);
1647             maximumColumnIndex = std::max(maximumColumnIndex, spanSize);
1648         }
1649
1650         grid.setGridItemArea(*child, { rowPositions, columnPositions });
1651     }
1652
1653     grid.setSmallestTracksStart(smallestRowStart, smallestColumnStart);
1654     grid.ensureGridSize(maximumRowIndex + std::abs(smallestRowStart), maximumColumnIndex + std::abs(smallestColumnStart));
1655 }
1656
1657 std::unique_ptr<GridArea> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(Grid& grid, const RenderBox& gridItem, GridTrackSizingDirection specifiedDirection, const GridSpan& specifiedPositions) const
1658 {
1659     GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
1660     const unsigned endOfCrossDirection = grid.numTracks(crossDirection);
1661     unsigned crossDirectionSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), gridItem, crossDirection);
1662     GridSpan crossDirectionPositions = GridSpan::translatedDefiniteGridSpan(endOfCrossDirection, endOfCrossDirection + crossDirectionSpanSize);
1663     return std::make_unique<GridArea>(specifiedDirection == ForColumns ? crossDirectionPositions : specifiedPositions, specifiedDirection == ForColumns ? specifiedPositions : crossDirectionPositions);
1664 }
1665
1666 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(Grid& grid, const Vector<RenderBox*>& autoGridItems) const
1667 {
1668     bool isForColumns = autoPlacementMajorAxisDirection() == ForColumns;
1669     bool isGridAutoFlowDense = style().isGridAutoFlowAlgorithmDense();
1670
1671     // Mapping between the major axis tracks (rows or columns) and the last auto-placed item's position inserted on
1672     // that track. This is needed to implement "sparse" packing for items locked to a given track.
1673     // See http://dev.w3.org/csswg/css-grid/#auto-placement-algo
1674     HashMap<unsigned, unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> minorAxisCursors;
1675
1676     for (auto& autoGridItem : autoGridItems) {
1677         GridSpan majorAxisPositions = grid.gridItemSpan(*autoGridItem, autoPlacementMajorAxisDirection());
1678         ASSERT(majorAxisPositions.isTranslatedDefinite());
1679         ASSERT(grid.gridItemSpan(*autoGridItem, autoPlacementMinorAxisDirection()).isIndefinite());
1680         unsigned minorAxisSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), *autoGridItem, autoPlacementMinorAxisDirection());
1681         unsigned majorAxisInitialPosition = majorAxisPositions.startLine();
1682
1683         GridIterator iterator(grid, autoPlacementMajorAxisDirection(), majorAxisPositions.startLine(), isGridAutoFlowDense ? 0 : minorAxisCursors.get(majorAxisInitialPosition));
1684         std::unique_ptr<GridArea> emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions.integerSpan(), minorAxisSpanSize);
1685         if (!emptyGridArea)
1686             emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(grid, *autoGridItem, autoPlacementMajorAxisDirection(), majorAxisPositions);
1687
1688         grid.insert(*autoGridItem, *emptyGridArea);
1689
1690         if (!isGridAutoFlowDense)
1691             minorAxisCursors.set(majorAxisInitialPosition, isForColumns ? emptyGridArea->rows.startLine() : emptyGridArea->columns.startLine());
1692     }
1693 }
1694
1695 void RenderGrid::placeAutoMajorAxisItemsOnGrid(Grid& grid, const Vector<RenderBox*>& autoGridItems) const
1696 {
1697     AutoPlacementCursor autoPlacementCursor = {0, 0};
1698     bool isGridAutoFlowDense = style().isGridAutoFlowAlgorithmDense();
1699
1700     for (auto& autoGridItem : autoGridItems) {
1701         placeAutoMajorAxisItemOnGrid(grid, *autoGridItem, autoPlacementCursor);
1702
1703         if (isGridAutoFlowDense) {
1704             autoPlacementCursor.first = 0;
1705             autoPlacementCursor.second = 0;
1706         }
1707     }
1708 }
1709
1710 void RenderGrid::placeAutoMajorAxisItemOnGrid(Grid& grid, RenderBox& gridItem, AutoPlacementCursor& autoPlacementCursor) const
1711 {
1712     ASSERT(grid.gridItemSpan(gridItem, autoPlacementMajorAxisDirection()).isIndefinite());
1713     unsigned majorAxisSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), gridItem, autoPlacementMajorAxisDirection());
1714
1715     const unsigned endOfMajorAxis = grid.numTracks(autoPlacementMajorAxisDirection());
1716     unsigned majorAxisAutoPlacementCursor = autoPlacementMajorAxisDirection() == ForColumns ? autoPlacementCursor.second : autoPlacementCursor.first;
1717     unsigned minorAxisAutoPlacementCursor = autoPlacementMajorAxisDirection() == ForColumns ? autoPlacementCursor.first : autoPlacementCursor.second;
1718
1719     std::unique_ptr<GridArea> emptyGridArea;
1720     GridSpan minorAxisPositions = grid.gridItemSpan(gridItem, autoPlacementMinorAxisDirection());
1721     if (minorAxisPositions.isTranslatedDefinite()) {
1722         // Move to the next track in major axis if initial position in minor axis is before auto-placement cursor.
1723         if (minorAxisPositions.startLine() < minorAxisAutoPlacementCursor)
1724             majorAxisAutoPlacementCursor++;
1725
1726         if (majorAxisAutoPlacementCursor < endOfMajorAxis) {
1727             GridIterator iterator(grid, autoPlacementMinorAxisDirection(), minorAxisPositions.startLine(), majorAxisAutoPlacementCursor);
1728             emptyGridArea = iterator.nextEmptyGridArea(minorAxisPositions.integerSpan(), majorAxisSpanSize);
1729         }
1730
1731         if (!emptyGridArea)
1732             emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(grid, gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions);
1733     } else {
1734         unsigned minorAxisSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), gridItem, autoPlacementMinorAxisDirection());
1735
1736         for (unsigned majorAxisIndex = majorAxisAutoPlacementCursor; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) {
1737             GridIterator iterator(grid, autoPlacementMajorAxisDirection(), majorAxisIndex, minorAxisAutoPlacementCursor);
1738             emptyGridArea = iterator.nextEmptyGridArea(majorAxisSpanSize, minorAxisSpanSize);
1739
1740             if (emptyGridArea) {
1741                 // Check that it fits in the minor axis direction, as we shouldn't grow in that direction here (it was already managed in populateExplicitGridAndOrderIterator()).
1742                 unsigned minorAxisFinalPositionIndex = autoPlacementMinorAxisDirection() == ForColumns ? emptyGridArea->columns.endLine() : emptyGridArea->rows.endLine();
1743                 const unsigned endOfMinorAxis = grid.numTracks(autoPlacementMinorAxisDirection());
1744                 if (minorAxisFinalPositionIndex <= endOfMinorAxis)
1745                     break;
1746
1747                 // Discard empty grid area as it does not fit in the minor axis direction.
1748                 // We don't need to create a new empty grid area yet as we might find a valid one in the next iteration.
1749                 emptyGridArea = nullptr;
1750             }
1751
1752             // As we're moving to the next track in the major axis we should reset the auto-placement cursor in the minor axis.
1753             minorAxisAutoPlacementCursor = 0;
1754         }
1755
1756         if (!emptyGridArea)
1757             emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(grid, gridItem, autoPlacementMinorAxisDirection(), GridSpan::translatedDefiniteGridSpan(0, minorAxisSpanSize));
1758     }
1759
1760     grid.insert(gridItem, *emptyGridArea);
1761     autoPlacementCursor.first = emptyGridArea->rows.startLine();
1762     autoPlacementCursor.second = emptyGridArea->columns.startLine();
1763 }
1764
1765 GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
1766 {
1767     return style().isGridAutoFlowDirectionColumn() ? ForColumns : ForRows;
1768 }
1769
1770 GridTrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
1771 {
1772     return style().isGridAutoFlowDirectionColumn() ? ForRows : ForColumns;
1773 }
1774
1775 void RenderGrid::dirtyGrid()
1776 {
1777     if (m_grid.needsItemsPlacement())
1778         return;
1779
1780     m_grid.setNeedsItemsPlacement(true);
1781 }
1782
1783 Vector<LayoutUnit> RenderGrid::trackSizesForComputedStyle(GridTrackSizingDirection direction) const
1784 {
1785     bool isRowAxis = direction == ForColumns;
1786     auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
1787     size_t numPositions = positions.size();
1788     LayoutUnit offsetBetweenTracks = isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
1789
1790     Vector<LayoutUnit> tracks;
1791     if (numPositions < 2)
1792         return tracks;
1793
1794     ASSERT(!m_grid.needsItemsPlacement());
1795     bool hasCollapsedTracks = m_grid.hasAutoRepeatEmptyTracks(direction);
1796     LayoutUnit gap = !hasCollapsedTracks ? gridGapForDirection(direction) : LayoutUnit();
1797     tracks.reserveCapacity(numPositions - 1);
1798     for (size_t i = 0; i < numPositions - 2; ++i)
1799         tracks.append(positions[i + 1] - positions[i] - offsetBetweenTracks - gap);
1800     tracks.append(positions[numPositions - 1] - positions[numPositions - 2]);
1801
1802     if (!hasCollapsedTracks)
1803         return tracks;
1804
1805     size_t remainingEmptyTracks = m_grid.autoRepeatEmptyTracks(direction)->size();
1806     size_t lastLine = tracks.size();
1807     gap = gridGapForDirection(direction);
1808     for (size_t i = 1; i < lastLine; ++i) {
1809         if (m_grid.isEmptyAutoRepeatTrack(direction, i - 1))
1810             --remainingEmptyTracks;
1811         else {
1812             // Remove the gap between consecutive non empty tracks. Remove it also just once for an
1813             // arbitrary number of empty tracks between two non empty ones.
1814             bool allRemainingTracksAreEmpty = remainingEmptyTracks == (lastLine - i);
1815             if (!allRemainingTracksAreEmpty || !m_grid.isEmptyAutoRepeatTrack(direction, i))
1816                 tracks[i - 1] -= gap;
1817         }
1818     }
1819
1820     return tracks;
1821 }
1822
1823 static const StyleContentAlignmentData& contentAlignmentNormalBehaviorGrid()
1824 {
1825     static const StyleContentAlignmentData normalBehavior = {ContentPositionNormal, ContentDistributionStretch};
1826     return normalBehavior;
1827 }
1828
1829 void RenderGrid::applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection direction, GridSizingData& sizingData)
1830 {
1831     std::optional<LayoutUnit> freeSpace = sizingData.freeSpace(direction);
1832     if (!freeSpace
1833         || freeSpace.value() <= 0
1834         || (direction == ForColumns && style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorGrid()) != ContentDistributionStretch)
1835         || (direction == ForRows && style().resolvedAlignContentDistribution(contentAlignmentNormalBehaviorGrid()) != ContentDistributionStretch))
1836         return;
1837
1838     // Spec defines auto-sized tracks as the ones with an 'auto' max-sizing function.
1839     Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
1840     Vector<unsigned> autoSizedTracksIndex;
1841     for (unsigned i = 0; i < tracks.size(); ++i) {
1842         const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData);
1843         if (trackSize.hasAutoMaxTrackBreadth())
1844             autoSizedTracksIndex.append(i);
1845     }
1846
1847     unsigned numberOfAutoSizedTracks = autoSizedTracksIndex.size();
1848     if (numberOfAutoSizedTracks < 1)
1849         return;
1850
1851     LayoutUnit sizeToIncrease = freeSpace.value() / numberOfAutoSizedTracks;
1852     for (const auto& trackIndex : autoSizedTracksIndex) {
1853         auto& track = tracks[trackIndex];
1854         track.setBaseSize(track.baseSize() + sizeToIncrease);
1855     }
1856     sizingData.setFreeSpace(direction, std::optional<LayoutUnit>(0));
1857 }
1858
1859 void RenderGrid::layoutGridItems(GridSizingData& sizingData)
1860 {
1861     ASSERT(sizingData.sizingOperation == TrackSizing);
1862     populateGridPositionsForDirection(sizingData, ForColumns);
1863     populateGridPositionsForDirection(sizingData, ForRows);
1864
1865     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1866         if (child->isOutOfFlowPositioned()) {
1867             prepareChildForPositionedLayout(*child);
1868             continue;
1869         }
1870
1871         // Because the grid area cannot be styled, we don't need to adjust
1872         // the grid breadth to account for 'box-sizing'.
1873         std::optional<LayoutUnit> oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
1874         std::optional<LayoutUnit> oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();
1875
1876         LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForColumns, sizingData);
1877         LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows, sizingData);
1878         if (!oldOverrideContainingBlockContentLogicalWidth || oldOverrideContainingBlockContentLogicalWidth.value() != overrideContainingBlockContentLogicalWidth
1879             || ((!oldOverrideContainingBlockContentLogicalHeight || oldOverrideContainingBlockContentLogicalHeight.value() != overrideContainingBlockContentLogicalHeight)
1880                 && child->hasRelativeLogicalHeight()))
1881             child->setNeedsLayout(MarkOnlyThis);
1882
1883         child->setOverrideContainingBlockContentLogicalWidth(overrideContainingBlockContentLogicalWidth);
1884         child->setOverrideContainingBlockContentLogicalHeight(overrideContainingBlockContentLogicalHeight);
1885
1886         LayoutRect oldChildRect = child->frameRect();
1887
1888         // Stretching logic might force a child layout, so we need to run it before the layoutIfNeeded
1889         // call to avoid unnecessary relayouts. This might imply that child margins, needed to correctly
1890         // determine the available space before stretching, are not set yet.
1891         applyStretchAlignmentToChildIfNeeded(*child);
1892
1893         child->layoutIfNeeded();
1894
1895         // We need pending layouts to be done in order to compute auto-margins properly.
1896         updateAutoMarginsInColumnAxisIfNeeded(*child);
1897         updateAutoMarginsInRowAxisIfNeeded(*child);
1898
1899         child->setLogicalLocation(findChildLogicalPosition(*child, sizingData));
1900
1901         // If the child moved, we have to repaint it as well as any floating/positioned
1902         // descendants. An exception is if we need a layout. In this case, we know we're going to
1903         // repaint ourselves (and the child) anyway.
1904         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
1905             child->repaintDuringLayoutIfMoved(oldChildRect);
1906     }
1907 }
1908
1909 void RenderGrid::prepareChildForPositionedLayout(RenderBox& child)
1910 {
1911     ASSERT(child.isOutOfFlowPositioned());
1912     child.containingBlock()->insertPositionedObject(child);
1913
1914     RenderLayer* childLayer = child.layer();
1915     childLayer->setStaticInlinePosition(borderAndPaddingStart());
1916     childLayer->setStaticBlockPosition(borderAndPaddingBefore());
1917 }
1918
1919 void RenderGrid::layoutPositionedObject(RenderBox& child, bool relayoutChildren, bool fixedPositionObjectsOnly)
1920 {
1921     // FIXME: Properly support orthogonal writing mode.
1922     if (!isOrthogonalChild(child)) {
1923         LayoutUnit columnOffset = LayoutUnit();
1924         LayoutUnit columnBreadth = LayoutUnit();
1925         offsetAndBreadthForPositionedChild(child, ForColumns, columnOffset, columnBreadth);
1926         LayoutUnit rowOffset = LayoutUnit();
1927         LayoutUnit rowBreadth = LayoutUnit();
1928         offsetAndBreadthForPositionedChild(child, ForRows, rowOffset, rowBreadth);
1929
1930         child.setOverrideContainingBlockContentLogicalWidth(columnBreadth);
1931         child.setOverrideContainingBlockContentLogicalHeight(rowBreadth);
1932         child.setExtraInlineOffset(columnOffset);
1933         child.setExtraBlockOffset(rowOffset);
1934
1935         if (child.parent() == this) {
1936             auto& childLayer = *child.layer();
1937             childLayer.setStaticInlinePosition(borderStart() + columnOffset);
1938             childLayer.setStaticBlockPosition(borderBefore() + rowOffset);
1939         }
1940     }
1941
1942     RenderBlock::layoutPositionedObject(child, relayoutChildren, fixedPositionObjectsOnly);
1943 }
1944
1945 void RenderGrid::offsetAndBreadthForPositionedChild(const RenderBox& child, GridTrackSizingDirection direction, LayoutUnit& offset, LayoutUnit& breadth)
1946 {
1947     ASSERT(!isOrthogonalChild(child));
1948     bool isRowAxis = direction == ForColumns;
1949
1950     unsigned autoRepeatCount = m_grid.autoRepeatTracks(direction);
1951     GridSpan positions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), child, direction, autoRepeatCount);
1952     if (positions.isIndefinite()) {
1953         offset = LayoutUnit();
1954         breadth = isRowAxis ? clientLogicalWidth() : clientLogicalHeight();
1955         return;
1956     }
1957
1958     // For positioned items we cannot use GridSpan::translate() because we could end up with negative values, as the positioned items do not create implicit tracks per spec.
1959     int smallestStart = std::abs(m_grid.smallestTrackStart(direction));
1960     int startLine = positions.untranslatedStartLine() + smallestStart;
1961     int endLine = positions.untranslatedEndLine() + smallestStart;
1962
1963     GridPosition startPosition = isRowAxis ? child.style().gridItemColumnStart() : child.style().gridItemRowStart();
1964     GridPosition endPosition = isRowAxis ? child.style().gridItemColumnEnd() : child.style().gridItemRowEnd();
1965     int lastLine = numTracks(direction, m_grid);
1966
1967     bool startIsAuto = startPosition.isAuto()
1968         || (startPosition.isNamedGridArea() && !NamedLineCollection::isValidNamedLineOrArea(startPosition.namedGridLine(), style(), (direction == ForColumns) ? ColumnStartSide : RowStartSide))
1969         || (startLine < 0)
1970         || (startLine > lastLine);
1971     bool endIsAuto = endPosition.isAuto()
1972         || (endPosition.isNamedGridArea() && !NamedLineCollection::isValidNamedLineOrArea(endPosition.namedGridLine(), style(), (direction == ForColumns) ? ColumnEndSide : RowEndSide))
1973         || (endLine < 0)
1974         || (endLine > lastLine);
1975
1976     // We're normalizing the positions to avoid issues with RTL (as they're stored in the same order than LTR but adding an offset).
1977     LayoutUnit start;
1978     if (!startIsAuto) {
1979         if (isRowAxis) {
1980             if (style().isLeftToRightDirection())
1981                 start = m_columnPositions[startLine] - borderLogicalLeft();
1982             else
1983                 start = logicalWidth() - translateRTLCoordinate(m_columnPositions[startLine]) - borderLogicalRight();
1984         } else
1985             start = m_rowPositions[startLine] - borderBefore();
1986     }
1987
1988     LayoutUnit end = isRowAxis ? clientLogicalWidth() : clientLogicalHeight();
1989     if (!endIsAuto) {
1990         if (isRowAxis) {
1991             if (style().isLeftToRightDirection())
1992                 end = m_columnPositions[endLine] - borderLogicalLeft();
1993             else
1994                 end = logicalWidth() - translateRTLCoordinate(m_columnPositions[endLine]) - borderLogicalRight();
1995         } else
1996             end = m_rowPositions[endLine] - borderBefore();
1997
1998         // These vectors store line positions including gaps, but we shouldn't consider them for the edges of the grid.
1999         if (endLine > 0 && endLine < lastLine) {
2000             ASSERT(!m_grid.needsItemsPlacement());
2001             end -= guttersSize(m_grid, direction, endLine - 1, 2);
2002             end -= isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
2003         }
2004     }
2005
2006     breadth = end - start;
2007     offset = start;
2008
2009     if (isRowAxis && !style().isLeftToRightDirection() && !child.style().hasStaticInlinePosition(child.isHorizontalWritingMode())) {
2010         // If the child doesn't have a static inline position (i.e. "left" and/or "right" aren't "auto",
2011         // we need to calculate the offset from the left (even if we're in RTL).
2012         if (endIsAuto)
2013             offset = LayoutUnit();
2014         else {
2015             offset = translateRTLCoordinate(m_columnPositions[endLine]) - borderLogicalLeft();
2016
2017             if (endLine > 0 && endLine < lastLine) {
2018                 ASSERT(!m_grid.needsItemsPlacement());
2019                 offset += guttersSize(m_grid, direction, endLine - 1, 2);
2020                 offset += isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
2021             }
2022         }
2023     }
2024 }
2025
2026 LayoutUnit RenderGrid::assumedRowsSizeForOrthogonalChild(const RenderBox& child, const GridSizingData& sizingData) const
2027 {
2028     ASSERT(isOrthogonalChild(child));
2029     const GridSpan& span = sizingData.grid().gridItemSpan(child, ForRows);
2030     LayoutUnit gridAreaSize;
2031     bool gridAreaIsIndefinite = false;
2032     LayoutUnit containingBlockAvailableSize = containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
2033     for (auto trackPosition : span) {
2034         GridLength maxTrackSize = gridTrackSize(ForRows, trackPosition, sizingData).maxTrackBreadth();
2035         if (maxTrackSize.isContentSized() || maxTrackSize.isFlex())
2036             gridAreaIsIndefinite = true;
2037         else
2038             gridAreaSize += valueForLength(maxTrackSize.length(), containingBlockAvailableSize);
2039     }
2040
2041     gridAreaSize += guttersSize(sizingData.grid(), ForRows, span.startLine(), span.integerSpan());
2042
2043     return gridAreaIsIndefinite ? std::max(child.maxPreferredLogicalWidth(), gridAreaSize) : gridAreaSize;
2044 }
2045
2046 LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox& child, GridTrackSizingDirection direction, const GridSizingData& sizingData) const
2047 {
2048     // To determine the column track's size based on an orthogonal grid item we need it's logical height, which
2049     // may depend on the row track's size. It's possible that the row tracks sizing logic has not been performed yet,
2050     // so we will need to do an estimation.
2051     if (direction == ForRows && sizingData.sizingState == GridSizingData::ColumnSizingFirstIteration)
2052         return assumedRowsSizeForOrthogonalChild(child, sizingData);
2053
2054     const Vector<GridTrack>& tracks = direction == ForColumns ? sizingData.columnTracks : sizingData.rowTracks;
2055     const GridSpan& span = sizingData.grid().gridItemSpan(child, direction);
2056     LayoutUnit gridAreaBreadth = 0;
2057     for (auto trackPosition : span)
2058         gridAreaBreadth += tracks[trackPosition].baseSize();
2059
2060     gridAreaBreadth += guttersSize(sizingData.grid(), direction, span.startLine(), span.integerSpan());
2061
2062     return gridAreaBreadth;
2063 }
2064
2065 LayoutUnit RenderGrid::gridAreaBreadthForChildIncludingAlignmentOffsets(const RenderBox& child, GridTrackSizingDirection direction, const GridSizingData& sizingData) const
2066 {
2067     // We need the cached value when available because Content Distribution alignment properties
2068     // may have some influence in the final grid area breadth.
2069     const auto& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
2070     const auto& span = sizingData.grid().gridItemSpan(child, direction);
2071     const auto& linePositions = (direction == ForColumns) ? m_columnPositions : m_rowPositions;
2072
2073     LayoutUnit initialTrackPosition = linePositions[span.startLine()];
2074     LayoutUnit finalTrackPosition = linePositions[span.endLine() - 1];
2075
2076     // Track Positions vector stores the 'start' grid line of each track, so we have to add last track's baseSize.
2077     return finalTrackPosition - initialTrackPosition + tracks[span.endLine() - 1].baseSize();
2078 }
2079
2080 void RenderGrid::populateGridPositionsForDirection(GridSizingData& sizingData, GridTrackSizingDirection direction)
2081 {
2082     // Since we add alignment offsets and track gutters, grid lines are not always adjacent. Hence we will have to
2083     // assume from now on that we just store positions of the initial grid lines of each track,
2084     // except the last one, which is the only one considered as a final grid line of a track.
2085
2086     // The grid container's frame elements (border, padding and <content-position> offset) are sensible to the
2087     // inline-axis flow direction. However, column lines positions are 'direction' unaware. This simplification
2088     // allows us to use the same indexes to identify the columns independently on the inline-axis direction.
2089     bool isRowAxis = direction == ForColumns;
2090     auto& tracks = isRowAxis ? sizingData.columnTracks : sizingData.rowTracks;
2091     unsigned numberOfTracks = tracks.size();
2092     unsigned numberOfLines = numberOfTracks + 1;
2093     unsigned lastLine = numberOfLines - 1;
2094
2095     ContentAlignmentData offset = computeContentPositionAndDistributionOffset(direction, sizingData.freeSpace(direction).value(), numberOfTracks);
2096     auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
2097     positions.resize(numberOfLines);
2098     auto borderAndPadding = isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore();
2099     positions[0] = borderAndPadding + offset.positionOffset;
2100     Grid& grid = sizingData.grid();
2101     if (numberOfLines > 1) {
2102         // If we have collapsed tracks we just ignore gaps here and add them later as we might not
2103         // compute the gap between two consecutive tracks without examining the surrounding ones.
2104         bool hasCollapsedTracks = grid.hasAutoRepeatEmptyTracks(direction);
2105         LayoutUnit gap = !hasCollapsedTracks ? gridGapForDirection(direction) : LayoutUnit();
2106         unsigned nextToLastLine = numberOfLines - 2;
2107         for (unsigned i = 0; i < nextToLastLine; ++i)
2108             positions[i + 1] = positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap;
2109         positions[lastLine] = positions[nextToLastLine] + tracks[nextToLastLine].baseSize();
2110
2111         // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to collapse (they
2112         // coincide exactly) except on the edges of the grid where they become 0.
2113         if (hasCollapsedTracks) {
2114             gap = gridGapForDirection(direction);
2115             unsigned remainingEmptyTracks = grid.autoRepeatEmptyTracks(direction)->size();
2116             LayoutUnit gapAccumulator;
2117             for (unsigned i = 1; i < lastLine; ++i) {
2118                 if (grid.isEmptyAutoRepeatTrack(direction, i - 1))
2119                     --remainingEmptyTracks;
2120                 else {
2121                     // Add gap between consecutive non empty tracks. Add it also just once for an
2122                     // arbitrary number of empty tracks between two non empty ones.
2123                     bool allRemainingTracksAreEmpty = remainingEmptyTracks == (lastLine - i);
2124                     if (!allRemainingTracksAreEmpty || !grid.isEmptyAutoRepeatTrack(direction, i))
2125                         gapAccumulator += gap;
2126                 }
2127                 positions[i] += gapAccumulator;
2128             }
2129             positions[lastLine] += gapAccumulator;
2130         }
2131     }
2132     auto& offsetBetweenTracks = isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
2133     offsetBetweenTracks = offset.distributionOffset;
2134 }
2135
2136 static LayoutUnit computeOverflowAlignmentOffset(OverflowAlignment overflow, LayoutUnit trackSize, LayoutUnit childSize)
2137 {
2138     LayoutUnit offset = trackSize - childSize;
2139     switch (overflow) {
2140     case OverflowAlignmentSafe:
2141         // If overflow is 'safe', we have to make sure we don't overflow the 'start'
2142         // edge (potentially cause some data loss as the overflow is unreachable).
2143         return std::max<LayoutUnit>(0, offset);
2144     case OverflowAlignmentUnsafe:
2145     case OverflowAlignmentDefault:
2146         // If we overflow our alignment container and overflow is 'true' (default), we
2147         // ignore the overflow and just return the value regardless (which may cause data
2148         // loss as we overflow the 'start' edge).
2149         return offset;
2150     }
2151
2152     ASSERT_NOT_REACHED();
2153     return 0;
2154 }
2155
2156 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2157 bool RenderGrid::needToStretchChildLogicalHeight(const RenderBox& child) const
2158 {
2159     if (child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehavior).position() != ItemPositionStretch)
2160         return false;
2161
2162     return isHorizontalWritingMode() && child.style().height().isAuto();
2163 }
2164
2165 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2166 LayoutUnit RenderGrid::marginLogicalHeightForChild(const RenderBox& child) const
2167 {
2168     return isHorizontalWritingMode() ? child.verticalMarginExtent() : child.horizontalMarginExtent();
2169 }
2170
2171 LayoutUnit RenderGrid::computeMarginLogicalSizeForChild(GridTrackSizingDirection direction, const RenderBox& child) const
2172 {
2173     if (!child.style().hasMargin())
2174         return 0;
2175
2176     LayoutUnit marginStart;
2177     LayoutUnit marginEnd;
2178     if (direction == ForColumns)
2179         child.computeInlineDirectionMargins(*this, child.containingBlockLogicalWidthForContentInRegion(nullptr), child.logicalWidth(), marginStart, marginEnd);
2180     else
2181         child.computeBlockDirectionMargins(*this, marginStart, marginEnd);
2182
2183     return marginStart + marginEnd;
2184 }
2185
2186 LayoutUnit RenderGrid::availableAlignmentSpaceForChildBeforeStretching(LayoutUnit gridAreaBreadthForChild, const RenderBox& child) const
2187 {
2188     // Because we want to avoid multiple layouts, stretching logic might be performed before
2189     // children are laid out, so we can't use the child cached values. Hence, we need to
2190     // compute margins in order to determine the available height before stretching.
2191     return gridAreaBreadthForChild - (child.needsLayout() ? computeMarginLogicalSizeForChild(ForRows, child) : marginLogicalHeightForChild(child));
2192 }
2193
2194 StyleSelfAlignmentData RenderGrid::alignSelfForChild(const RenderBox& child) const
2195 {
2196     return child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehavior);
2197 }
2198
2199 StyleSelfAlignmentData RenderGrid::justifySelfForChild(const RenderBox& child) const
2200 {
2201     return child.style().resolvedJustifySelf(style(), selfAlignmentNormalBehavior);
2202 }
2203
2204 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2205 void RenderGrid::applyStretchAlignmentToChildIfNeeded(RenderBox& child)
2206 {
2207     ASSERT(child.overrideContainingBlockContentLogicalHeight());
2208
2209     // We clear height override values because we will decide now whether it's allowed or
2210     // not, evaluating the conditions which might have changed since the old values were set.
2211     child.clearOverrideLogicalContentHeight();
2212
2213     GridTrackSizingDirection childBlockDirection = flowAwareDirectionForChild(child, ForRows);
2214     bool blockFlowIsColumnAxis = childBlockDirection == ForRows;
2215     bool allowedToStretchChildBlockSize = blockFlowIsColumnAxis ? allowedToStretchChildAlongColumnAxis(child) : allowedToStretchChildAlongRowAxis(child);
2216     if (allowedToStretchChildBlockSize) {
2217         LayoutUnit stretchedLogicalHeight = availableAlignmentSpaceForChildBeforeStretching(overrideContainingBlockContentSizeForChild(child, childBlockDirection).value(), child);
2218         LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(stretchedLogicalHeight, LayoutUnit(-1));
2219         child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight());
2220         if (desiredLogicalHeight != child.logicalHeight()) {
2221             // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
2222             child.setLogicalHeight(LayoutUnit());
2223             child.setNeedsLayout();
2224         }
2225     }
2226 }
2227
2228 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2229 bool RenderGrid::hasAutoMarginsInColumnAxis(const RenderBox& child) const
2230 {
2231     if (isHorizontalWritingMode())
2232         return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
2233     return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
2234 }
2235
2236 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2237 bool RenderGrid::hasAutoMarginsInRowAxis(const RenderBox& child) const
2238 {
2239     if (isHorizontalWritingMode())
2240         return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
2241     return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
2242 }
2243
2244 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2245 void RenderGrid::updateAutoMarginsInRowAxisIfNeeded(RenderBox& child)
2246 {
2247     ASSERT(!child.isOutOfFlowPositioned());
2248
2249     LayoutUnit availableAlignmentSpace = child.overrideContainingBlockContentLogicalWidth().value() - child.logicalWidth() - child.marginLogicalWidth();
2250     if (availableAlignmentSpace <= 0)
2251         return;
2252
2253     const RenderStyle& parentStyle = style();
2254     Length marginStart = child.style().marginStartUsing(&parentStyle);
2255     Length marginEnd = child.style().marginEndUsing(&parentStyle);
2256     if (marginStart.isAuto() && marginEnd.isAuto()) {
2257         child.setMarginStart(availableAlignmentSpace / 2, &parentStyle);
2258         child.setMarginEnd(availableAlignmentSpace / 2, &parentStyle);
2259     } else if (marginStart.isAuto()) {
2260         child.setMarginStart(availableAlignmentSpace, &parentStyle);
2261     } else if (marginEnd.isAuto()) {
2262         child.setMarginEnd(availableAlignmentSpace, &parentStyle);
2263     }
2264 }
2265
2266 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
2267 void RenderGrid::updateAutoMarginsInColumnAxisIfNeeded(RenderBox& child)
2268 {
2269     ASSERT(!child.isOutOfFlowPositioned());
2270
2271     LayoutUnit availableAlignmentSpace = child.overrideContainingBlockContentLogicalHeight().value() - child.logicalHeight() - child.marginLogicalHeight();
2272     if (availableAlignmentSpace <= 0)
2273         return;
2274
2275     const RenderStyle& parentStyle = style();
2276     Length marginBefore = child.style().marginBeforeUsing(&parentStyle);
2277     Length marginAfter = child.style().marginAfterUsing(&parentStyle);
2278     if (marginBefore.isAuto() && marginAfter.isAuto()) {
2279         child.setMarginBefore(availableAlignmentSpace / 2, &parentStyle);
2280         child.setMarginAfter(availableAlignmentSpace / 2, &parentStyle);
2281     } else if (marginBefore.isAuto()) {
2282         child.setMarginBefore(availableAlignmentSpace, &parentStyle);
2283     } else if (marginAfter.isAuto()) {
2284         child.setMarginAfter(availableAlignmentSpace, &parentStyle);
2285     }
2286 }
2287
2288 // FIXME: This logic could be refactored somehow and defined in RenderBox.
2289 static int synthesizedBaselineFromBorderBox(const RenderBox& box, LineDirectionMode direction)
2290 {
2291     return (direction == HorizontalLine ? box.size().height() : box.size().width()).toInt();
2292 }
2293
2294 bool RenderGrid::isInlineBaselineAlignedChild(const RenderBox& child) const
2295 {
2296     return alignSelfForChild(child).position() == ItemPositionBaseline && !isOrthogonalChild(child) && !hasAutoMarginsInColumnAxis(child);
2297 }
2298
2299 // FIXME: This logic is shared by RenderFlexibleBox, so it might be refactored somehow.
2300 int RenderGrid::baselinePosition(FontBaseline, bool, LineDirectionMode direction, LinePositionMode mode) const
2301 {
2302 #if ENABLE(ASSERT)
2303     ASSERT(mode == PositionOnContainingLine);
2304 #else
2305     UNUSED_PARAM(mode);
2306 #endif
2307     int baseline = firstLineBaseline().value_or(synthesizedBaselineFromBorderBox(*this, direction));
2308
2309     int marginSize = direction == HorizontalLine ? verticalMarginExtent() : horizontalMarginExtent();
2310     return baseline + marginSize;
2311 }
2312
2313 std::optional<int> RenderGrid::firstLineBaseline() const
2314 {
2315     if (isWritingModeRoot() || !m_grid.hasGridItems())
2316         return std::nullopt;
2317
2318     const RenderBox* baselineChild = nullptr;
2319     // Finding the first grid item in grid order.
2320     unsigned numColumns = m_grid.numTracks(ForColumns);
2321     for (size_t column = 0; column < numColumns; column++) {
2322         for (const auto* child : m_grid.cell(0, column)) {
2323             // If an item participates in baseline alignment, we select such item.
2324             if (isInlineBaselineAlignedChild(*child)) {
2325                 // FIXME: self-baseline and content-baseline alignment not implemented yet.
2326                 baselineChild = child;
2327                 break;
2328             }
2329             if (!baselineChild)
2330                 baselineChild = child;
2331         }
2332     }
2333
2334     if (!baselineChild)
2335         return std::nullopt;
2336
2337     auto baseline = isOrthogonalChild(*baselineChild) ? std::nullopt : baselineChild->firstLineBaseline();
2338     // We take border-box's bottom if no valid baseline.
2339     if (!baseline) {
2340         // FIXME: We should pass |direction| into firstLineBaseline and stop bailing out if we're a writing
2341         // mode root. This would also fix some cases where the grid is orthogonal to its container.
2342         LineDirectionMode direction = isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
2343         return synthesizedBaselineFromBorderBox(*baselineChild, direction) + baselineChild->logicalTop().toInt();
2344     }
2345     return baseline.value() + baselineChild->logicalTop().toInt();
2346 }
2347
2348 std::optional<int> RenderGrid::inlineBlockBaseline(LineDirectionMode direction) const
2349 {
2350     if (std::optional<int> baseline = firstLineBaseline())
2351         return baseline;
2352
2353     int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
2354     return synthesizedBaselineFromBorderBox(*this, direction) + marginAscent;
2355 }
2356
2357 GridAxisPosition RenderGrid::columnAxisPositionForChild(const RenderBox& child) const
2358 {
2359     bool hasSameWritingMode = child.style().writingMode() == style().writingMode();
2360     bool childIsLTR = child.style().isLeftToRightDirection();
2361
2362     switch (child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehavior).position()) {
2363     case ItemPositionSelfStart:
2364         // FIXME: Should we implement this logic in a generic utility function ?
2365         // Aligns the alignment subject to be flush with the edge of the alignment container
2366         // corresponding to the alignment subject's 'start' side in the column axis.
2367         if (isOrthogonalChild(child)) {
2368             // If orthogonal writing-modes, self-start will be based on the child's inline-axis
2369             // direction (inline-start), because it's the one parallel to the column axis.
2370             if (style().isFlippedBlocksWritingMode())
2371                 return childIsLTR ? GridAxisEnd : GridAxisStart;
2372             return childIsLTR ? GridAxisStart : GridAxisEnd;
2373         }
2374         // self-start is based on the child's block-flow direction. That's why we need to check against the grid container's block-flow direction.
2375         return hasSameWritingMode ? GridAxisStart : GridAxisEnd;
2376     case ItemPositionSelfEnd:
2377         // FIXME: Should we implement this logic in a generic utility function ?
2378         // Aligns the alignment subject to be flush with the edge of the alignment container
2379         // corresponding to the alignment subject's 'end' side in the column axis.
2380         if (isOrthogonalChild(child)) {
2381             // If orthogonal writing-modes, self-end will be based on the child's inline-axis
2382             // direction, (inline-end) because it's the one parallel to the column axis.
2383             if (style().isFlippedBlocksWritingMode())
2384                 return childIsLTR ? GridAxisStart : GridAxisEnd;
2385             return childIsLTR ? GridAxisEnd : GridAxisStart;
2386         }
2387         // self-end is based on the child's block-flow direction. That's why we need to check against the grid container's block-flow direction.
2388         return hasSameWritingMode ? GridAxisEnd : GridAxisStart;
2389     case ItemPositionLeft:
2390         // Aligns the alignment subject to be flush with the alignment container's 'line-left' edge.
2391         // The alignment axis (column axis) is always orthogonal to the inline axis, hence this value behaves as 'start'.
2392         return GridAxisStart;
2393     case ItemPositionRight:
2394         // Aligns the alignment subject to be flush with the alignment container's 'line-right' edge.
2395         // The alignment axis (column axis) is always orthogonal to the inline axis, hence this value behaves as 'start'.
2396         return GridAxisStart;
2397     case ItemPositionCenter:
2398         return GridAxisCenter;
2399     case ItemPositionFlexStart: // Only used in flex layout, otherwise equivalent to 'start'.
2400         // Aligns the alignment subject to be flush with the alignment container's 'start' edge (block-start) in the column axis.
2401     case ItemPositionStart:
2402         return GridAxisStart;
2403     case ItemPositionFlexEnd: // Only used in flex layout, otherwise equivalent to 'end'.
2404         // Aligns the alignment subject to be flush with the alignment container's 'end' edge (block-end) in the column axis.
2405     case ItemPositionEnd:
2406         return GridAxisEnd;
2407     case ItemPositionStretch:
2408         return GridAxisStart;
2409     case ItemPositionBaseline:
2410     case ItemPositionLastBaseline:
2411         // FIXME: Implement the previous values. For now, we always 'start' align the child.
2412         return GridAxisStart;
2413     case ItemPositionAuto:
2414     case ItemPositionNormal:
2415         break;
2416     }
2417
2418     ASSERT_NOT_REACHED();
2419     return GridAxisStart;
2420 }
2421
2422 GridAxisPosition RenderGrid::rowAxisPositionForChild(const RenderBox& child) const
2423 {
2424     bool hasSameDirection = child.style().direction() == style().direction();
2425     bool gridIsLTR = style().isLeftToRightDirection();
2426
2427     switch (child.style().resolvedJustifySelf(style(), selfAlignmentNormalBehavior).position()) {
2428     case ItemPositionSelfStart:
2429         // FIXME: Should we implement this logic in a generic utility function ?
2430         // Aligns the alignment subject to be flush with the edge of the alignment container
2431         // corresponding to the alignment subject's 'start' side in the row axis.
2432         if (isOrthogonalChild(child)) {
2433             // If orthogonal writing-modes, self-start will be based on the child's block-axis
2434             // direction, because it's the one parallel to the row axis.
2435             if (child.style().isFlippedBlocksWritingMode())
2436                 return gridIsLTR ? GridAxisEnd : GridAxisStart;
2437             return gridIsLTR ? GridAxisStart : GridAxisEnd;
2438         }
2439         // self-start is based on the child's inline-flow direction. That's why we need to check against the grid container's direction.
2440         return hasSameDirection ? GridAxisStart : GridAxisEnd;
2441     case ItemPositionSelfEnd:
2442         // FIXME: Should we implement this logic in a generic utility function ?
2443         // Aligns the alignment subject to be flush with the edge of the alignment container
2444         // corresponding to the alignment subject's 'end' side in the row axis.
2445         if (isOrthogonalChild(child)) {
2446             // If orthogonal writing-modes, self-end will be based on the child's block-axis
2447             // direction, because it's the one parallel to the row axis.
2448             if (child.style().isFlippedBlocksWritingMode())
2449                 return gridIsLTR ? GridAxisStart : GridAxisEnd;
2450             return gridIsLTR ? GridAxisEnd : GridAxisStart;
2451         }
2452         // self-end is based on the child's inline-flow direction. That's why we need to check against the grid container's direction.
2453         return hasSameDirection ? GridAxisEnd : GridAxisStart;
2454     case ItemPositionLeft:
2455         // Aligns the alignment subject to be flush with the alignment container's 'line-left' edge.
2456         // We want the physical 'left' side, so we have to take account, container's inline-flow direction.
2457         return gridIsLTR ? GridAxisStart : GridAxisEnd;
2458     case ItemPositionRight:
2459         // Aligns the alignment subject to be flush with the alignment container's 'line-right' edge.
2460         // We want the physical 'right' side, so we have to take account, container's inline-flow direction.
2461         return gridIsLTR ? GridAxisEnd : GridAxisStart;
2462     case ItemPositionCenter:
2463         return GridAxisCenter;
2464     case ItemPositionFlexStart: // Only used in flex layout, otherwise equivalent to 'start'.
2465         // Aligns the alignment subject to be flush with the alignment container's 'start' edge (inline-start) in the row axis.
2466     case ItemPositionStart:
2467         return GridAxisStart;
2468     case ItemPositionFlexEnd: // Only used in flex layout, otherwise equivalent to 'end'.
2469         // Aligns the alignment subject to be flush with the alignment container's 'end' edge (inline-end) in the row axis.
2470     case ItemPositionEnd:
2471         return GridAxisEnd;
2472     case ItemPositionStretch:
2473         return GridAxisStart;
2474     case ItemPositionBaseline:
2475     case ItemPositionLastBaseline:
2476         // FIXME: Implement the previous values. For now, we always 'start' align the child.
2477         return GridAxisStart;
2478     case ItemPositionAuto:
2479     case ItemPositionNormal:
2480         break;
2481     }
2482
2483     ASSERT_NOT_REACHED();
2484     return GridAxisStart;
2485 }
2486
2487 LayoutUnit RenderGrid::columnAxisOffsetForChild(const RenderBox& child, const GridSizingData& sizingData) const
2488 {
2489     const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows);
2490     unsigned childStartLine = rowsSpan.startLine();
2491     LayoutUnit startOfRow = m_rowPositions[childStartLine];
2492     LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
2493     if (hasAutoMarginsInColumnAxis(child))
2494         return startPosition;
2495     GridAxisPosition axisPosition = columnAxisPositionForChild(child);
2496     switch (axisPosition) {
2497     case GridAxisStart:
2498         return startPosition;
2499     case GridAxisEnd:
2500     case GridAxisCenter: {
2501         unsigned childEndLine = rowsSpan.endLine();
2502         LayoutUnit endOfRow = m_rowPositions[childEndLine];
2503         // m_rowPositions include distribution offset (because of content alignment) and gutters
2504         // so we need to subtract them to get the actual end position for a given row
2505         // (this does not have to be done for the last track as there are no more m_rowPositions after it).
2506         if (childEndLine < m_rowPositions.size() - 1)
2507             endOfRow -= gridGapForDirection(ForRows) + m_offsetBetweenRows;
2508         LayoutUnit columnAxisChildSize = isOrthogonalChild(child) ? child.logicalWidth() + child.marginLogicalWidth() : child.logicalHeight() + child.marginLogicalHeight();
2509         auto overflow = child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehavior).overflow();
2510         LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(overflow, endOfRow - startOfRow, columnAxisChildSize);
2511         return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPosition : offsetFromStartPosition / 2);
2512     }
2513     }
2514
2515     ASSERT_NOT_REACHED();
2516     return 0;
2517 }
2518
2519
2520 LayoutUnit RenderGrid::rowAxisOffsetForChild(const RenderBox& child, const GridSizingData& sizingData) const
2521 {
2522     const GridSpan& columnsSpan = sizingData.grid().gridItemSpan(child, ForColumns);
2523     unsigned childStartLine = columnsSpan.startLine();
2524     LayoutUnit startOfColumn = m_columnPositions[childStartLine];
2525     LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
2526     if (hasAutoMarginsInRowAxis(child))
2527         return startPosition;
2528     GridAxisPosition axisPosition = rowAxisPositionForChild(child);
2529     switch (axisPosition) {
2530     case GridAxisStart:
2531         return startPosition;
2532     case GridAxisEnd:
2533     case GridAxisCenter: {
2534         unsigned childEndLine = columnsSpan.endLine();
2535         LayoutUnit endOfColumn = m_columnPositions[childEndLine];
2536         // m_columnPositions include distribution offset (because of content alignment) and gutters
2537         // so we need to subtract them to get the actual end position for a given column
2538         // (this does not have to be done for the last track as there are no more m_columnPositions after it).
2539         if (childEndLine < m_columnPositions.size() - 1)
2540             endOfColumn -= gridGapForDirection(ForColumns) + m_offsetBetweenColumns;
2541         LayoutUnit rowAxisChildSize = isOrthogonalChild(child) ? child.logicalHeight() + child.marginLogicalHeight() : child.logicalWidth() + child.marginLogicalWidth();
2542         auto overflow = child.style().resolvedJustifySelf(style(), selfAlignmentNormalBehavior).overflow();
2543         LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(overflow, endOfColumn - startOfColumn, rowAxisChildSize);
2544         return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPosition : offsetFromStartPosition / 2);
2545     }
2546     }
2547
2548     ASSERT_NOT_REACHED();
2549     return 0;
2550 }
2551
2552 ContentPosition static resolveContentDistributionFallback(ContentDistributionType distribution)
2553 {
2554     switch (distribution) {
2555     case ContentDistributionSpaceBetween:
2556         return ContentPositionStart;
2557     case ContentDistributionSpaceAround:
2558         return ContentPositionCenter;
2559     case ContentDistributionSpaceEvenly:
2560         return ContentPositionCenter;
2561     case ContentDistributionStretch:
2562         return ContentPositionStart;
2563     case ContentDistributionDefault:
2564         return ContentPositionNormal;
2565     }
2566
2567     ASSERT_NOT_REACHED();
2568     return ContentPositionNormal;
2569 }
2570
2571 static ContentAlignmentData contentDistributionOffset(const LayoutUnit& availableFreeSpace, ContentPosition& fallbackPosition, ContentDistributionType distribution, unsigned numberOfGridTracks)
2572 {
2573     if (distribution != ContentDistributionDefault && fallbackPosition == ContentPositionNormal)
2574         fallbackPosition = resolveContentDistributionFallback(distribution);
2575
2576     if (availableFreeSpace <= 0)
2577         return ContentAlignmentData::defaultOffsets();
2578
2579     LayoutUnit distributionOffset;
2580     switch (distribution) {
2581     case ContentDistributionSpaceBetween:
2582         if (numberOfGridTracks < 2)
2583             return ContentAlignmentData::defaultOffsets();
2584         return {0, availableFreeSpace / (numberOfGridTracks - 1)};
2585     case ContentDistributionSpaceAround:
2586         if (numberOfGridTracks < 1)
2587             return ContentAlignmentData::defaultOffsets();
2588         distributionOffset = availableFreeSpace / numberOfGridTracks;
2589         return {distributionOffset / 2, distributionOffset};
2590     case ContentDistributionSpaceEvenly:
2591         distributionOffset = availableFreeSpace / (numberOfGridTracks + 1);
2592         return {distributionOffset, distributionOffset};
2593     case ContentDistributionStretch:
2594     case ContentDistributionDefault:
2595         return ContentAlignmentData::defaultOffsets();
2596     }
2597
2598     ASSERT_NOT_REACHED();
2599     return ContentAlignmentData::defaultOffsets();
2600 }
2601
2602 ContentAlignmentData RenderGrid::computeContentPositionAndDistributionOffset(GridTrackSizingDirection direction, const LayoutUnit& availableFreeSpace, unsigned numberOfGridTracks) const
2603 {
2604     bool isRowAxis = direction == ForColumns;
2605     auto position = isRowAxis ? style().resolvedJustifyContentPosition(contentAlignmentNormalBehaviorGrid()) : style().resolvedAlignContentPosition(contentAlignmentNormalBehaviorGrid());
2606     auto distribution = isRowAxis ? style().resolvedJustifyContentDistribution(contentAlignmentNormalBehaviorGrid()) : style().resolvedAlignContentDistribution(contentAlignmentNormalBehaviorGrid());
2607     // If <content-distribution> value can't be applied, 'position' will become the associated
2608     // <content-position> fallback value.
2609     auto contentAlignment = contentDistributionOffset(availableFreeSpace, position, distribution, numberOfGridTracks);
2610     if (contentAlignment.isValid())
2611         return contentAlignment;
2612
2613     auto overflow = (isRowAxis ? style().justifyContent() : style().alignContent()).overflow();
2614     if (availableFreeSpace <= 0 && overflow == OverflowAlignmentSafe)
2615         return {0, 0};
2616
2617     switch (position) {
2618     case ContentPositionLeft:
2619         // The align-content's axis is always orthogonal to the inline-axis.
2620         return {0, 0};
2621     case ContentPositionRight:
2622         if (isRowAxis)
2623             return {availableFreeSpace, 0};
2624         // The align-content's axis is always orthogonal to the inline-axis.
2625         return {0, 0};
2626     case ContentPositionCenter:
2627         return {availableFreeSpace / 2, 0};
2628     case ContentPositionFlexEnd: // Only used in flex layout, for other layout, it's equivalent to 'end'.
2629     case ContentPositionEnd:
2630         if (isRowAxis)
2631             return {style().isLeftToRightDirection() ? availableFreeSpace : LayoutUnit(), LayoutUnit()};
2632         return {availableFreeSpace, 0};
2633     case ContentPositionFlexStart: // Only used in flex layout, for other layout, it's equivalent to 'start'.
2634     case ContentPositionStart:
2635         if (isRowAxis)
2636             return {style().isLeftToRightDirection() ? LayoutUnit() : availableFreeSpace, LayoutUnit()};
2637         return {0, 0};
2638     case ContentPositionBaseline:
2639     case ContentPositionLastBaseline:
2640         // FIXME: Implement the previous values. For now, we always 'start' align.
2641         // http://webkit.org/b/145566
2642         if (isRowAxis)
2643             return {style().isLeftToRightDirection() ? LayoutUnit() : availableFreeSpace, LayoutUnit()};
2644         return {0, 0};
2645     case ContentPositionNormal:
2646         break;
2647     }
2648
2649     ASSERT_NOT_REACHED();
2650     return {0, 0};
2651 }
2652
2653 LayoutUnit RenderGrid::translateRTLCoordinate(LayoutUnit coordinate) const
2654 {
2655     ASSERT(!style().isLeftToRightDirection());
2656
2657     LayoutUnit alignmentOffset = m_columnPositions[0];
2658     LayoutUnit rightGridEdgePosition = m_columnPositions[m_columnPositions.size() - 1];
2659     return rightGridEdgePosition + alignmentOffset - coordinate;
2660 }
2661
2662 LayoutPoint RenderGrid::findChildLogicalPosition(const RenderBox& child, const GridSizingData& sizingData) const
2663 {
2664     LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child, sizingData);
2665     LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child, sizingData);
2666     // We stored m_columnPositions's data ignoring the direction, hence we might need now
2667     // to translate positions from RTL to LTR, as it's more convenient for painting.
2668     if (!style().isLeftToRightDirection())
2669         rowAxisOffset = translateRTLCoordinate(rowAxisOffset) - (isOrthogonalChild(child) ? child.logicalHeight()  : child.logicalWidth());
2670
2671     // "In the positioning phase [...] calculations are performed according to the writing mode
2672     // of the containing block of the box establishing the orthogonal flow." However, the
2673     // resulting LayoutPoint will be used in 'setLogicalPosition' in order to set the child's
2674     // logical position, which will only take into account the child's writing-mode.
2675     LayoutPoint childLocation(rowAxisOffset, columnAxisOffset);
2676     return isOrthogonalChild(child) ? childLocation.transposedPoint() : childLocation;
2677 }
2678
2679 unsigned RenderGrid::numTracks(GridTrackSizingDirection direction, const Grid& grid) const
2680 {
2681     // Due to limitations in our internal representation, we cannot know the number of columns from
2682     // m_grid *if* there is no row (because m_grid would be empty). That's why in that case we need
2683     // to get it from the style. Note that we know for sure that there are't any implicit tracks,
2684     // because not having rows implies that there are no "normal" children (out-of-flow children are
2685     // not stored in m_grid).
2686     ASSERT(!grid.needsItemsPlacement());
2687     if (direction == ForRows)
2688         return grid.numTracks(ForRows);
2689
2690     // FIXME: This still requires knowledge about m_grid internals.
2691     return grid.numTracks(ForRows) ? grid.numTracks(ForColumns) : GridPositionsResolver::explicitGridColumnCount(style(), grid.autoRepeatTracks(ForColumns));
2692 }
2693
2694 void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect)
2695 {
2696     ASSERT(!m_grid.needsItemsPlacement());
2697     for (RenderBox* child = m_grid.orderIterator().first(); child; child = m_grid.orderIterator().next())
2698         paintChild(*child, paintInfo, paintOffset, forChild, usePrintRect, PaintAsInlineBlock);
2699 }
2700
2701 const char* RenderGrid::renderName() const
2702 {
2703     if (isFloating())
2704         return "RenderGrid (floating)";
2705     if (isOutOfFlowPositioned())
2706         return "RenderGrid (positioned)";
2707     if (isAnonymous())
2708         return "RenderGrid (generated)";
2709     if (isRelPositioned())
2710         return "RenderGrid (relative positioned)";
2711     return "RenderGrid";
2712 }
2713
2714 } // namespace WebCore