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