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