Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / rendering / RenderGrid.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2013-2017 Igalia S.L.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "RenderGrid.h"
29
30 #include "GridArea.h"
31 #include "GridPositionsResolver.h"
32 #include "GridTrackSizingAlgorithm.h"
33 #include "LayoutRepainter.h"
34 #include "RenderChildIterator.h"
35 #include "RenderLayer.h"
36 #include "RenderView.h"
37 #include <cstdlib>
38
39 namespace WebCore {
40
41 enum TrackSizeRestriction {
42     AllowInfinity,
43     ForbidInfinity,
44 };
45
46 struct ContentAlignmentData {
47     WTF_MAKE_FAST_ALLOCATED;
48 public:
49     bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; }
50     static ContentAlignmentData defaultOffsets() { return {-1, -1}; }
51
52     LayoutUnit positionOffset;
53     LayoutUnit distributionOffset;
54 };
55
56 RenderGrid::RenderGrid(Element& element, RenderStyle&& style)
57     : RenderBlock(element, WTFMove(style), 0)
58     , m_grid(*this)
59     , m_trackSizingAlgorithm(this, m_grid)
60 {
61     // All of our children must be block level.
62     setChildrenInline(false);
63 }
64
65 RenderGrid::~RenderGrid() = default;
66
67 void RenderGrid::addChild(RenderPtr<RenderObject> newChild, RenderObject* beforeChild)
68 {
69     auto& child = *newChild;
70     RenderBlock::addChild(WTFMove(newChild), beforeChild);
71
72     // Positioned grid items do not take up space or otherwise participate in the layout of the grid,
73     // for that reason we don't need to mark the grid as dirty when they are added.
74     if (child.isOutOfFlowPositioned())
75         return;
76
77     // The grid needs to be recomputed as it might contain auto-placed items that
78     // will change their position.
79     dirtyGrid();
80 }
81
82 RenderPtr<RenderObject> RenderGrid::takeChild(RenderObject& child)
83 {
84     auto takenChild = RenderBlock::takeChild(child);
85
86     // Positioned grid items do not take up space or otherwise participate in the layout of the grid,
87     // for that reason we don't need to mark the grid as dirty when they are removed.
88     if (child.isOutOfFlowPositioned())
89         return takenChild;
90
91     // The grid needs to be recomputed as it might contain auto-placed items that
92     // will change their position.
93     dirtyGrid();
94     return takenChild;
95 }
96
97 StyleSelfAlignmentData RenderGrid::selfAlignmentForChild(GridAxis axis, const RenderBox& child, const RenderStyle* gridStyle) const
98 {
99     return axis == GridRowAxis ? justifySelfForChild(child, gridStyle) : alignSelfForChild(child, gridStyle);
100 }
101
102 bool RenderGrid::selfAlignmentChangedToStretch(GridAxis axis, const RenderStyle& oldStyle, const RenderStyle& newStyle, const RenderBox& child) const
103 {
104     return selfAlignmentForChild(axis, child, &oldStyle).position() != ItemPositionStretch
105         && selfAlignmentForChild(axis, child, &newStyle).position() == ItemPositionStretch;
106 }
107
108 bool RenderGrid::selfAlignmentChangedFromStretch(GridAxis axis, const RenderStyle& oldStyle, const RenderStyle& newStyle, const RenderBox& child) const
109 {
110     return selfAlignmentForChild(axis, child, &oldStyle).position() == ItemPositionStretch
111         && selfAlignmentForChild(axis, child, &newStyle).position() != ItemPositionStretch;
112 }
113
114 void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
115 {
116     RenderBlock::styleDidChange(diff, oldStyle);
117     if (!oldStyle || diff != StyleDifferenceLayout)
118         return;
119
120     const RenderStyle& newStyle = this->style();
121     if (oldStyle->resolvedAlignItems(selfAlignmentNormalBehavior(this)).position() == ItemPositionStretch) {
122         // Style changes on the grid container implying stretching (to-stretch) or
123         // shrinking (from-stretch) require the affected items to be laid out again.
124         // These logic only applies to 'stretch' since the rest of the alignment
125         // values don't change the size of the box.
126         // In any case, the items' overrideSize will be cleared and recomputed (if
127         // necessary)  as part of the Grid layout logic, triggered by this style
128         // change.
129         for (auto& child : childrenOfType<RenderBox>(*this)) {
130             if (child.isOutOfFlowPositioned())
131                 continue;
132             if (selfAlignmentChangedToStretch(GridRowAxis, *oldStyle, newStyle, child)
133                 || selfAlignmentChangedFromStretch(GridRowAxis, *oldStyle, newStyle, child)
134                 || selfAlignmentChangedToStretch(GridColumnAxis, *oldStyle, newStyle, child)
135                 || selfAlignmentChangedFromStretch(GridColumnAxis, *oldStyle, newStyle, child)) {
136                 child.setNeedsLayout();
137             }
138         }
139     }
140
141     if (explicitGridDidResize(*oldStyle) || namedGridLinesDefinitionDidChange(*oldStyle) || oldStyle->gridAutoFlow() != style().gridAutoFlow()
142         || (style().gridAutoRepeatColumns().size() || style().gridAutoRepeatRows().size()))
143         dirtyGrid();
144 }
145
146 bool RenderGrid::explicitGridDidResize(const RenderStyle& oldStyle) const
147 {
148     return oldStyle.gridColumns().size() != style().gridColumns().size()
149         || oldStyle.gridRows().size() != style().gridRows().size()
150         || oldStyle.namedGridAreaColumnCount() != style().namedGridAreaColumnCount()
151         || oldStyle.namedGridAreaRowCount() != style().namedGridAreaRowCount()
152         || oldStyle.gridAutoRepeatColumns().size() != style().gridAutoRepeatColumns().size()
153         || oldStyle.gridAutoRepeatRows().size() != style().gridAutoRepeatRows().size();
154 }
155
156 bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle& oldStyle) const
157 {
158     return oldStyle.namedGridRowLines() != style().namedGridRowLines()
159         || oldStyle.namedGridColumnLines() != style().namedGridColumnLines();
160 }
161
162 // This method optimizes the gutters computation by skiping the available size
163 // call if gaps are fixed size (it's only needed for percentages).
164 std::optional<LayoutUnit> RenderGrid::availableSpaceForGutters(GridTrackSizingDirection direction) const
165 {
166     bool isRowAxis = direction == ForColumns;
167     const Length& gap = isRowAxis ? style().gridColumnGap() : style().gridRowGap();
168     if (!gap.isPercent())
169         return std::nullopt;
170
171     return isRowAxis ? availableLogicalWidth() : availableLogicalHeightForPercentageComputation();
172 }
173
174 LayoutUnit RenderGrid::computeTrackBasedLogicalHeight() const
175 {
176     LayoutUnit logicalHeight;
177
178     auto& allRows = m_trackSizingAlgorithm.tracks(ForRows);
179     for (const auto& row : allRows)
180         logicalHeight += row.baseSize();
181
182     logicalHeight += guttersSize(m_grid, ForRows, 0, allRows.size(), availableSpaceForGutters(ForRows));
183
184     return logicalHeight;
185 }
186
187 void RenderGrid::computeTrackSizesForDefiniteSize(GridTrackSizingDirection direction, LayoutUnit availableSpace)
188 {
189     LayoutUnit totalGuttersSize = guttersSize(m_grid, direction, 0, m_grid.numTracks(direction), availableSpace);
190     LayoutUnit freeSpace = availableSpace - totalGuttersSize;
191
192     m_trackSizingAlgorithm.setup(direction, numTracks(direction, m_grid), TrackSizing, availableSpace, freeSpace);
193     m_trackSizingAlgorithm.run();
194
195     ASSERT(m_trackSizingAlgorithm.tracksAreWiderThanMinTrackBreadth());
196 }
197
198 void RenderGrid::repeatTracksSizingIfNeeded(LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows)
199 {
200     // In orthogonal flow cases column track's size is determined by using the computed
201     // row track's size, which it was estimated during the first cycle of the sizing
202     // algorithm. Hence we need to repeat computeUsedBreadthOfGridTracks for both,
203     // columns and rows, to determine the final values.
204     // TODO (lajava): orthogonal flows is just one of the cases which may require
205     // a new cycle of the sizing algorithm; there may be more. In addition, not all the
206     // cases with orthogonal flows require this extra cycle; we need a more specific
207     // condition to detect whether child's min-content contribution has changed or not.
208     if (m_grid.hasAnyOrthogonalGridItem()) {
209         computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
210         computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows);
211     }
212 }
213
214 bool RenderGrid::canPerformSimplifiedLayout() const
215 {
216     // We cannot perform a simplified layout if we need to position the items and we have some
217     // positioned items to be laid out.
218     if (m_grid.needsItemsPlacement() && posChildNeedsLayout())
219         return false;
220
221     return RenderBlock::canPerformSimplifiedLayout();
222 }
223
224 void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
225 {
226     ASSERT(needsLayout());
227
228     if (!relayoutChildren && simplifiedLayout())
229         return;
230
231     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
232     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
233
234     preparePaginationBeforeBlockLayout(relayoutChildren);
235
236     LayoutSize previousSize = size();
237     // FIXME: We should use RenderBlock::hasDefiniteLogicalHeight() but it does not work for positioned stuff.
238     // FIXME: Consider caching the hasDefiniteLogicalHeight value throughout the layout.
239     bool hasDefiniteLogicalHeight = hasOverrideLogicalContentHeight() || computeContentLogicalHeight(MainOrPreferredSize, style().logicalHeight(), std::nullopt);
240
241     // We need to clear both own and containingBlock override sizes of orthogonal items to ensure we get the
242     // same result when grid's intrinsic size is computed again in the updateLogicalWidth call bellow.
243     if (sizesLogicalWidthToFitContent(MaxSize) || style().logicalWidth().isIntrinsicOrAuto()) {
244         for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
245             if (child->isOutOfFlowPositioned() || !isOrthogonalChild(*child))
246                 continue;
247             child->clearOverrideSize();
248             child->clearContainingBlockOverrideSize();
249             child->setNeedsLayout();
250             child->layoutIfNeeded();
251         }
252     }
253
254     setLogicalHeight(0);
255     updateLogicalWidth();
256
257     // Fieldsets need to find their legend and position it inside the border of the object.
258     // The legend then gets skipped during normal layout. The same is true for ruby text.
259     // It doesn't get included in the normal layout process but is instead skipped.
260     layoutExcludedChildren(relayoutChildren);
261
262     LayoutUnit availableSpaceForColumns = availableLogicalWidth();
263     placeItemsOnGrid(m_grid, availableSpaceForColumns);
264
265     // At this point the logical width is always definite as the above call to updateLogicalWidth()
266     // properly resolves intrinsic sizes. We cannot do the same for heights though because many code
267     // paths inside updateLogicalHeight() require a previous call to setLogicalHeight() to resolve
268     // heights properly (like for positioned items for example).
269     computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
270
271     if (!hasDefiniteLogicalHeight) {
272         m_minContentHeight = LayoutUnit();
273         m_maxContentHeight = LayoutUnit();
274         computeTrackSizesForIndefiniteSize(m_trackSizingAlgorithm, ForRows, m_grid, *m_minContentHeight, *m_maxContentHeight);
275         // FIXME: This should be really added to the intrinsic height in RenderBox::computeContentAndScrollbarLogicalHeightUsing().
276         // Remove this when that is fixed.
277         ASSERT(m_minContentHeight);
278         ASSERT(m_maxContentHeight);
279         LayoutUnit scrollbarHeight = scrollbarLogicalHeight();
280         *m_minContentHeight += scrollbarHeight;
281         *m_maxContentHeight += scrollbarHeight;
282     } else
283         computeTrackSizesForDefiniteSize(ForRows, availableLogicalHeight(ExcludeMarginBorderPadding));
284     LayoutUnit trackBasedLogicalHeight = computeTrackBasedLogicalHeight() + borderAndPaddingLogicalHeight() + scrollbarLogicalHeight();
285     setLogicalHeight(trackBasedLogicalHeight);
286
287     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
288     updateLogicalHeight();
289
290     // Once grid's indefinite height is resolved, we can compute the
291     // available free space for Content Alignment.
292     if (!hasDefiniteLogicalHeight)
293         m_trackSizingAlgorithm.setFreeSpace(ForRows, logicalHeight() - trackBasedLogicalHeight);
294
295     // 3- If the min-content contribution of any grid items have changed based on the row
296     // sizes calculated in step 2, steps 1 and 2 are repeated with the new min-content
297     // contribution (once only).
298     repeatTracksSizingIfNeeded(availableSpaceForColumns, contentLogicalHeight());
299
300     // Grid container should have the minimum height of a line if it's editable. That does not affect track sizing though.
301     if (hasLineIfEmpty()) {
302         LayoutUnit minHeightForEmptyLine = borderAndPaddingLogicalHeight()
303             + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)
304             + scrollbarLogicalHeight();
305         setLogicalHeight(std::max(logicalHeight(), minHeightForEmptyLine));
306     }
307
308     layoutGridItems();
309     m_trackSizingAlgorithm.reset();
310
311     if (size() != previousSize)
312         relayoutChildren = true;
313
314     layoutPositionedObjects(relayoutChildren || isDocumentElementRenderer());
315
316     computeOverflow(oldClientAfterEdge);
317     statePusher.pop();
318
319     updateLayerTransform();
320
321     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
322     // we overflow or not.
323     updateScrollInfoAfterLayout();
324
325     repainter.repaintAfterLayout();
326
327     clearNeedsLayout();
328 }
329
330 LayoutUnit RenderGrid::gridGap(GridTrackSizingDirection direction, std::optional<LayoutUnit> availableSize) const
331 {
332     const Length& gap = direction == ForColumns ? style().gridColumnGap() : style().gridRowGap();
333     return valueForLength(gap, availableSize.value_or(0));
334 }
335
336 LayoutUnit RenderGrid::gridGap(GridTrackSizingDirection direction) const
337 {
338     return gridGap(direction, availableSpaceForGutters(direction));
339 }
340
341 LayoutUnit RenderGrid::guttersSize(const Grid& grid, GridTrackSizingDirection direction, unsigned startLine, unsigned span, std::optional<LayoutUnit> availableSize) const
342 {
343     if (span <= 1)
344         return { };
345
346     LayoutUnit gap = gridGap(direction, availableSize);
347
348     // Fast path, no collapsing tracks.
349     if (!grid.hasAutoRepeatEmptyTracks(direction))
350         return gap * (span - 1);
351
352     // If there are collapsing tracks we need to be sure that gutters are properly collapsed. Apart
353     // from that, if we have a collapsed track in the edges of the span we're considering, we need
354     // to move forward (or backwards) in order to know whether the collapsed tracks reach the end of
355     // the grid (so the gap becomes 0) or there is a non empty track before that.
356
357     LayoutUnit gapAccumulator;
358     unsigned endLine = startLine + span;
359
360     for (unsigned line = startLine; line < endLine - 1; ++line) {
361         if (!grid.isEmptyAutoRepeatTrack(direction, line))
362             gapAccumulator += gap;
363     }
364
365     // The above loop adds one extra gap for trailing collapsed tracks.
366     if (gapAccumulator && grid.isEmptyAutoRepeatTrack(direction, endLine - 1)) {
367         ASSERT(gapAccumulator >= gap);
368         gapAccumulator -= gap;
369     }
370
371     // If the startLine is the start line of a collapsed track we need to go backwards till we reach
372     // a non collapsed track. If we find a non collapsed track we need to add that gap.
373     if (startLine && grid.isEmptyAutoRepeatTrack(direction, startLine)) {
374         unsigned nonEmptyTracksBeforeStartLine = startLine;
375         auto begin = grid.autoRepeatEmptyTracks(direction)->begin();
376         for (auto it = begin; *it != startLine; ++it) {
377             ASSERT(nonEmptyTracksBeforeStartLine);
378             --nonEmptyTracksBeforeStartLine;
379         }
380         if (nonEmptyTracksBeforeStartLine)
381             gapAccumulator += gap;
382     }
383
384     // If the endLine is the end line of a collapsed track we need to go forward till we reach a non
385     // collapsed track. If we find a non collapsed track we need to add that gap.
386     if (grid.isEmptyAutoRepeatTrack(direction, endLine - 1)) {
387         unsigned nonEmptyTracksAfterEndLine = grid.numTracks(direction) - endLine;
388         auto currentEmptyTrack = grid.autoRepeatEmptyTracks(direction)->find(endLine - 1);
389         auto endEmptyTrack = grid.autoRepeatEmptyTracks(direction)->end();
390         // HashSet iterators do not implement operator- so we have to manually iterate to know the number of remaining empty tracks.
391         for (auto it = ++currentEmptyTrack; it != endEmptyTrack; ++it) {
392             ASSERT(nonEmptyTracksAfterEndLine >= 1);
393             --nonEmptyTracksAfterEndLine;
394         }
395         if (nonEmptyTracksAfterEndLine)
396             gapAccumulator += gap;
397     }
398
399     return gapAccumulator;
400 }
401
402 void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
403 {
404     LayoutUnit childMinWidth;
405     LayoutUnit childMaxWidth;
406     bool hadExcludedChildren = computePreferredWidthsForExcludedChildren(childMinWidth, childMaxWidth);
407
408     Grid grid(const_cast<RenderGrid&>(*this));
409     placeItemsOnGrid(grid, std::nullopt);
410
411     GridTrackSizingAlgorithm algorithm(this, grid);
412     computeTrackSizesForIndefiniteSize(algorithm, ForColumns, grid, minLogicalWidth, maxLogicalWidth);
413
414     if (hadExcludedChildren) {
415         minLogicalWidth = std::max(minLogicalWidth, childMinWidth);
416         maxLogicalWidth = std::max(maxLogicalWidth, childMaxWidth);
417     }
418
419     LayoutUnit scrollbarWidth = intrinsicScrollbarLogicalWidth();
420     minLogicalWidth += scrollbarWidth;
421     maxLogicalWidth += scrollbarWidth;
422 }
423
424 void RenderGrid::computeTrackSizesForIndefiniteSize(GridTrackSizingAlgorithm& algorithm, GridTrackSizingDirection direction, Grid& grid, LayoutUnit& minIntrinsicSize, LayoutUnit& maxIntrinsicSize) const
425 {
426     algorithm.setup(direction, numTracks(direction, grid), IntrinsicSizeComputation, std::nullopt, std::nullopt);
427     algorithm.run();
428
429     size_t numberOfTracks = algorithm.tracks(direction).size();
430     LayoutUnit totalGuttersSize = guttersSize(grid, direction, 0, numberOfTracks, std::nullopt);
431
432     minIntrinsicSize = algorithm.minContentSize() + totalGuttersSize;
433     maxIntrinsicSize = algorithm.maxContentSize() + totalGuttersSize;
434
435     ASSERT(algorithm.tracksAreWiderThanMinTrackBreadth());
436 }
437
438 std::optional<LayoutUnit> RenderGrid::computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, std::optional<LayoutUnit> intrinsicLogicalHeight, LayoutUnit borderAndPadding) const
439 {
440     if (!intrinsicLogicalHeight)
441         return std::nullopt;
442
443     if (logicalHeightLength.isMinContent())
444         return m_minContentHeight;
445
446     if (logicalHeightLength.isMaxContent())
447         return m_maxContentHeight;
448
449     if (logicalHeightLength.isFitContent()) {
450         LayoutUnit fillAvailableExtent = containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding);
451         return std::min(m_maxContentHeight.value_or(0), std::max(m_minContentHeight.value_or(0), fillAvailableExtent));
452     }
453
454     if (logicalHeightLength.isFillAvailable())
455         return containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding) - borderAndPadding;
456     ASSERT_NOT_REACHED();
457     return std::nullopt;
458 }
459
460 static std::optional<LayoutUnit> overrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
461 {
462     return direction == ForColumns ? child.overrideContainingBlockContentLogicalWidth() : child.overrideContainingBlockContentLogicalHeight();
463 }
464
465 bool RenderGrid::isOrthogonalChild(const RenderBox& child) const
466 {
467     return child.isHorizontalWritingMode() != isHorizontalWritingMode();
468 }
469
470 GridTrackSizingDirection RenderGrid::flowAwareDirectionForChild(const RenderBox& child, GridTrackSizingDirection direction) const
471 {
472     return !isOrthogonalChild(child) ? direction : (direction == ForColumns ? ForRows : ForColumns);
473 }
474
475 unsigned RenderGrid::computeAutoRepeatTracksCount(GridTrackSizingDirection direction, std::optional<LayoutUnit> availableSize) const
476 {
477     ASSERT(!availableSize || availableSize.value() != -1);
478     bool isRowAxis = direction == ForColumns;
479     const auto& autoRepeatTracks = isRowAxis ? style().gridAutoRepeatColumns() : style().gridAutoRepeatRows();
480     unsigned autoRepeatTrackListLength = autoRepeatTracks.size();
481
482     if (!autoRepeatTrackListLength)
483         return 0;
484
485     if (!isRowAxis && !availableSize) {
486         const Length& maxLength = style().logicalMaxHeight();
487         if (!maxLength.isUndefined()) {
488             availableSize = computeContentLogicalHeight(MaxSize, maxLength, std::nullopt);
489             if (availableSize)
490                 availableSize = constrainContentBoxLogicalHeightByMinMax(availableSize.value(), std::nullopt);
491         }
492     }
493
494     bool needsToFulfillMinimumSize = false;
495     if (!availableSize) {
496         const Length& minSize = isRowAxis ? style().logicalMinWidth() : style().logicalMinHeight();
497         if (!minSize.isSpecified())
498             return autoRepeatTrackListLength;
499
500         LayoutUnit containingBlockAvailableSize = isRowAxis ? containingBlockLogicalWidthForContent() : containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
501         availableSize = valueForLength(minSize, containingBlockAvailableSize);
502         needsToFulfillMinimumSize = true;
503     }
504
505     LayoutUnit autoRepeatTracksSize;
506     for (auto& autoTrackSize : autoRepeatTracks) {
507         ASSERT(autoTrackSize.minTrackBreadth().isLength());
508         ASSERT(!autoTrackSize.minTrackBreadth().isFlex());
509         bool hasDefiniteMaxTrackSizingFunction = autoTrackSize.maxTrackBreadth().isLength() && !autoTrackSize.maxTrackBreadth().isContentSized();
510         auto trackLength = hasDefiniteMaxTrackSizingFunction ? autoTrackSize.maxTrackBreadth().length() : autoTrackSize.minTrackBreadth().length();
511         autoRepeatTracksSize += valueForLength(trackLength, availableSize.value());
512     }
513     // For the purpose of finding the number of auto-repeated tracks, the UA must floor the track size to a UA-specified
514     // value to avoid division by zero. It is suggested that this floor be 1px.
515     autoRepeatTracksSize = std::max<LayoutUnit>(LayoutUnit(1), autoRepeatTracksSize);
516
517     // There will be always at least 1 auto-repeat track, so take it already into account when computing the total track size.
518     LayoutUnit tracksSize = autoRepeatTracksSize;
519     auto& trackSizes = isRowAxis ? style().gridColumns() : style().gridRows();
520
521     for (const auto& track : trackSizes) {
522         bool hasDefiniteMaxTrackBreadth = track.maxTrackBreadth().isLength() && !track.maxTrackBreadth().isContentSized();
523         ASSERT(hasDefiniteMaxTrackBreadth || (track.minTrackBreadth().isLength() && !track.minTrackBreadth().isContentSized()));
524         tracksSize += valueForLength(hasDefiniteMaxTrackBreadth ? track.maxTrackBreadth().length() : track.minTrackBreadth().length(), availableSize.value());
525     }
526
527     // Add gutters as if there where only 1 auto repeat track. Gaps between auto repeat tracks will be added later when
528     // computing the repetitions.
529     LayoutUnit gapSize = gridGap(direction, availableSize);
530     tracksSize += gapSize * trackSizes.size();
531
532     LayoutUnit freeSpace = availableSize.value() - tracksSize;
533     if (freeSpace <= 0)
534         return autoRepeatTrackListLength;
535
536     unsigned repetitions = 1 + (freeSpace / (autoRepeatTracksSize + gapSize)).toInt();
537
538     // Provided the grid container does not have a definite size or max-size in the relevant axis,
539     // if the min size is definite then the number of repetitions is the largest possible positive
540     // integer that fulfills that minimum requirement.
541     if (needsToFulfillMinimumSize)
542         ++repetitions;
543
544     return repetitions * autoRepeatTrackListLength;
545 }
546
547
548 std::unique_ptr<OrderedTrackIndexSet> RenderGrid::computeEmptyTracksForAutoRepeat(Grid& grid, GridTrackSizingDirection direction) const
549 {
550     bool isRowAxis = direction == ForColumns;
551     if ((isRowAxis && style().gridAutoRepeatColumnsType() != AutoFit)
552         || (!isRowAxis && style().gridAutoRepeatRowsType() != AutoFit))
553         return nullptr;
554
555     std::unique_ptr<OrderedTrackIndexSet> emptyTrackIndexes;
556     unsigned insertionPoint = isRowAxis ? style().gridAutoRepeatColumnsInsertionPoint() : style().gridAutoRepeatRowsInsertionPoint();
557     unsigned firstAutoRepeatTrack = insertionPoint + std::abs(grid.smallestTrackStart(direction));
558     unsigned lastAutoRepeatTrack = firstAutoRepeatTrack + grid.autoRepeatTracks(direction);
559
560     if (!grid.hasGridItems()) {
561         emptyTrackIndexes = std::make_unique<OrderedTrackIndexSet>();
562         for (unsigned trackIndex = firstAutoRepeatTrack; trackIndex < lastAutoRepeatTrack; ++trackIndex)
563             emptyTrackIndexes->add(trackIndex);
564     } else {
565         for (unsigned trackIndex = firstAutoRepeatTrack; trackIndex < lastAutoRepeatTrack; ++trackIndex) {
566             GridIterator iterator(grid, direction, trackIndex);
567             if (!iterator.nextGridItem()) {
568                 if (!emptyTrackIndexes)
569                     emptyTrackIndexes = std::make_unique<OrderedTrackIndexSet>();
570                 emptyTrackIndexes->add(trackIndex);
571             }
572         }
573     }
574     return emptyTrackIndexes;
575 }
576
577 unsigned RenderGrid::clampAutoRepeatTracks(GridTrackSizingDirection direction, unsigned autoRepeatTracks) const
578 {
579     if (!autoRepeatTracks)
580         return 0;
581
582     unsigned insertionPoint = direction == ForColumns ? style().gridAutoRepeatColumnsInsertionPoint() : style().gridAutoRepeatRowsInsertionPoint();
583     unsigned maxTracks = static_cast<unsigned>(GridPosition::max());
584
585     if (!insertionPoint)
586         return std::min(autoRepeatTracks, maxTracks);
587
588     if (insertionPoint >= maxTracks)
589         return 0;
590
591     return std::min(autoRepeatTracks, maxTracks - insertionPoint);
592 }
593
594 // FIXME): We shouldn't have to pass the available logical width as argument. The problem is that
595 // availableLogicalWidth() does always return a value even if we cannot resolve it like when
596 // computing the intrinsic size (preferred widths). That's why we pass the responsibility to the
597 // caller who does know whether the available logical width is indefinite or not.
598 void RenderGrid::placeItemsOnGrid(Grid& grid, std::optional<LayoutUnit> availableSpace) const
599 {
600     unsigned autoRepeatColumns = computeAutoRepeatTracksCount(ForColumns, availableSpace);
601     unsigned autoRepeatRows = computeAutoRepeatTracksCount(ForRows, availableLogicalHeightForPercentageComputation());
602
603     autoRepeatRows = clampAutoRepeatTracks(ForRows, autoRepeatRows);
604     autoRepeatColumns = clampAutoRepeatTracks(ForColumns, autoRepeatColumns);
605
606     if (autoRepeatColumns != grid.autoRepeatTracks(ForColumns) || autoRepeatRows != grid.autoRepeatTracks(ForRows)) {
607         grid.setNeedsItemsPlacement(true);
608         grid.setAutoRepeatTracks(autoRepeatRows, autoRepeatColumns);
609     }
610
611     if (!grid.needsItemsPlacement())
612         return;
613
614     ASSERT(!grid.hasGridItems());
615     populateExplicitGridAndOrderIterator(grid);
616
617     Vector<RenderBox*> autoMajorAxisAutoGridItems;
618     Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
619     bool hasAnyOrthogonalGridItem = false;
620     for (auto* child = grid.orderIterator().first(); child; child = grid.orderIterator().next()) {
621         if (grid.orderIterator().shouldSkipChild(*child))
622             continue;
623
624         hasAnyOrthogonalGridItem = hasAnyOrthogonalGridItem || isOrthogonalChild(*child);
625
626         GridArea area = grid.gridItemArea(*child);
627         if (!area.rows.isIndefinite())
628             area.rows.translate(std::abs(grid.smallestTrackStart(ForRows)));
629         if (!area.columns.isIndefinite())
630             area.columns.translate(std::abs(grid.smallestTrackStart(ForColumns)));
631
632         if (area.rows.isIndefinite() || area.columns.isIndefinite()) {
633             grid.setGridItemArea(*child, area);
634             bool majorAxisDirectionIsForColumns = autoPlacementMajorAxisDirection() == ForColumns;
635             if ((majorAxisDirectionIsForColumns && area.columns.isIndefinite())
636                 || (!majorAxisDirectionIsForColumns && area.rows.isIndefinite()))
637                 autoMajorAxisAutoGridItems.append(child);
638             else
639                 specifiedMajorAxisAutoGridItems.append(child);
640             continue;
641         }
642         grid.insert(*child, { area.rows, area.columns });
643     }
644     grid.setHasAnyOrthogonalGridItem(hasAnyOrthogonalGridItem);
645
646 #if ENABLE(ASSERT)
647     if (grid.hasGridItems()) {
648         ASSERT(grid.numTracks(ForRows) >= GridPositionsResolver::explicitGridRowCount(style(), grid.autoRepeatTracks(ForRows)));
649         ASSERT(grid.numTracks(ForColumns) >= GridPositionsResolver::explicitGridColumnCount(style(), grid.autoRepeatTracks(ForColumns)));
650     }
651 #endif
652
653     placeSpecifiedMajorAxisItemsOnGrid(grid, specifiedMajorAxisAutoGridItems);
654     placeAutoMajorAxisItemsOnGrid(grid, autoMajorAxisAutoGridItems);
655
656     // Compute collapsible tracks for auto-fit.
657     grid.setAutoRepeatEmptyColumns(computeEmptyTracksForAutoRepeat(grid, ForColumns));
658     grid.setAutoRepeatEmptyRows(computeEmptyTracksForAutoRepeat(grid, ForRows));
659
660     grid.setNeedsItemsPlacement(false);
661
662 #if ENABLE(ASSERT)
663     for (auto* child = grid.orderIterator().first(); child; child = grid.orderIterator().next()) {
664         if (grid.orderIterator().shouldSkipChild(*child))
665             continue;
666
667         GridArea area = grid.gridItemArea(*child);
668         ASSERT(area.rows.isTranslatedDefinite() && area.columns.isTranslatedDefinite());
669     }
670 #endif
671 }
672
673 void RenderGrid::populateExplicitGridAndOrderIterator(Grid& grid) const
674 {
675     OrderIteratorPopulator populator(grid.orderIterator());
676     int smallestRowStart = 0;
677     int smallestColumnStart = 0;
678     unsigned autoRepeatRows = grid.autoRepeatTracks(ForRows);
679     unsigned autoRepeatColumns = grid.autoRepeatTracks(ForColumns);
680     unsigned maximumRowIndex = GridPositionsResolver::explicitGridRowCount(style(), autoRepeatRows);
681     unsigned maximumColumnIndex = GridPositionsResolver::explicitGridColumnCount(style(), autoRepeatColumns);
682
683     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
684         if (!populator.collectChild(*child))
685             continue;
686         
687         GridSpan rowPositions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), *child, ForRows, autoRepeatRows);
688         if (!rowPositions.isIndefinite()) {
689             smallestRowStart = std::min(smallestRowStart, rowPositions.untranslatedStartLine());
690             maximumRowIndex = std::max<int>(maximumRowIndex, rowPositions.untranslatedEndLine());
691         } else {
692             // Grow the grid for items with a definite row span, getting the largest such span.
693             unsigned spanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), *child, ForRows);
694             maximumRowIndex = std::max(maximumRowIndex, spanSize);
695         }
696
697         GridSpan columnPositions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), *child, ForColumns, autoRepeatColumns);
698         if (!columnPositions.isIndefinite()) {
699             smallestColumnStart = std::min(smallestColumnStart, columnPositions.untranslatedStartLine());
700             maximumColumnIndex = std::max<int>(maximumColumnIndex, columnPositions.untranslatedEndLine());
701         } else {
702             // Grow the grid for items with a definite column span, getting the largest such span.
703             unsigned spanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), *child, ForColumns);
704             maximumColumnIndex = std::max(maximumColumnIndex, spanSize);
705         }
706
707         grid.setGridItemArea(*child, { rowPositions, columnPositions });
708     }
709
710     grid.setSmallestTracksStart(smallestRowStart, smallestColumnStart);
711     grid.ensureGridSize(maximumRowIndex + std::abs(smallestRowStart), maximumColumnIndex + std::abs(smallestColumnStart));
712 }
713
714 std::unique_ptr<GridArea> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(Grid& grid, const RenderBox& gridItem, GridTrackSizingDirection specifiedDirection, const GridSpan& specifiedPositions) const
715 {
716     GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
717     const unsigned endOfCrossDirection = grid.numTracks(crossDirection);
718     unsigned crossDirectionSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), gridItem, crossDirection);
719     GridSpan crossDirectionPositions = GridSpan::translatedDefiniteGridSpan(endOfCrossDirection, endOfCrossDirection + crossDirectionSpanSize);
720     return std::make_unique<GridArea>(specifiedDirection == ForColumns ? crossDirectionPositions : specifiedPositions, specifiedDirection == ForColumns ? specifiedPositions : crossDirectionPositions);
721 }
722
723 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(Grid& grid, const Vector<RenderBox*>& autoGridItems) const
724 {
725     bool isForColumns = autoPlacementMajorAxisDirection() == ForColumns;
726     bool isGridAutoFlowDense = style().isGridAutoFlowAlgorithmDense();
727
728     // Mapping between the major axis tracks (rows or columns) and the last auto-placed item's position inserted on
729     // that track. This is needed to implement "sparse" packing for items locked to a given track.
730     // See http://dev.w3.org/csswg/css-grid/#auto-placement-algorithm
731     HashMap<unsigned, unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> minorAxisCursors;
732
733     for (auto& autoGridItem : autoGridItems) {
734         GridSpan majorAxisPositions = grid.gridItemSpan(*autoGridItem, autoPlacementMajorAxisDirection());
735         ASSERT(majorAxisPositions.isTranslatedDefinite());
736         ASSERT(grid.gridItemSpan(*autoGridItem, autoPlacementMinorAxisDirection()).isIndefinite());
737         unsigned minorAxisSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), *autoGridItem, autoPlacementMinorAxisDirection());
738         unsigned majorAxisInitialPosition = majorAxisPositions.startLine();
739
740         GridIterator iterator(grid, autoPlacementMajorAxisDirection(), majorAxisPositions.startLine(), isGridAutoFlowDense ? 0 : minorAxisCursors.get(majorAxisInitialPosition));
741         std::unique_ptr<GridArea> emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions.integerSpan(), minorAxisSpanSize);
742         if (!emptyGridArea)
743             emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(grid, *autoGridItem, autoPlacementMajorAxisDirection(), majorAxisPositions);
744
745         grid.insert(*autoGridItem, *emptyGridArea);
746
747         if (!isGridAutoFlowDense)
748             minorAxisCursors.set(majorAxisInitialPosition, isForColumns ? emptyGridArea->rows.startLine() : emptyGridArea->columns.startLine());
749     }
750 }
751
752 void RenderGrid::placeAutoMajorAxisItemsOnGrid(Grid& grid, const Vector<RenderBox*>& autoGridItems) const
753 {
754     AutoPlacementCursor autoPlacementCursor = {0, 0};
755     bool isGridAutoFlowDense = style().isGridAutoFlowAlgorithmDense();
756
757     for (auto& autoGridItem : autoGridItems) {
758         placeAutoMajorAxisItemOnGrid(grid, *autoGridItem, autoPlacementCursor);
759
760         if (isGridAutoFlowDense) {
761             autoPlacementCursor.first = 0;
762             autoPlacementCursor.second = 0;
763         }
764     }
765 }
766
767 void RenderGrid::placeAutoMajorAxisItemOnGrid(Grid& grid, RenderBox& gridItem, AutoPlacementCursor& autoPlacementCursor) const
768 {
769     ASSERT(grid.gridItemSpan(gridItem, autoPlacementMajorAxisDirection()).isIndefinite());
770     unsigned majorAxisSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), gridItem, autoPlacementMajorAxisDirection());
771
772     const unsigned endOfMajorAxis = grid.numTracks(autoPlacementMajorAxisDirection());
773     unsigned majorAxisAutoPlacementCursor = autoPlacementMajorAxisDirection() == ForColumns ? autoPlacementCursor.second : autoPlacementCursor.first;
774     unsigned minorAxisAutoPlacementCursor = autoPlacementMajorAxisDirection() == ForColumns ? autoPlacementCursor.first : autoPlacementCursor.second;
775
776     std::unique_ptr<GridArea> emptyGridArea;
777     GridSpan minorAxisPositions = grid.gridItemSpan(gridItem, autoPlacementMinorAxisDirection());
778     if (minorAxisPositions.isTranslatedDefinite()) {
779         // Move to the next track in major axis if initial position in minor axis is before auto-placement cursor.
780         if (minorAxisPositions.startLine() < minorAxisAutoPlacementCursor)
781             majorAxisAutoPlacementCursor++;
782
783         if (majorAxisAutoPlacementCursor < endOfMajorAxis) {
784             GridIterator iterator(grid, autoPlacementMinorAxisDirection(), minorAxisPositions.startLine(), majorAxisAutoPlacementCursor);
785             emptyGridArea = iterator.nextEmptyGridArea(minorAxisPositions.integerSpan(), majorAxisSpanSize);
786         }
787
788         if (!emptyGridArea)
789             emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(grid, gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions);
790     } else {
791         unsigned minorAxisSpanSize = GridPositionsResolver::spanSizeForAutoPlacedItem(style(), gridItem, autoPlacementMinorAxisDirection());
792
793         for (unsigned majorAxisIndex = majorAxisAutoPlacementCursor; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) {
794             GridIterator iterator(grid, autoPlacementMajorAxisDirection(), majorAxisIndex, minorAxisAutoPlacementCursor);
795             emptyGridArea = iterator.nextEmptyGridArea(majorAxisSpanSize, minorAxisSpanSize);
796
797             if (emptyGridArea) {
798                 // Check that it fits in the minor axis direction, as we shouldn't grow in that direction here (it was already managed in populateExplicitGridAndOrderIterator()).
799                 unsigned minorAxisFinalPositionIndex = autoPlacementMinorAxisDirection() == ForColumns ? emptyGridArea->columns.endLine() : emptyGridArea->rows.endLine();
800                 const unsigned endOfMinorAxis = grid.numTracks(autoPlacementMinorAxisDirection());
801                 if (minorAxisFinalPositionIndex <= endOfMinorAxis)
802                     break;
803
804                 // Discard empty grid area as it does not fit in the minor axis direction.
805                 // We don't need to create a new empty grid area yet as we might find a valid one in the next iteration.
806                 emptyGridArea = nullptr;
807             }
808
809             // As we're moving to the next track in the major axis we should reset the auto-placement cursor in the minor axis.
810             minorAxisAutoPlacementCursor = 0;
811         }
812
813         if (!emptyGridArea)
814             emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(grid, gridItem, autoPlacementMinorAxisDirection(), GridSpan::translatedDefiniteGridSpan(0, minorAxisSpanSize));
815     }
816
817     grid.insert(gridItem, *emptyGridArea);
818     autoPlacementCursor.first = emptyGridArea->rows.startLine();
819     autoPlacementCursor.second = emptyGridArea->columns.startLine();
820 }
821
822 GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
823 {
824     return style().isGridAutoFlowDirectionColumn() ? ForColumns : ForRows;
825 }
826
827 GridTrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
828 {
829     return style().isGridAutoFlowDirectionColumn() ? ForRows : ForColumns;
830 }
831
832 void RenderGrid::dirtyGrid()
833 {
834     if (m_grid.needsItemsPlacement())
835         return;
836
837     m_grid.setNeedsItemsPlacement(true);
838 }
839
840 Vector<LayoutUnit> RenderGrid::trackSizesForComputedStyle(GridTrackSizingDirection direction) const
841 {
842     bool isRowAxis = direction == ForColumns;
843     auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
844     size_t numPositions = positions.size();
845     LayoutUnit offsetBetweenTracks = isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
846
847     Vector<LayoutUnit> tracks;
848     if (numPositions < 2)
849         return tracks;
850
851     ASSERT(!m_grid.needsItemsPlacement());
852     bool hasCollapsedTracks = m_grid.hasAutoRepeatEmptyTracks(direction);
853     LayoutUnit gap = !hasCollapsedTracks ? gridGap(direction) : LayoutUnit();
854     tracks.reserveCapacity(numPositions - 1);
855     for (size_t i = 0; i < numPositions - 2; ++i)
856         tracks.append(positions[i + 1] - positions[i] - offsetBetweenTracks - gap);
857     tracks.append(positions[numPositions - 1] - positions[numPositions - 2]);
858
859     if (!hasCollapsedTracks)
860         return tracks;
861
862     size_t remainingEmptyTracks = m_grid.autoRepeatEmptyTracks(direction)->size();
863     size_t lastLine = tracks.size();
864     gap = gridGap(direction);
865     for (size_t i = 1; i < lastLine; ++i) {
866         if (m_grid.isEmptyAutoRepeatTrack(direction, i - 1))
867             --remainingEmptyTracks;
868         else {
869             // Remove the gap between consecutive non empty tracks. Remove it also just once for an
870             // arbitrary number of empty tracks between two non empty ones.
871             bool allRemainingTracksAreEmpty = remainingEmptyTracks == (lastLine - i);
872             if (!allRemainingTracksAreEmpty || !m_grid.isEmptyAutoRepeatTrack(direction, i))
873                 tracks[i - 1] -= gap;
874         }
875     }
876
877     return tracks;
878 }
879
880 static const StyleContentAlignmentData& contentAlignmentNormalBehaviorGrid()
881 {
882     static const StyleContentAlignmentData normalBehavior = {ContentPositionNormal, ContentDistributionStretch};
883     return normalBehavior;
884 }
885
886 void RenderGrid::layoutGridItems()
887 {
888     populateGridPositionsForDirection(ForColumns);
889     populateGridPositionsForDirection(ForRows);
890
891     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
892         
893         if (m_grid.orderIterator().shouldSkipChild(*child)) {
894             if (child->isOutOfFlowPositioned())
895                 prepareChildForPositionedLayout(*child);
896             continue;
897         }
898
899         // Because the grid area cannot be styled, we don't need to adjust
900         // the grid breadth to account for 'box-sizing'.
901         std::optional<LayoutUnit> oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
902         std::optional<LayoutUnit> oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();
903
904         LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForColumns);
905         LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows);
906         if (!oldOverrideContainingBlockContentLogicalWidth || oldOverrideContainingBlockContentLogicalWidth.value() != overrideContainingBlockContentLogicalWidth
907             || ((!oldOverrideContainingBlockContentLogicalHeight || oldOverrideContainingBlockContentLogicalHeight.value() != overrideContainingBlockContentLogicalHeight)
908                 && child->hasRelativeLogicalHeight()))
909             child->setNeedsLayout(MarkOnlyThis);
910
911         child->setOverrideContainingBlockContentLogicalWidth(overrideContainingBlockContentLogicalWidth);
912         child->setOverrideContainingBlockContentLogicalHeight(overrideContainingBlockContentLogicalHeight);
913
914         LayoutRect oldChildRect = child->frameRect();
915
916         // Stretching logic might force a child layout, so we need to run it before the layoutIfNeeded
917         // call to avoid unnecessary relayouts. This might imply that child margins, needed to correctly
918         // determine the available space before stretching, are not set yet.
919         applyStretchAlignmentToChildIfNeeded(*child);
920
921         child->layoutIfNeeded();
922
923         // We need pending layouts to be done in order to compute auto-margins properly.
924         updateAutoMarginsInColumnAxisIfNeeded(*child);
925         updateAutoMarginsInRowAxisIfNeeded(*child);
926
927         child->setLogicalLocation(findChildLogicalPosition(*child));
928
929         // If the child moved, we have to repaint it as well as any floating/positioned
930         // descendants. An exception is if we need a layout. In this case, we know we're going to
931         // repaint ourselves (and the child) anyway.
932         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
933             child->repaintDuringLayoutIfMoved(oldChildRect);
934     }
935 }
936
937 void RenderGrid::prepareChildForPositionedLayout(RenderBox& child)
938 {
939     ASSERT(child.isOutOfFlowPositioned());
940     child.containingBlock()->insertPositionedObject(child);
941
942     RenderLayer* childLayer = child.layer();
943     childLayer->setStaticInlinePosition(borderStart());
944     childLayer->setStaticBlockPosition(borderBefore());
945 }
946
947 void RenderGrid::layoutPositionedObject(RenderBox& child, bool relayoutChildren, bool fixedPositionObjectsOnly)
948 {
949     LayoutUnit columnOffset;
950     LayoutUnit columnBreadth;
951     offsetAndBreadthForPositionedChild(child, ForColumns, columnOffset, columnBreadth);
952     LayoutUnit rowOffset;
953     LayoutUnit rowBreadth;
954     offsetAndBreadthForPositionedChild(child, ForRows, rowOffset, rowBreadth);
955
956     child.setOverrideContainingBlockContentLogicalWidth(columnBreadth);
957     child.setOverrideContainingBlockContentLogicalHeight(rowBreadth);
958
959     // Mark for layout as we're resetting the position before and we relay in generic layout logic
960     // for positioned items in order to get the offsets properly resolved.
961     child.setChildNeedsLayout(MarkOnlyThis);
962
963     // FIXME: If possible it'd be nice to avoid this layout here when it's not needed.
964     RenderBlock::layoutPositionedObject(child, relayoutChildren, fixedPositionObjectsOnly);
965
966     bool isOrthogonal = isOrthogonalChild(child);
967     LayoutUnit logicalLeft = child.logicalLeft() + (isOrthogonal ? rowOffset : columnOffset);
968     LayoutUnit logicalTop = child.logicalTop() + (isOrthogonal ? columnOffset : rowOffset);
969     child.setLogicalLocation(LayoutPoint(logicalLeft, logicalTop));
970 }
971
972 void RenderGrid::offsetAndBreadthForPositionedChild(const RenderBox& child, GridTrackSizingDirection direction, LayoutUnit& offset, LayoutUnit& breadth)
973 {
974     bool isRowAxis = direction == ForColumns;
975
976     unsigned autoRepeatCount = m_grid.autoRepeatTracks(direction);
977     GridSpan positions = GridPositionsResolver::resolveGridPositionsFromStyle(style(), child, direction, autoRepeatCount);
978     if (positions.isIndefinite()) {
979         offset = LayoutUnit();
980         breadth = isRowAxis ? clientLogicalWidth() : clientLogicalHeight();
981         return;
982     }
983
984     // 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.
985     int smallestStart = std::abs(m_grid.smallestTrackStart(direction));
986     int startLine = positions.untranslatedStartLine() + smallestStart;
987     int endLine = positions.untranslatedEndLine() + smallestStart;
988
989     GridPosition startPosition = isRowAxis ? child.style().gridItemColumnStart() : child.style().gridItemRowStart();
990     GridPosition endPosition = isRowAxis ? child.style().gridItemColumnEnd() : child.style().gridItemRowEnd();
991     int lastLine = numTracks(direction, m_grid);
992
993     bool startIsAuto = startPosition.isAuto()
994         || (startPosition.isNamedGridArea() && !NamedLineCollection::isValidNamedLineOrArea(startPosition.namedGridLine(), style(), (direction == ForColumns) ? ColumnStartSide : RowStartSide))
995         || (startLine < 0)
996         || (startLine > lastLine);
997     bool endIsAuto = endPosition.isAuto()
998         || (endPosition.isNamedGridArea() && !NamedLineCollection::isValidNamedLineOrArea(endPosition.namedGridLine(), style(), (direction == ForColumns) ? ColumnEndSide : RowEndSide))
999         || (endLine < 0)
1000         || (endLine > lastLine);
1001
1002     // We're normalizing the positions to avoid issues with RTL (as they're stored in the same order than LTR but adding an offset).
1003     LayoutUnit start;
1004     if (!startIsAuto) {
1005         if (isRowAxis) {
1006             if (style().isLeftToRightDirection())
1007                 start = m_columnPositions[startLine] - borderLogicalLeft();
1008             else
1009                 start = logicalWidth() - translateRTLCoordinate(m_columnPositions[startLine]) - borderLogicalRight();
1010         } else
1011             start = m_rowPositions[startLine] - borderBefore();
1012     }
1013
1014     std::optional<LayoutUnit> availableSizeForGutters = availableSpaceForGutters(direction);
1015     LayoutUnit end = isRowAxis ? clientLogicalWidth() : clientLogicalHeight();
1016     if (!endIsAuto) {
1017         if (isRowAxis) {
1018             if (style().isLeftToRightDirection())
1019                 end = m_columnPositions[endLine] - borderLogicalLeft();
1020             else
1021                 end = logicalWidth() - translateRTLCoordinate(m_columnPositions[endLine]) - borderLogicalRight();
1022         } else
1023             end = m_rowPositions[endLine] - borderBefore();
1024
1025         // These vectors store line positions including gaps, but we shouldn't consider them for the edges of the grid.
1026         if (endLine > 0 && endLine < lastLine) {
1027             ASSERT(!m_grid.needsItemsPlacement());
1028             end -= guttersSize(m_grid, direction, endLine - 1, 2, availableSizeForGutters);
1029             end -= isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
1030         }
1031     }
1032
1033     breadth = end - start;
1034     offset = start;
1035
1036     if (isRowAxis && !style().isLeftToRightDirection()) {
1037         // We always want to calculate the static position from the left (even if we're in RTL).
1038         if (endIsAuto)
1039             offset = LayoutUnit();
1040         else {
1041             offset = translateRTLCoordinate(m_columnPositions[endLine]) - borderLogicalLeft();
1042
1043             if (endLine > 0 && endLine < lastLine) {
1044                 ASSERT(!m_grid.needsItemsPlacement());
1045                 offset += guttersSize(m_grid, direction, endLine - 1, 2, availableSizeForGutters);
1046                 offset += isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
1047             }
1048         }
1049     }
1050 }
1051
1052 LayoutUnit RenderGrid::gridAreaBreadthForChildIncludingAlignmentOffsets(const RenderBox& child, GridTrackSizingDirection direction) const
1053 {
1054     // We need the cached value when available because Content Distribution alignment properties
1055     // may have some influence in the final grid area breadth.
1056     const auto& tracks = m_trackSizingAlgorithm.tracks(direction);
1057     const auto& span = m_grid.gridItemSpan(child, direction);
1058     const auto& linePositions = (direction == ForColumns) ? m_columnPositions : m_rowPositions;
1059
1060     LayoutUnit initialTrackPosition = linePositions[span.startLine()];
1061     LayoutUnit finalTrackPosition = linePositions[span.endLine() - 1];
1062
1063     // Track Positions vector stores the 'start' grid line of each track, so we have to add last track's baseSize.
1064     return finalTrackPosition - initialTrackPosition + tracks[span.endLine() - 1].baseSize();
1065 }
1066
1067 void RenderGrid::populateGridPositionsForDirection(GridTrackSizingDirection direction)
1068 {
1069     // Since we add alignment offsets and track gutters, grid lines are not always adjacent. Hence we will have to
1070     // assume from now on that we just store positions of the initial grid lines of each track,
1071     // except the last one, which is the only one considered as a final grid line of a track.
1072
1073     // The grid container's frame elements (border, padding and <content-position> offset) are sensible to the
1074     // inline-axis flow direction. However, column lines positions are 'direction' unaware. This simplification
1075     // allows us to use the same indexes to identify the columns independently on the inline-axis direction.
1076     bool isRowAxis = direction == ForColumns;
1077     auto& tracks = m_trackSizingAlgorithm.tracks(direction);
1078     unsigned numberOfTracks = tracks.size();
1079     unsigned numberOfLines = numberOfTracks + 1;
1080     unsigned lastLine = numberOfLines - 1;
1081     bool hasCollapsedTracks = m_grid.hasAutoRepeatEmptyTracks(direction);
1082     size_t numberOfCollapsedTracks = hasCollapsedTracks ? m_grid.autoRepeatEmptyTracks(direction)->size() : 0;
1083     ContentAlignmentData offset = computeContentPositionAndDistributionOffset(direction, m_trackSizingAlgorithm.freeSpace(direction).value(), numberOfTracks - numberOfCollapsedTracks);
1084     auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
1085     positions.resize(numberOfLines);
1086     auto borderAndPadding = isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore();
1087     positions[0] = borderAndPadding + offset.positionOffset;
1088     if (numberOfLines > 1) {
1089         // If we have collapsed tracks we just ignore gaps here and add them later as we might not
1090         // compute the gap between two consecutive tracks without examining the surrounding ones.
1091         LayoutUnit gap = !hasCollapsedTracks ? gridGap(direction) : LayoutUnit();
1092         unsigned nextToLastLine = numberOfLines - 2;
1093         for (unsigned i = 0; i < nextToLastLine; ++i)
1094             positions[i + 1] = positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap;
1095         positions[lastLine] = positions[nextToLastLine] + tracks[nextToLastLine].baseSize();
1096
1097         // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to collapse (they
1098         // coincide exactly) except on the edges of the grid where they become 0.
1099         if (hasCollapsedTracks) {
1100             gap = gridGap(direction);
1101             unsigned remainingEmptyTracks = numberOfCollapsedTracks;
1102             LayoutUnit offsetAccumulator;
1103             LayoutUnit gapAccumulator;
1104             for (unsigned i = 1; i < lastLine; ++i) {
1105                 if (m_grid.isEmptyAutoRepeatTrack(direction, i - 1)) {
1106                     --remainingEmptyTracks;
1107                     offsetAccumulator += offset.distributionOffset;
1108                 } else {
1109                     // Add gap between consecutive non empty tracks. Add it also just once for an
1110                     // arbitrary number of empty tracks between two non empty ones.
1111                     bool allRemainingTracksAreEmpty = remainingEmptyTracks == (lastLine - i);
1112                     if (!allRemainingTracksAreEmpty || !m_grid.isEmptyAutoRepeatTrack(direction, i))
1113                         gapAccumulator += gap;
1114                 }
1115                 positions[i] += gapAccumulator - offsetAccumulator;
1116             }
1117             positions[lastLine] += gapAccumulator - offsetAccumulator;
1118         }
1119     }
1120     auto& offsetBetweenTracks = isRowAxis ? m_offsetBetweenColumns : m_offsetBetweenRows;
1121     offsetBetweenTracks = offset.distributionOffset;
1122 }
1123
1124 static LayoutUnit computeOverflowAlignmentOffset(OverflowAlignment overflow, LayoutUnit trackSize, LayoutUnit childSize)
1125 {
1126     LayoutUnit offset = trackSize - childSize;
1127     switch (overflow) {
1128     case OverflowAlignmentSafe:
1129         // If overflow is 'safe', we have to make sure we don't overflow the 'start'
1130         // edge (potentially cause some data loss as the overflow is unreachable).
1131         return std::max<LayoutUnit>(0, offset);
1132     case OverflowAlignmentUnsafe:
1133     case OverflowAlignmentDefault:
1134         // If we overflow our alignment container and overflow is 'true' (default), we
1135         // ignore the overflow and just return the value regardless (which may cause data
1136         // loss as we overflow the 'start' edge).
1137         return offset;
1138     }
1139
1140     ASSERT_NOT_REACHED();
1141     return 0;
1142 }
1143
1144 LayoutUnit RenderGrid::marginLogicalSizeForChild(GridTrackSizingDirection direction, const RenderBox& child) const
1145 {
1146     return flowAwareDirectionForChild(child, direction) == ForColumns ? child.marginLogicalWidth() : child.marginLogicalHeight();
1147 }
1148
1149 LayoutUnit RenderGrid::computeMarginLogicalSizeForChild(GridTrackSizingDirection direction, const RenderBox& child) const
1150 {
1151     if (!child.style().hasMargin())
1152         return 0;
1153
1154     LayoutUnit marginStart;
1155     LayoutUnit marginEnd;
1156     if (direction == ForColumns)
1157         child.computeInlineDirectionMargins(*this, child.containingBlockLogicalWidthForContentInFragment(nullptr), child.logicalWidth(), marginStart, marginEnd);
1158     else
1159         child.computeBlockDirectionMargins(*this, marginStart, marginEnd);
1160
1161     return marginStart + marginEnd;
1162 }
1163
1164 LayoutUnit RenderGrid::availableAlignmentSpaceForChildBeforeStretching(LayoutUnit gridAreaBreadthForChild, const RenderBox& child) const
1165 {
1166     // Because we want to avoid multiple layouts, stretching logic might be performed before
1167     // children are laid out, so we can't use the child cached values. Hence, we need to
1168     // compute margins in order to determine the available height before stretching.
1169     GridTrackSizingDirection childBlockFlowDirection = flowAwareDirectionForChild(child, ForRows);
1170     return gridAreaBreadthForChild - (child.needsLayout() ? computeMarginLogicalSizeForChild(childBlockFlowDirection, child) : marginLogicalSizeForChild(childBlockFlowDirection, child));
1171 }
1172
1173 StyleSelfAlignmentData RenderGrid::alignSelfForChild(const RenderBox& child, const RenderStyle* gridStyle) const
1174 {
1175     if (!gridStyle)
1176         gridStyle = &style();
1177     return child.style().resolvedAlignSelf(gridStyle, selfAlignmentNormalBehavior(&child));
1178 }
1179
1180 StyleSelfAlignmentData RenderGrid::justifySelfForChild(const RenderBox& child, const RenderStyle* gridStyle) const
1181 {
1182     if (!gridStyle)
1183         gridStyle = &style();
1184     return child.style().resolvedJustifySelf(gridStyle, selfAlignmentNormalBehavior(&child));
1185 }
1186
1187 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
1188 void RenderGrid::applyStretchAlignmentToChildIfNeeded(RenderBox& child)
1189 {
1190     ASSERT(child.overrideContainingBlockContentLogicalHeight());
1191
1192     // We clear height override values because we will decide now whether it's allowed or
1193     // not, evaluating the conditions which might have changed since the old values were set.
1194     child.clearOverrideLogicalContentHeight();
1195
1196     GridTrackSizingDirection childBlockDirection = flowAwareDirectionForChild(child, ForRows);
1197     bool blockFlowIsColumnAxis = childBlockDirection == ForRows;
1198     bool allowedToStretchChildBlockSize = blockFlowIsColumnAxis ? allowedToStretchChildAlongColumnAxis(child) : allowedToStretchChildAlongRowAxis(child);
1199     if (allowedToStretchChildBlockSize) {
1200         LayoutUnit stretchedLogicalHeight = availableAlignmentSpaceForChildBeforeStretching(overrideContainingBlockContentSizeForChild(child, childBlockDirection).value(), child);
1201         LayoutUnit desiredLogicalHeight = child.constrainLogicalHeightByMinMax(stretchedLogicalHeight, LayoutUnit(-1));
1202         child.setOverrideLogicalContentHeight(desiredLogicalHeight - child.borderAndPaddingLogicalHeight());
1203         if (desiredLogicalHeight != child.logicalHeight()) {
1204             // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
1205             child.setLogicalHeight(LayoutUnit());
1206             child.setNeedsLayout();
1207         }
1208     }
1209 }
1210
1211 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
1212 bool RenderGrid::hasAutoMarginsInColumnAxis(const RenderBox& child) const
1213 {
1214     if (isHorizontalWritingMode())
1215         return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
1216     return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
1217 }
1218
1219 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
1220 bool RenderGrid::hasAutoMarginsInRowAxis(const RenderBox& child) const
1221 {
1222     if (isHorizontalWritingMode())
1223         return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
1224     return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
1225 }
1226
1227 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
1228 void RenderGrid::updateAutoMarginsInRowAxisIfNeeded(RenderBox& child)
1229 {
1230     ASSERT(!child.isOutOfFlowPositioned());
1231
1232     LayoutUnit availableAlignmentSpace = child.overrideContainingBlockContentLogicalWidth().value() - child.logicalWidth() - child.marginLogicalWidth();
1233     if (availableAlignmentSpace <= 0)
1234         return;
1235
1236     const RenderStyle& parentStyle = style();
1237     Length marginStart = child.style().marginStartUsing(&parentStyle);
1238     Length marginEnd = child.style().marginEndUsing(&parentStyle);
1239     if (marginStart.isAuto() && marginEnd.isAuto()) {
1240         child.setMarginStart(availableAlignmentSpace / 2, &parentStyle);
1241         child.setMarginEnd(availableAlignmentSpace / 2, &parentStyle);
1242     } else if (marginStart.isAuto()) {
1243         child.setMarginStart(availableAlignmentSpace, &parentStyle);
1244     } else if (marginEnd.isAuto()) {
1245         child.setMarginEnd(availableAlignmentSpace, &parentStyle);
1246     }
1247 }
1248
1249 // FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
1250 void RenderGrid::updateAutoMarginsInColumnAxisIfNeeded(RenderBox& child)
1251 {
1252     ASSERT(!child.isOutOfFlowPositioned());
1253
1254     LayoutUnit availableAlignmentSpace = child.overrideContainingBlockContentLogicalHeight().value() - child.logicalHeight() - child.marginLogicalHeight();
1255     if (availableAlignmentSpace <= 0)
1256         return;
1257
1258     const RenderStyle& parentStyle = style();
1259     Length marginBefore = child.style().marginBeforeUsing(&parentStyle);
1260     Length marginAfter = child.style().marginAfterUsing(&parentStyle);
1261     if (marginBefore.isAuto() && marginAfter.isAuto()) {
1262         child.setMarginBefore(availableAlignmentSpace / 2, &parentStyle);
1263         child.setMarginAfter(availableAlignmentSpace / 2, &parentStyle);
1264     } else if (marginBefore.isAuto()) {
1265         child.setMarginBefore(availableAlignmentSpace, &parentStyle);
1266     } else if (marginAfter.isAuto()) {
1267         child.setMarginAfter(availableAlignmentSpace, &parentStyle);
1268     }
1269 }
1270
1271 // FIXME: This logic could be refactored somehow and defined in RenderBox.
1272 static int synthesizedBaselineFromBorderBox(const RenderBox& box, LineDirectionMode direction)
1273 {
1274     return (direction == HorizontalLine ? box.size().height() : box.size().width()).toInt();
1275 }
1276
1277 bool RenderGrid::isInlineBaselineAlignedChild(const RenderBox& child) const
1278 {
1279     return alignSelfForChild(child).position() == ItemPositionBaseline && !isOrthogonalChild(child) && !hasAutoMarginsInColumnAxis(child);
1280 }
1281
1282 // FIXME: This logic is shared by RenderFlexibleBox, so it might be refactored somehow.
1283 int RenderGrid::baselinePosition(FontBaseline, bool, LineDirectionMode direction, LinePositionMode mode) const
1284 {
1285 #if ENABLE(ASSERT)
1286     ASSERT(mode == PositionOnContainingLine);
1287 #else
1288     UNUSED_PARAM(mode);
1289 #endif
1290     int baseline = firstLineBaseline().value_or(synthesizedBaselineFromBorderBox(*this, direction));
1291
1292     int marginSize = direction == HorizontalLine ? verticalMarginExtent() : horizontalMarginExtent();
1293     return baseline + marginSize;
1294 }
1295
1296 std::optional<int> RenderGrid::firstLineBaseline() const
1297 {
1298     if (isWritingModeRoot() || !m_grid.hasGridItems())
1299         return std::nullopt;
1300
1301     const RenderBox* baselineChild = nullptr;
1302     // Finding the first grid item in grid order.
1303     unsigned numColumns = m_grid.numTracks(ForColumns);
1304     for (size_t column = 0; column < numColumns; column++) {
1305         for (const auto* child : m_grid.cell(0, column)) {
1306             // If an item participates in baseline alignment, we select such item.
1307             if (isInlineBaselineAlignedChild(*child)) {
1308                 // FIXME: self-baseline and content-baseline alignment not implemented yet.
1309                 baselineChild = child;
1310                 break;
1311             }
1312             if (!baselineChild)
1313                 baselineChild = child;
1314         }
1315     }
1316
1317     if (!baselineChild)
1318         return std::nullopt;
1319
1320     auto baseline = isOrthogonalChild(*baselineChild) ? std::nullopt : baselineChild->firstLineBaseline();
1321     // We take border-box's bottom if no valid baseline.
1322     if (!baseline) {
1323         // FIXME: We should pass |direction| into firstLineBaseline and stop bailing out if we're a writing
1324         // mode root. This would also fix some cases where the grid is orthogonal to its container.
1325         LineDirectionMode direction = isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
1326         return synthesizedBaselineFromBorderBox(*baselineChild, direction) + baselineChild->logicalTop().toInt();
1327     }
1328     return baseline.value() + baselineChild->logicalTop().toInt();
1329 }
1330
1331 std::optional<int> RenderGrid::inlineBlockBaseline(LineDirectionMode direction) const
1332 {
1333     if (std::optional<int> baseline = firstLineBaseline())
1334         return baseline;
1335
1336     int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
1337     return synthesizedBaselineFromBorderBox(*this, direction) + marginAscent;
1338 }
1339
1340 GridAxisPosition RenderGrid::columnAxisPositionForChild(const RenderBox& child) const
1341 {
1342     bool hasSameWritingMode = child.style().writingMode() == style().writingMode();
1343     bool childIsLTR = child.style().isLeftToRightDirection();
1344
1345     switch (alignSelfForChild(child).position()) {
1346     case ItemPositionSelfStart:
1347         // FIXME: Should we implement this logic in a generic utility function ?
1348         // Aligns the alignment subject to be flush with the edge of the alignment container
1349         // corresponding to the alignment subject's 'start' side in the column axis.
1350         if (isOrthogonalChild(child)) {
1351             // If orthogonal writing-modes, self-start will be based on the child's inline-axis
1352             // direction (inline-start), because it's the one parallel to the column axis.
1353             if (style().isFlippedBlocksWritingMode())
1354                 return childIsLTR ? GridAxisEnd : GridAxisStart;
1355             return childIsLTR ? GridAxisStart : GridAxisEnd;
1356         }
1357         // 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.
1358         return hasSameWritingMode ? GridAxisStart : GridAxisEnd;
1359     case ItemPositionSelfEnd:
1360         // FIXME: Should we implement this logic in a generic utility function ?
1361         // Aligns the alignment subject to be flush with the edge of the alignment container
1362         // corresponding to the alignment subject's 'end' side in the column axis.
1363         if (isOrthogonalChild(child)) {
1364             // If orthogonal writing-modes, self-end will be based on the child's inline-axis
1365             // direction, (inline-end) because it's the one parallel to the column axis.
1366             if (style().isFlippedBlocksWritingMode())
1367                 return childIsLTR ? GridAxisStart : GridAxisEnd;
1368             return childIsLTR ? GridAxisEnd : GridAxisStart;
1369         }
1370         // 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.
1371         return hasSameWritingMode ? GridAxisEnd : GridAxisStart;
1372     case ItemPositionLeft:
1373         // Aligns the alignment subject to be flush with the alignment container's 'line-left' edge.
1374         // The alignment axis (column axis) is always orthogonal to the inline axis, hence this value behaves as 'start'.
1375         return GridAxisStart;
1376     case ItemPositionRight:
1377         // Aligns the alignment subject to be flush with the alignment container's 'line-right' edge.
1378         // The alignment axis (column axis) is always orthogonal to the inline axis, hence this value behaves as 'start'.
1379         return GridAxisStart;
1380     case ItemPositionCenter:
1381         return GridAxisCenter;
1382     case ItemPositionFlexStart: // Only used in flex layout, otherwise equivalent to 'start'.
1383         // Aligns the alignment subject to be flush with the alignment container's 'start' edge (block-start) in the column axis.
1384     case ItemPositionStart:
1385         return GridAxisStart;
1386     case ItemPositionFlexEnd: // Only used in flex layout, otherwise equivalent to 'end'.
1387         // Aligns the alignment subject to be flush with the alignment container's 'end' edge (block-end) in the column axis.
1388     case ItemPositionEnd:
1389         return GridAxisEnd;
1390     case ItemPositionStretch:
1391         return GridAxisStart;
1392     case ItemPositionBaseline:
1393     case ItemPositionLastBaseline:
1394         // FIXME: Implement the previous values. For now, we always 'start' align the child.
1395         return GridAxisStart;
1396     case ItemPositionAuto:
1397     case ItemPositionNormal:
1398         break;
1399     }
1400
1401     ASSERT_NOT_REACHED();
1402     return GridAxisStart;
1403 }
1404
1405 GridAxisPosition RenderGrid::rowAxisPositionForChild(const RenderBox& child) const
1406 {
1407     bool hasSameDirection = child.style().direction() == style().direction();
1408     bool gridIsLTR = style().isLeftToRightDirection();
1409
1410     switch (justifySelfForChild(child).position()) {
1411     case ItemPositionSelfStart:
1412         // FIXME: Should we implement this logic in a generic utility function ?
1413         // Aligns the alignment subject to be flush with the edge of the alignment container
1414         // corresponding to the alignment subject's 'start' side in the row axis.
1415         if (isOrthogonalChild(child)) {
1416             // If orthogonal writing-modes, self-start will be based on the child's block-axis
1417             // direction, because it's the one parallel to the row axis.
1418             if (child.style().isFlippedBlocksWritingMode())
1419                 return gridIsLTR ? GridAxisEnd : GridAxisStart;
1420             return gridIsLTR ? GridAxisStart : GridAxisEnd;
1421         }
1422         // self-start is based on the child's inline-flow direction. That's why we need to check against the grid container's direction.
1423         return hasSameDirection ? GridAxisStart : GridAxisEnd;
1424     case ItemPositionSelfEnd:
1425         // FIXME: Should we implement this logic in a generic utility function ?
1426         // Aligns the alignment subject to be flush with the edge of the alignment container
1427         // corresponding to the alignment subject's 'end' side in the row axis.
1428         if (isOrthogonalChild(child)) {
1429             // If orthogonal writing-modes, self-end will be based on the child's block-axis
1430             // direction, because it's the one parallel to the row axis.
1431             if (child.style().isFlippedBlocksWritingMode())
1432                 return gridIsLTR ? GridAxisStart : GridAxisEnd;
1433             return gridIsLTR ? GridAxisEnd : GridAxisStart;
1434         }
1435         // self-end is based on the child's inline-flow direction. That's why we need to check against the grid container's direction.
1436         return hasSameDirection ? GridAxisEnd : GridAxisStart;
1437     case ItemPositionLeft:
1438         // Aligns the alignment subject to be flush with the alignment container's 'line-left' edge.
1439         // We want the physical 'left' side, so we have to take account, container's inline-flow direction.
1440         return gridIsLTR ? GridAxisStart : GridAxisEnd;
1441     case ItemPositionRight:
1442         // Aligns the alignment subject to be flush with the alignment container's 'line-right' edge.
1443         // We want the physical 'right' side, so we have to take account, container's inline-flow direction.
1444         return gridIsLTR ? GridAxisEnd : GridAxisStart;
1445     case ItemPositionCenter:
1446         return GridAxisCenter;
1447     case ItemPositionFlexStart: // Only used in flex layout, otherwise equivalent to 'start'.
1448         // Aligns the alignment subject to be flush with the alignment container's 'start' edge (inline-start) in the row axis.
1449     case ItemPositionStart:
1450         return GridAxisStart;
1451     case ItemPositionFlexEnd: // Only used in flex layout, otherwise equivalent to 'end'.
1452         // Aligns the alignment subject to be flush with the alignment container's 'end' edge (inline-end) in the row axis.
1453     case ItemPositionEnd:
1454         return GridAxisEnd;
1455     case ItemPositionStretch:
1456         return GridAxisStart;
1457     case ItemPositionBaseline:
1458     case ItemPositionLastBaseline:
1459         // FIXME: Implement the previous values. For now, we always 'start' align the child.
1460         return GridAxisStart;
1461     case ItemPositionAuto:
1462     case ItemPositionNormal:
1463         break;
1464     }
1465
1466     ASSERT_NOT_REACHED();
1467     return GridAxisStart;
1468 }
1469
1470 LayoutUnit RenderGrid::columnAxisOffsetForChild(const RenderBox& child) const
1471 {
1472     const GridSpan& rowsSpan = m_grid.gridItemSpan(child, ForRows);
1473     unsigned childStartLine = rowsSpan.startLine();
1474     LayoutUnit startOfRow = m_rowPositions[childStartLine];
1475     LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
1476     if (hasAutoMarginsInColumnAxis(child))
1477         return startPosition;
1478     GridAxisPosition axisPosition = columnAxisPositionForChild(child);
1479     switch (axisPosition) {
1480     case GridAxisStart:
1481         return startPosition;
1482     case GridAxisEnd:
1483     case GridAxisCenter: {
1484         unsigned childEndLine = rowsSpan.endLine();
1485         LayoutUnit endOfRow = m_rowPositions[childEndLine];
1486         // m_rowPositions include distribution offset (because of content alignment) and gutters
1487         // so we need to subtract them to get the actual end position for a given row
1488         // (this does not have to be done for the last track as there are no more m_rowPositions after it).
1489         if (childEndLine < m_rowPositions.size() - 1)
1490             endOfRow -= gridGap(ForRows) + m_offsetBetweenRows;
1491         LayoutUnit columnAxisChildSize = isOrthogonalChild(child) ? child.logicalWidth() + child.marginLogicalWidth() : child.logicalHeight() + child.marginLogicalHeight();
1492         auto overflow = alignSelfForChild(child).overflow();
1493         LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(overflow, endOfRow - startOfRow, columnAxisChildSize);
1494         return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPosition : offsetFromStartPosition / 2);
1495     }
1496     }
1497
1498     ASSERT_NOT_REACHED();
1499     return 0;
1500 }
1501
1502 LayoutUnit RenderGrid::rowAxisOffsetForChild(const RenderBox& child) const
1503 {
1504     const GridSpan& columnsSpan = m_grid.gridItemSpan(child, ForColumns);
1505     unsigned childStartLine = columnsSpan.startLine();
1506     LayoutUnit startOfColumn = m_columnPositions[childStartLine];
1507     LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
1508     if (hasAutoMarginsInRowAxis(child))
1509         return startPosition;
1510     GridAxisPosition axisPosition = rowAxisPositionForChild(child);
1511     switch (axisPosition) {
1512     case GridAxisStart:
1513         return startPosition;
1514     case GridAxisEnd:
1515     case GridAxisCenter: {
1516         unsigned childEndLine = columnsSpan.endLine();
1517         LayoutUnit endOfColumn = m_columnPositions[childEndLine];
1518         // m_columnPositions include distribution offset (because of content alignment) and gutters
1519         // so we need to subtract them to get the actual end position for a given column
1520         // (this does not have to be done for the last track as there are no more m_columnPositions after it).
1521         if (childEndLine < m_columnPositions.size() - 1)
1522             endOfColumn -= gridGap(ForColumns) + m_offsetBetweenColumns;
1523         LayoutUnit rowAxisChildSize = isOrthogonalChild(child) ? child.logicalHeight() + child.marginLogicalHeight() : child.logicalWidth() + child.marginLogicalWidth();
1524         auto overflow = justifySelfForChild(child).overflow();
1525         LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(overflow, endOfColumn - startOfColumn, rowAxisChildSize);
1526         return startPosition + (axisPosition == GridAxisEnd ? offsetFromStartPosition : offsetFromStartPosition / 2);
1527     }
1528     }
1529
1530     ASSERT_NOT_REACHED();
1531     return 0;
1532 }
1533
1534 ContentPosition static resolveContentDistributionFallback(ContentDistributionType distribution)
1535 {
1536     switch (distribution) {
1537     case ContentDistributionSpaceBetween:
1538         return ContentPositionStart;
1539     case ContentDistributionSpaceAround:
1540         return ContentPositionCenter;
1541     case ContentDistributionSpaceEvenly:
1542         return ContentPositionCenter;
1543     case ContentDistributionStretch:
1544         return ContentPositionStart;
1545     case ContentDistributionDefault:
1546         return ContentPositionNormal;
1547     }
1548
1549     ASSERT_NOT_REACHED();
1550     return ContentPositionNormal;
1551 }
1552
1553 static ContentAlignmentData contentDistributionOffset(const LayoutUnit& availableFreeSpace, ContentPosition& fallbackPosition, ContentDistributionType distribution, unsigned numberOfGridTracks)
1554 {
1555     if (distribution != ContentDistributionDefault && fallbackPosition == ContentPositionNormal)
1556         fallbackPosition = resolveContentDistributionFallback(distribution);
1557
1558     if (availableFreeSpace <= 0)
1559         return ContentAlignmentData::defaultOffsets();
1560
1561     LayoutUnit distributionOffset;
1562     switch (distribution) {
1563     case ContentDistributionSpaceBetween:
1564         if (numberOfGridTracks < 2)
1565             return ContentAlignmentData::defaultOffsets();
1566         return {0, availableFreeSpace / (numberOfGridTracks - 1)};
1567     case ContentDistributionSpaceAround:
1568         if (numberOfGridTracks < 1)
1569             return ContentAlignmentData::defaultOffsets();
1570         distributionOffset = availableFreeSpace / numberOfGridTracks;
1571         return {distributionOffset / 2, distributionOffset};
1572     case ContentDistributionSpaceEvenly:
1573         distributionOffset = availableFreeSpace / (numberOfGridTracks + 1);
1574         return {distributionOffset, distributionOffset};
1575     case ContentDistributionStretch:
1576     case ContentDistributionDefault:
1577         return ContentAlignmentData::defaultOffsets();
1578     }
1579
1580     ASSERT_NOT_REACHED();
1581     return ContentAlignmentData::defaultOffsets();
1582 }
1583
1584 StyleContentAlignmentData RenderGrid::contentAlignment(GridTrackSizingDirection direction) const
1585 {
1586     return direction == ForColumns ? style().resolvedJustifyContent(contentAlignmentNormalBehaviorGrid()) : style().resolvedAlignContent(contentAlignmentNormalBehaviorGrid());
1587 }
1588
1589 ContentAlignmentData RenderGrid::computeContentPositionAndDistributionOffset(GridTrackSizingDirection direction, const LayoutUnit& availableFreeSpace, unsigned numberOfGridTracks) const
1590 {
1591     bool isRowAxis = direction == ForColumns;
1592     auto contentAlignmentData = contentAlignment(direction);
1593     auto position = contentAlignmentData.position();
1594     // If <content-distribution> value can't be applied, 'position' will become the associated
1595     // <content-position> fallback value.
1596     auto contentAlignment = contentDistributionOffset(availableFreeSpace, position, contentAlignmentData.distribution(), numberOfGridTracks);
1597     if (contentAlignment.isValid())
1598         return contentAlignment;
1599
1600     if (availableFreeSpace <= 0 && contentAlignmentData.overflow() == OverflowAlignmentSafe)
1601         return {0, 0};
1602
1603     switch (position) {
1604     case ContentPositionLeft:
1605         // The align-content's axis is always orthogonal to the inline-axis.
1606         return {0, 0};
1607     case ContentPositionRight:
1608         if (isRowAxis)
1609             return {availableFreeSpace, 0};
1610         // The align-content's axis is always orthogonal to the inline-axis.
1611         return {0, 0};
1612     case ContentPositionCenter:
1613         return {availableFreeSpace / 2, 0};
1614     case ContentPositionFlexEnd: // Only used in flex layout, for other layout, it's equivalent to 'end'.
1615     case ContentPositionEnd:
1616         if (isRowAxis)
1617             return {style().isLeftToRightDirection() ? availableFreeSpace : LayoutUnit(), LayoutUnit()};
1618         return {availableFreeSpace, 0};
1619     case ContentPositionFlexStart: // Only used in flex layout, for other layout, it's equivalent to 'start'.
1620     case ContentPositionStart:
1621         if (isRowAxis)
1622             return {style().isLeftToRightDirection() ? LayoutUnit() : availableFreeSpace, LayoutUnit()};
1623         return {0, 0};
1624     case ContentPositionBaseline:
1625     case ContentPositionLastBaseline:
1626         // FIXME: Implement the previous values. For now, we always 'start' align.
1627         // http://webkit.org/b/145566
1628         if (isRowAxis)
1629             return {style().isLeftToRightDirection() ? LayoutUnit() : availableFreeSpace, LayoutUnit()};
1630         return {0, 0};
1631     case ContentPositionNormal:
1632         break;
1633     }
1634
1635     ASSERT_NOT_REACHED();
1636     return {0, 0};
1637 }
1638
1639 LayoutUnit RenderGrid::translateRTLCoordinate(LayoutUnit coordinate) const
1640 {
1641     ASSERT(!style().isLeftToRightDirection());
1642
1643     LayoutUnit alignmentOffset = m_columnPositions[0];
1644     LayoutUnit rightGridEdgePosition = m_columnPositions[m_columnPositions.size() - 1];
1645     return rightGridEdgePosition + alignmentOffset - coordinate;
1646 }
1647
1648 LayoutPoint RenderGrid::findChildLogicalPosition(const RenderBox& child) const
1649 {
1650     LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child);
1651     LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child);
1652
1653     // We stored m_columnPositions's data ignoring the direction, hence we might need now
1654     // to translate positions from RTL to LTR, as it's more convenient for painting.
1655     if (!style().isLeftToRightDirection())
1656         rowAxisOffset = translateRTLCoordinate(rowAxisOffset) - (isOrthogonalChild(child) ? child.logicalHeight()  : child.logicalWidth());
1657
1658     // "In the positioning phase [...] calculations are performed according to the writing mode
1659     // of the containing block of the box establishing the orthogonal flow." However, the
1660     // resulting LayoutPoint will be used in 'setLogicalPosition' in order to set the child's
1661     // logical position, which will only take into account the child's writing-mode.
1662     LayoutPoint childLocation(rowAxisOffset, columnAxisOffset);
1663     return isOrthogonalChild(child) ? childLocation.transposedPoint() : childLocation;
1664 }
1665
1666 unsigned RenderGrid::numTracks(GridTrackSizingDirection direction, const Grid& grid) const
1667 {
1668     // Due to limitations in our internal representation, we cannot know the number of columns from
1669     // m_grid *if* there is no row (because m_grid would be empty). That's why in that case we need
1670     // to get it from the style. Note that we know for sure that there are't any implicit tracks,
1671     // because not having rows implies that there are no "normal" children (out-of-flow children are
1672     // not stored in m_grid).
1673     ASSERT(!grid.needsItemsPlacement());
1674     if (direction == ForRows)
1675         return grid.numTracks(ForRows);
1676
1677     // FIXME: This still requires knowledge about m_grid internals.
1678     return grid.numTracks(ForRows) ? grid.numTracks(ForColumns) : GridPositionsResolver::explicitGridColumnCount(style(), grid.autoRepeatTracks(ForColumns));
1679 }
1680
1681 void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect)
1682 {
1683     ASSERT(!m_grid.needsItemsPlacement());
1684     for (RenderBox* child = m_grid.orderIterator().first(); child; child = m_grid.orderIterator().next())
1685         paintChild(*child, paintInfo, paintOffset, forChild, usePrintRect, PaintAsInlineBlock);
1686 }
1687
1688 const char* RenderGrid::renderName() const
1689 {
1690     if (isFloating())
1691         return "RenderGrid (floating)";
1692     if (isOutOfFlowPositioned())
1693         return "RenderGrid (positioned)";
1694     if (isAnonymous())
1695         return "RenderGrid (generated)";
1696     if (isRelPositioned())
1697         return "RenderGrid (relative positioned)";
1698     return "RenderGrid";
1699 }
1700
1701 } // namespace WebCore