Implement RenderGrid::computeIntrinsicLogicalWidths
[WebKit-https.git] / Source / WebCore / rendering / RenderGrid.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RenderGrid.h"
28
29 #include "LayoutRepainter.h"
30 #include "NotImplemented.h"
31 #include "RenderLayer.h"
32 #include "RenderView.h"
33
34 namespace WebCore {
35
36 static const int infinity = intMaxForLayoutUnit;
37
38 class GridTrack {
39 public:
40     GridTrack()
41         : m_usedBreadth(0)
42         , m_maxBreadth(0)
43     {
44     }
45
46     void growUsedBreadth(LayoutUnit growth)
47     {
48         ASSERT(growth >= 0);
49         m_usedBreadth += growth;
50     }
51     LayoutUnit usedBreadth() const { return m_usedBreadth; }
52
53     void growMaxBreadth(LayoutUnit growth)
54     {
55         if (m_maxBreadth == infinity)
56             m_maxBreadth = m_usedBreadth + growth;
57         else
58             m_maxBreadth += growth;
59     }
60     LayoutUnit maxBreadthIfNotInfinite() const
61     {
62         return (m_maxBreadth == infinity) ? m_usedBreadth : m_maxBreadth;
63     }
64
65     LayoutUnit m_usedBreadth;
66     LayoutUnit m_maxBreadth;
67 };
68
69 class RenderGrid::GridIterator {
70     WTF_MAKE_NONCOPYABLE(GridIterator);
71 public:
72     // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
73     // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd column.
74     GridIterator(const Vector<Vector<Vector<RenderBox*, 1> > >& grid, TrackSizingDirection direction, size_t fixedTrackIndex)
75         : m_grid(grid)
76         , m_direction(direction)
77         , m_rowIndex((direction == ForColumns) ? 0 : fixedTrackIndex)
78         , m_columnIndex((direction == ForColumns) ? fixedTrackIndex : 0)
79         , m_childIndex(0)
80     {
81     }
82
83     RenderBox* nextGridItem()
84     {
85         if (!m_grid.size())
86             return 0;
87
88         size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
89         const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
90         for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
91             const Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
92             if (m_childIndex < children.size())
93                 return children[m_childIndex++];
94
95             m_childIndex = 0;
96         }
97         return 0;
98     }
99 private:
100     const Vector<Vector<Vector<RenderBox*, 1> > >& m_grid;
101     TrackSizingDirection m_direction;
102     size_t m_rowIndex;
103     size_t m_columnIndex;
104     size_t m_childIndex;
105 };
106
107 RenderGrid::RenderGrid(Element* element)
108     : RenderBlock(element)
109 {
110     // All of our children must be block level.
111     setChildrenInline(false);
112 }
113
114 RenderGrid::~RenderGrid()
115 {
116 }
117
118 void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
119 {
120     ASSERT(needsLayout());
121
122     if (!relayoutChildren && simplifiedLayout())
123         return;
124
125     // FIXME: Much of this method is boiler plate that matches RenderBox::layoutBlock and Render*FlexibleBox::layoutBlock.
126     // It would be nice to refactor some of the duplicate code.
127     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
128     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
129
130     if (inRenderFlowThread()) {
131         // Regions changing widths can force us to relayout our children.
132         if (logicalWidthChangedInRegions())
133             relayoutChildren = true;
134     }
135     updateRegionsAndExclusionsLogicalSize();
136
137     LayoutSize previousSize = size();
138
139     setLogicalHeight(0);
140     updateLogicalWidth();
141
142     m_overflow.clear();
143
144     layoutGridItems();
145
146     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
147     updateLogicalHeight();
148
149     if (size() != previousSize)
150         relayoutChildren = true;
151
152     layoutPositionedObjects(relayoutChildren || isRoot());
153
154     computeRegionRangeForBlock();
155
156     computeOverflow(oldClientAfterEdge);
157     statePusher.pop();
158
159     updateLayerTransform();
160
161     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
162     // we overflow or not.
163     if (hasOverflowClip())
164         layer()->updateScrollInfoAfterLayout();
165
166     repainter.repaintAfterLayout();
167
168     setNeedsLayout(false);
169 }
170
171 void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
172 {
173     const_cast<RenderGrid*>(this)->placeItemsOnGrid();
174
175     const Vector<GridTrackSize>& trackStyles = style()->gridColumns();
176     for (size_t i = 0; i < trackStyles.size(); ++i) {
177         LayoutUnit minTrackBreadth = computePreferredTrackWidth(trackStyles[i].minTrackBreadth(), i);
178         LayoutUnit maxTrackBreadth = computePreferredTrackWidth(trackStyles[i].maxTrackBreadth(), i);
179         maxTrackBreadth = std::max(maxTrackBreadth, minTrackBreadth);
180
181         minLogicalWidth += minTrackBreadth;
182         maxLogicalWidth += maxTrackBreadth;
183
184         // FIXME: This should add in the scrollbarWidth (e.g. see RenderFlexibleBox).
185     }
186
187     const_cast<RenderGrid*>(this)->m_grid.clear();
188 }
189
190 void RenderGrid::computePreferredLogicalWidths()
191 {
192     ASSERT(preferredLogicalWidthsDirty());
193
194     m_minPreferredLogicalWidth = 0;
195     m_maxPreferredLogicalWidth = 0;
196
197     // FIXME: We don't take our own logical width into account.
198     computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
199     // FIXME: We should account for min / max logical width.
200
201     LayoutUnit borderAndPaddingInInlineDirection = borderAndPaddingLogicalWidth();
202     m_minPreferredLogicalWidth += borderAndPaddingInInlineDirection;
203     m_maxPreferredLogicalWidth += borderAndPaddingInInlineDirection;
204
205     setPreferredLogicalWidthsDirty(false);
206 }
207
208 LayoutUnit RenderGrid::computePreferredTrackWidth(const Length& length, size_t trackIndex) const
209 {
210     if (length.isFixed()) {
211         // Grid areas don't have borders, margins or paddings so we don't need to account for them.
212         return length.intValue();
213     }
214
215     if (length.isMinContent()) {
216         LayoutUnit minContentSize = 0;
217         GridIterator iterator(m_grid, ForColumns, trackIndex);
218         while (RenderBox* gridItem = iterator.nextGridItem()) {
219             // FIXME: We should include the child's fixed margins like RenderFlexibleBox.
220             minContentSize = std::max(minContentSize, gridItem->minPreferredLogicalWidth());
221         }
222         return minContentSize;
223     }
224
225     if (length.isMaxContent()) {
226         LayoutUnit maxContentSize = 0;
227         GridIterator iterator(m_grid, ForColumns, trackIndex);
228         while (RenderBox* gridItem = iterator.nextGridItem()) {
229             // FIXME: We should include the child's fixed margins like RenderFlexibleBox.
230             maxContentSize = std::max(maxContentSize, gridItem->maxPreferredLogicalWidth());
231         }
232         return maxContentSize;
233     }
234
235     // FIXME: css3-sizing mentions that we should resolve "definite sizes"
236     // (including <percentage> and calc()) but we don't do it elsewhere.
237     return 0;
238 }
239
240 void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks)
241 {
242     const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridColumns() : style()->gridRows();
243     LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding);
244     Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
245     for (size_t i = 0; i < trackStyles.size(); ++i) {
246         GridTrack& track = tracks[i];
247         const Length& minTrackBreadth = trackStyles[i].minTrackBreadth();
248         const Length& maxTrackBreadth = trackStyles[i].maxTrackBreadth();
249
250         track.m_usedBreadth = computeUsedBreadthOfMinLength(direction, minTrackBreadth);
251         track.m_maxBreadth = computeUsedBreadthOfMaxLength(direction, maxTrackBreadth);
252
253         track.m_maxBreadth = std::max(track.m_maxBreadth, track.m_usedBreadth);
254
255         availableLogicalSpace -= track.m_usedBreadth;
256     }
257
258     // FIXME: We shouldn't call resolveContentBasedTrackSizingFunctions if we have no min-content / max-content tracks.
259     resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, availableLogicalSpace);
260
261     if (availableLogicalSpace <= 0)
262         return;
263
264     const size_t tracksSize = tracks.size();
265     Vector<GridTrack*> tracksForDistribution(tracksSize);
266     for (size_t i = 0; i < tracksSize; ++i)
267         tracksForDistribution[i] = tracks.data() + i;
268
269     distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, availableLogicalSpace);
270 }
271
272 LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(TrackSizingDirection direction, const Length& trackLength) const
273 {
274     if (trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage())
275         return computeUsedBreadthOfSpecifiedLength(direction, trackLength);
276
277     ASSERT(trackLength.isMinContent() || trackLength.isMaxContent() || trackLength.isAuto());
278     return 0;
279 }
280
281 LayoutUnit RenderGrid::computeUsedBreadthOfMaxLength(TrackSizingDirection direction, const Length& trackLength) const
282 {
283     if (trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage()) {
284         LayoutUnit computedBreadth = computeUsedBreadthOfSpecifiedLength(direction, trackLength);
285         // FIXME: We should ASSERT that computedBreadth cannot return infinity but it's currently
286         // possible. See https://bugs.webkit.org/show_bug.cgi?id=107053
287         return computedBreadth;
288     }
289
290     ASSERT(trackLength.isMinContent() || trackLength.isMaxContent() || trackLength.isAuto());
291     return infinity;
292 }
293
294 LayoutUnit RenderGrid::computeUsedBreadthOfSpecifiedLength(TrackSizingDirection direction, const Length& trackLength) const
295 {
296     // FIXME: We still need to support calc() here (https://webkit.org/b/103761).
297     ASSERT(trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage());
298     return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : computeContentLogicalHeight(MainOrPreferredSize, style()->logicalHeight()), view());
299 }
300
301 const GridTrackSize& RenderGrid::gridTrackSize(TrackSizingDirection direction, size_t i)
302 {
303     const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridColumns() : style()->gridRows();
304     if (i >= trackStyles.size()) {
305         // FIXME: This should match the default grid sizing (https://webkit.org/b/103333)
306         DEFINE_STATIC_LOCAL(GridTrackSize, defaultAutoSize, (Auto));
307         return defaultAutoSize;
308     }
309     return trackStyles[i];
310 }
311
312 size_t RenderGrid::maximumIndexInDirection(TrackSizingDirection direction) const
313 {
314     const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridColumns() : style()->gridRows();
315
316     size_t maximumIndex = trackStyles.size();
317
318     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
319         GridPosition position = (direction == ForColumns) ? child->style()->gridItemColumn() : child->style()->gridItemRow();
320         maximumIndex = std::max(maximumIndex, resolveGridPosition(position) + 1);
321     }
322
323     return maximumIndex;
324 }
325
326 LayoutUnit RenderGrid::logicalContentHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
327 {
328     // FIXME: We shouldn't force a layout every time this function is called but
329     // 1) Return computeLogicalHeight's value if it's available. Unfortunately computeLogicalHeight
330     // doesn't return if the logical height is available so would need to be changed.
331     // 2) Relayout if the column track's used breadth changed OR the logical height is unavailable.
332     if (!child->needsLayout())
333         child->setNeedsLayout(true, MarkOnlyThis);
334
335     size_t columnTrack = resolveGridPosition(ForColumns, child);
336     child->setOverrideContainingBlockContentLogicalWidth(columnTracks[columnTrack].m_usedBreadth);
337     child->clearOverrideContainingBlockContentLogicalHeight();
338     child->layout();
339     return child->logicalHeight();
340 }
341
342 LayoutUnit RenderGrid::minContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
343 {
344     bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
345     // FIXME: Properly support orthogonal writing mode.
346     if (hasOrthogonalWritingMode)
347         return 0;
348
349     if (direction == ForColumns) {
350         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
351         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
352         return child->minPreferredLogicalWidth();
353     }
354
355     return logicalContentHeightForChild(child, columnTracks);
356 }
357
358 LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
359 {
360     bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
361     // FIXME: Properly support orthogonal writing mode.
362     if (hasOrthogonalWritingMode)
363         return LayoutUnit();
364
365     if (direction == ForColumns) {
366         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
367         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
368         return child->maxPreferredLogicalWidth();
369     }
370
371     return logicalContentHeightForChild(child, columnTracks);
372 }
373
374 void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace)
375 {
376     // FIXME: Split the grid tracks once we support spanning or fractions (step 1 and 2 of the algorithm).
377
378     Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
379
380     for (size_t i = 0; i < tracks.size(); ++i) {
381         const GridTrackSize& trackSize = gridTrackSize(direction, i);
382         GridTrack& track = tracks[i];
383         const Length& minTrackBreadth = trackSize.minTrackBreadth();
384         if (minTrackBreadth.isMinContent() || minTrackBreadth.isMaxContent()) {
385             LayoutUnit oldUsedBreadth = track.m_usedBreadth;
386             resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, i, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
387             availableLogicalSpace -= (track.m_usedBreadth - oldUsedBreadth);
388         }
389
390         if (minTrackBreadth.isMaxContent()) {
391             LayoutUnit oldUsedBreadth = track.m_usedBreadth;
392             resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, i, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
393             availableLogicalSpace -= (track.m_usedBreadth - oldUsedBreadth);
394         }
395
396         const Length& maxTrackBreadth = trackSize.maxTrackBreadth();
397         if (maxTrackBreadth.isMinContent() || maxTrackBreadth.isMaxContent())
398             resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, i, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
399
400         if (maxTrackBreadth.isMaxContent())
401             resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, i, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
402
403         if (track.m_maxBreadth == infinity)
404             track.m_maxBreadth = track.m_usedBreadth;
405     }
406 }
407
408 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, size_t trackIndex, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
409 {
410     GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndex] : rowTracks[trackIndex];
411     GridIterator iterator(m_grid, direction, trackIndex);
412     while (RenderBox* gridItem = iterator.nextGridItem()) {
413         LayoutUnit contentSize = (this->*sizingFunction)(gridItem, direction, columnTracks);
414         LayoutUnit additionalBreadthSpace = contentSize - (track.*trackGetter)();
415         Vector<GridTrack*> tracks;
416         tracks.append(&track);
417         // FIXME: We should pass different values for |tracksForGrowthAboveMaxBreadth|.
418         distributeSpaceToTracks(tracks, &tracks, trackGetter, trackGrowthFunction, additionalBreadthSpace);
419     }
420 }
421
422 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTrack* track2)
423 {
424     return (track1->m_maxBreadth - track1->m_usedBreadth) < (track2->m_maxBreadth - track2->m_usedBreadth);
425 }
426
427 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, LayoutUnit& availableLogicalSpace)
428 {
429     std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
430
431     size_t tracksSize = tracks.size();
432     Vector<LayoutUnit> updatedTrackBreadths(tracksSize);
433
434     for (size_t i = 0; i < tracksSize; ++i) {
435         GridTrack& track = *tracks[i];
436         LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i);
437         LayoutUnit trackBreadth = (tracks[i]->*trackGetter)();
438         LayoutUnit growthShare = std::min(availableLogicalSpaceShare, track.m_maxBreadth - trackBreadth);
439         updatedTrackBreadths[i] = trackBreadth + growthShare;
440         availableLogicalSpace -= growthShare;
441     }
442
443     if (availableLogicalSpace > 0 && tracksForGrowthAboveMaxBreadth) {
444         tracksSize = tracksForGrowthAboveMaxBreadth->size();
445         for (size_t i = 0; i < tracksSize; ++i) {
446             LayoutUnit growthShare = availableLogicalSpace / (tracksSize - i);
447             updatedTrackBreadths[i] += growthShare;
448             availableLogicalSpace -= growthShare;
449         }
450     }
451
452     for (size_t i = 0; i < tracksSize; ++i) {
453         LayoutUnit growth = updatedTrackBreadths[i] - (tracks[i]->*trackGetter)();
454         if (growth >= 0)
455             (tracks[i]->*trackGrowthFunction)(growth);
456     }
457 }
458
459 #ifndef NDEBUG
460 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(TrackSizingDirection direction, const Vector<GridTrack>& tracks)
461 {
462     for (size_t i = 0; i < tracks.size(); ++i) {
463         const GridTrackSize& trackSize = gridTrackSize(direction, i);
464         const Length& minTrackBreadth = trackSize.minTrackBreadth();
465         if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i].m_usedBreadth)
466             return false;
467     }
468     return true;
469 }
470 #endif
471
472 void RenderGrid::placeItemsOnGrid()
473 {
474     ASSERT(m_grid.isEmpty());
475     m_grid.grow(maximumIndexInDirection(ForRows));
476     size_t maximumColumnIndex = maximumIndexInDirection(ForColumns);
477     for (size_t i = 0; i < gridRowCount(); ++i)
478         m_grid[i].grow(maximumColumnIndex);
479
480     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
481         size_t columnTrack = resolveGridPosition(child->style()->gridItemColumn());
482         size_t rowTrack = resolveGridPosition(child->style()->gridItemRow());
483
484         m_grid[rowTrack][columnTrack].append(child);
485     }
486 }
487
488 void RenderGrid::layoutGridItems()
489 {
490     placeItemsOnGrid();
491
492     Vector<GridTrack> columnTracks(gridColumnCount());
493     Vector<GridTrack> rowTracks(gridRowCount());
494     computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks);
495     ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks));
496     computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks);
497     ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, rowTracks));
498
499     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
500         LayoutPoint childPosition = findChildLogicalPosition(child, columnTracks, rowTracks);
501
502         size_t columnTrack = resolveGridPosition(child->style()->gridItemColumn());
503         size_t rowTrack = resolveGridPosition(child->style()->gridItemRow());
504
505         // Because the grid area cannot be styled, we don't need to adjust
506         // the grid breadth to account for 'box-sizing'.
507         LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
508         LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();
509
510         // FIXME: For children in a content sized track, we clear the overrideContainingBlockContentLogicalHeight
511         // in minContentForChild / maxContentForChild which means that we will always relayout the child.
512         if (oldOverrideContainingBlockContentLogicalWidth != columnTracks[columnTrack].m_usedBreadth || oldOverrideContainingBlockContentLogicalHeight != rowTracks[rowTrack].m_usedBreadth)
513             child->setNeedsLayout(true, MarkOnlyThis);
514
515         child->setOverrideContainingBlockContentLogicalWidth(columnTracks[columnTrack].m_usedBreadth);
516         child->setOverrideContainingBlockContentLogicalHeight(rowTracks[rowTrack].m_usedBreadth);
517
518         // FIXME: Grid items should stretch to fill their cells. Once we
519         // implement grid-{column,row}-align, we can also shrink to fit. For
520         // now, just size as if we were a regular child.
521         child->layoutIfNeeded();
522
523         // FIXME: Handle border & padding on the grid element.
524         child->setLogicalLocation(childPosition);
525     }
526
527     for (size_t i = 0; i < rowTracks.size(); ++i)
528         setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);
529
530     // FIXME: We should handle min / max logical height.
531
532     setLogicalHeight(logicalHeight() + borderAndPaddingLogicalHeight());
533     m_grid.clear();
534 }
535
536 size_t RenderGrid::resolveGridPosition(TrackSizingDirection direction, const RenderObject* gridItem) const
537 {
538     const GridPosition& position = (direction == ForColumns) ? gridItem->style()->gridItemColumn() : gridItem->style()->gridItemRow();
539     return resolveGridPosition(position);
540 }
541
542 size_t RenderGrid::resolveGridPosition(const GridPosition& position) const
543 {
544     // FIXME: Handle other values for grid-{row,column} like ranges or line names.
545     switch (position.type()) {
546     case IntegerPosition:
547         // FIXME: What does a non-positive integer mean for a column/row?
548         if (!position.isPositive())
549             return 0;
550
551         return position.integerPosition() - 1;
552     case AutoPosition:
553         // FIXME: We should follow 'grid-auto-flow' for resolution.
554         // Until then, we use the 'grid-auto-flow: none' behavior (which is the default)
555         // and resolve 'auto' as the first row / column.
556         return 0;
557     }
558     ASSERT_NOT_REACHED();
559     return 0;
560 }
561
562 LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
563 {
564     size_t columnTrack = resolveGridPosition(child->style()->gridItemColumn());
565     size_t rowTrack = resolveGridPosition(child->style()->gridItemRow());
566
567     LayoutPoint offset;
568     // FIXME: |columnTrack| and |rowTrack| should be smaller than our column / row count.
569     for (size_t i = 0; i < columnTrack && i < columnTracks.size(); ++i)
570         offset.setX(offset.x() + columnTracks[i].m_usedBreadth);
571     for (size_t i = 0; i < rowTrack && i < rowTracks.size(); ++i)
572         offset.setY(offset.y() + rowTracks[i].m_usedBreadth);
573
574     // FIXME: Handle margins on the grid item.
575     return offset;
576 }
577
578 const char* RenderGrid::renderName() const
579 {
580     if (isFloating())
581         return "RenderGrid (floating)";
582     if (isOutOfFlowPositioned())
583         return "RenderGrid (positioned)";
584     if (isAnonymous())
585         return "RenderGrid (generated)";
586     if (isRelPositioned())
587         return "RenderGrid (relative positioned)";
588     return "RenderGrid";
589 }
590
591 } // namespace WebCore