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