Home | History | Annotate | Download | only in rendering
      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 "core/rendering/RenderGrid.h"
     28 
     29 #include "core/rendering/LayoutRepainter.h"
     30 #include "core/rendering/RenderLayer.h"
     31 #include "core/rendering/RenderView.h"
     32 #include "core/rendering/style/GridCoordinate.h"
     33 
     34 namespace WebCore {
     35 
     36 static const int infinity = -1;
     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 struct GridTrackForNormalization {
     70     GridTrackForNormalization(const GridTrack& track, double flex)
     71         : m_track(&track)
     72         , m_flex(flex)
     73         , m_normalizedFlexValue(track.m_usedBreadth / flex)
     74     {
     75     }
     76 
     77     // Required by std::sort.
     78     GridTrackForNormalization operator=(const GridTrackForNormalization& o)
     79     {
     80         m_track = o.m_track;
     81         m_flex = o.m_flex;
     82         m_normalizedFlexValue = o.m_normalizedFlexValue;
     83         return *this;
     84     }
     85 
     86     const GridTrack* m_track;
     87     double m_flex;
     88     LayoutUnit m_normalizedFlexValue;
     89 };
     90 
     91 class RenderGrid::GridIterator {
     92     WTF_MAKE_NONCOPYABLE(GridIterator);
     93 public:
     94     // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
     95     // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd column.
     96     GridIterator(const Vector<Vector<Vector<RenderBox*, 1> > >& grid, TrackSizingDirection direction, size_t fixedTrackIndex)
     97         : m_grid(grid)
     98         , m_direction(direction)
     99         , m_rowIndex((direction == ForColumns) ? 0 : fixedTrackIndex)
    100         , m_columnIndex((direction == ForColumns) ? fixedTrackIndex : 0)
    101         , m_childIndex(0)
    102     {
    103         ASSERT(m_rowIndex < m_grid.size());
    104         ASSERT(m_columnIndex < m_grid[0].size());
    105     }
    106 
    107     RenderBox* nextGridItem()
    108     {
    109         if (!m_grid.size())
    110             return 0;
    111 
    112         size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
    113         const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
    114         for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
    115             const Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
    116             if (m_childIndex < children.size())
    117                 return children[m_childIndex++];
    118 
    119             m_childIndex = 0;
    120         }
    121         return 0;
    122     }
    123 
    124     PassOwnPtr<GridCoordinate> nextEmptyGridArea()
    125     {
    126         if (m_grid.isEmpty())
    127             return nullptr;
    128 
    129         size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
    130         const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
    131         for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
    132             const Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
    133             if (children.isEmpty()) {
    134                 OwnPtr<GridCoordinate> result = adoptPtr(new GridCoordinate(GridSpan(m_rowIndex, m_rowIndex), GridSpan(m_columnIndex, m_columnIndex)));
    135                 // Advance the iterator to avoid an infinite loop where we would return the same grid area over and over.
    136                 ++varyingTrackIndex;
    137                 return result.release();
    138             }
    139         }
    140         return nullptr;
    141     }
    142 
    143 private:
    144     const Vector<Vector<Vector<RenderBox*, 1> > >& m_grid;
    145     TrackSizingDirection m_direction;
    146     size_t m_rowIndex;
    147     size_t m_columnIndex;
    148     size_t m_childIndex;
    149 };
    150 
    151 RenderGrid::RenderGrid(Element* element)
    152     : RenderBlock(element)
    153     , m_gridIsDirty(true)
    154     , m_orderIterator(this)
    155 {
    156     // All of our children must be block level.
    157     setChildrenInline(false);
    158 }
    159 
    160 RenderGrid::~RenderGrid()
    161 {
    162 }
    163 
    164 void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
    165 {
    166     RenderBlock::addChild(newChild, beforeChild);
    167 
    168     if (gridIsDirty())
    169         return;
    170 
    171     RenderBox* newChildBox = toRenderBox(newChild);
    172     OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(newChildBox, ForRows);
    173     OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(newChildBox, ForColumns);
    174     if (!rowPositions || !columnPositions) {
    175         // The new child requires the auto-placement algorithm to run so we need to recompute the grid fully.
    176         dirtyGrid();
    177     } else {
    178         if (gridRowCount() <= rowPositions->finalPositionIndex || gridColumnCount() <= columnPositions->finalPositionIndex) {
    179             // FIXME: We could just insert the new child provided we had a primitive to arbitrarily grow the grid.
    180             dirtyGrid();
    181         } else {
    182             insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPositions));
    183         }
    184     }
    185 }
    186 
    187 void RenderGrid::removeChild(RenderObject* child)
    188 {
    189     RenderBlock::removeChild(child);
    190 
    191     if (gridIsDirty())
    192         return;
    193 
    194     ASSERT(child->isBox());
    195     // FIXME: We could avoid dirtying the grid in some cases (e.g. if it's an explicitly positioned element).
    196     dirtyGrid();
    197 }
    198 
    199 void RenderGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    200 {
    201     RenderBlock::styleDidChange(diff, oldStyle);
    202     if (!oldStyle)
    203         return;
    204 
    205     // FIXME: The following checks could be narrowed down if we kept track of which type of grid items we have:
    206     // - explicit grid size changes impact negative explicitely positioned and auto-placed grid items.
    207     // - named grid lines only impact grid items with named grid lines.
    208     // - auto-flow changes only impacts auto-placed children.
    209 
    210     if (explicitGridDidResize(oldStyle)
    211         || namedGridLinesDefinitionDidChange(oldStyle)
    212         || oldStyle->gridAutoFlow() != style()->gridAutoFlow())
    213         dirtyGrid();
    214 }
    215 
    216 bool RenderGrid::explicitGridDidResize(const RenderStyle* oldStyle) const
    217 {
    218     return oldStyle->gridDefinitionColumns().size() != style()->gridDefinitionColumns().size()
    219         || oldStyle->gridDefinitionRows().size() != style()->gridDefinitionRows().size();
    220 }
    221 
    222 bool RenderGrid::namedGridLinesDefinitionDidChange(const RenderStyle* oldStyle) const
    223 {
    224     return oldStyle->namedGridRowLines() != style()->namedGridRowLines()
    225         || oldStyle->namedGridColumnLines() != style()->namedGridColumnLines();
    226 }
    227 
    228 void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
    229 {
    230     ASSERT(needsLayout());
    231 
    232     if (!relayoutChildren && simplifiedLayout())
    233         return;
    234 
    235     // FIXME: Much of this method is boiler plate that matches RenderBox::layoutBlock and Render*FlexibleBox::layoutBlock.
    236     // It would be nice to refactor some of the duplicate code.
    237     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
    238     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
    239 
    240     // Regions changing widths can force us to relayout our children.
    241     RenderFlowThread* flowThread = flowThreadContainingBlock();
    242     if (logicalWidthChangedInRegions(flowThread))
    243         relayoutChildren = true;
    244     if (updateRegionsAndShapesLogicalSize(flowThread))
    245         relayoutChildren = true;
    246 
    247     LayoutSize previousSize = size();
    248 
    249     setLogicalHeight(0);
    250     updateLogicalWidth();
    251 
    252     layoutGridItems();
    253 
    254     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
    255     updateLogicalHeight();
    256 
    257     if (size() != previousSize)
    258         relayoutChildren = true;
    259 
    260     layoutPositionedObjects(relayoutChildren || isRoot());
    261 
    262     computeRegionRangeForBlock(flowThread);
    263 
    264     computeOverflow(oldClientAfterEdge);
    265     statePusher.pop();
    266 
    267     updateLayerTransform();
    268 
    269     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
    270     // we overflow or not.
    271     if (hasOverflowClip())
    272         layer()->updateScrollInfoAfterLayout();
    273 
    274     repainter.repaintAfterLayout();
    275 
    276     clearNeedsLayout();
    277 }
    278 
    279 void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
    280 {
    281     const_cast<RenderGrid*>(this)->placeItemsOnGrid();
    282 
    283     // FIXME: This is an inefficient way to fill our sizes as it will try every grid areas, when we would
    284     // only want to account for fixed grid tracks and grid items. Also this will be incorrect if we have spanning
    285     // grid items.
    286     for (size_t i = 0; i < gridColumnCount(); ++i) {
    287         const GridTrackSize& trackSize = gridTrackSize(ForColumns, i);
    288         LayoutUnit minTrackBreadth = computePreferredTrackWidth(trackSize.minTrackBreadth(), i);
    289         LayoutUnit maxTrackBreadth = computePreferredTrackWidth(trackSize.maxTrackBreadth(), i);
    290         maxTrackBreadth = std::max(maxTrackBreadth, minTrackBreadth);
    291 
    292         minLogicalWidth += minTrackBreadth;
    293         maxLogicalWidth += maxTrackBreadth;
    294 
    295         // FIXME: This should add in the scrollbarWidth (e.g. see RenderFlexibleBox).
    296     }
    297 }
    298 
    299 void RenderGrid::computePreferredLogicalWidths()
    300 {
    301     ASSERT(preferredLogicalWidthsDirty());
    302 
    303     m_minPreferredLogicalWidth = 0;
    304     m_maxPreferredLogicalWidth = 0;
    305 
    306     // FIXME: We don't take our own logical width into account. Once we do, we need to make sure
    307     // we apply (and test the interaction with) min-width / max-width.
    308 
    309     computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
    310 
    311     LayoutUnit borderAndPaddingInInlineDirection = borderAndPaddingLogicalWidth();
    312     m_minPreferredLogicalWidth += borderAndPaddingInInlineDirection;
    313     m_maxPreferredLogicalWidth += borderAndPaddingInInlineDirection;
    314 
    315     setPreferredLogicalWidthsDirty(false);
    316 }
    317 
    318 LayoutUnit RenderGrid::computePreferredTrackWidth(const GridLength& gridLength, size_t trackIndex) const
    319 {
    320     if (gridLength.isFlex())
    321         return 0;
    322 
    323     const Length& length = gridLength.length();
    324 
    325     if (length.isFixed()) {
    326         // Grid areas don't have borders, margins or paddings so we don't need to account for them.
    327         return length.intValue();
    328     }
    329 
    330     if (length.isMinContent()) {
    331         LayoutUnit minContentSize = 0;
    332         GridIterator iterator(m_grid, ForColumns, trackIndex);
    333         while (RenderBox* gridItem = iterator.nextGridItem()) {
    334             // FIXME: We should include the child's fixed margins like RenderFlexibleBox.
    335             minContentSize = std::max(minContentSize, gridItem->minPreferredLogicalWidth());
    336         }
    337         return minContentSize;
    338     }
    339 
    340     if (length.isMaxContent()) {
    341         LayoutUnit maxContentSize = 0;
    342         GridIterator iterator(m_grid, ForColumns, trackIndex);
    343         while (RenderBox* gridItem = iterator.nextGridItem()) {
    344             // FIXME: We should include the child's fixed margins like RenderFlexibleBox.
    345             maxContentSize = std::max(maxContentSize, gridItem->maxPreferredLogicalWidth());
    346         }
    347         return maxContentSize;
    348     }
    349 
    350     // FIXME: css3-sizing mentions that we should resolve "definite sizes"
    351     // (including <percentage> and calc()) but we don't do it elsewhere.
    352     return 0;
    353 }
    354 
    355 void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks)
    356 {
    357     LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding);
    358     Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
    359     for (size_t i = 0; i < tracks.size(); ++i) {
    360         GridTrack& track = tracks[i];
    361         const GridTrackSize& trackSize = gridTrackSize(direction, i);
    362         const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
    363         const GridLength& maxTrackBreadth = trackSize.maxTrackBreadth();
    364 
    365         track.m_usedBreadth = computeUsedBreadthOfMinLength(direction, minTrackBreadth);
    366         track.m_maxBreadth = computeUsedBreadthOfMaxLength(direction, maxTrackBreadth, track.m_usedBreadth);
    367 
    368         track.m_maxBreadth = std::max(track.m_maxBreadth, track.m_usedBreadth);
    369     }
    370 
    371     // FIXME: We shouldn't call resolveContentBasedTrackSizingFunctions if we have no min-content / max-content tracks.
    372     resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, availableLogicalSpace);
    373 
    374     if (availableLogicalSpace <= 0)
    375         return;
    376 
    377     const size_t tracksSize = tracks.size();
    378     Vector<GridTrack*> tracksForDistribution(tracksSize);
    379     for (size_t i = 0; i < tracksSize; ++i)
    380         tracksForDistribution[i] = tracks.data() + i;
    381 
    382     distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, availableLogicalSpace);
    383 
    384     // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
    385 
    386     // FIXME: Handle the case where RemainingSpace is not defined.
    387     double normalizedFractionBreadth = computeNormalizedFractionBreadth(tracks, direction, availableLogicalSpace);
    388     for (size_t i = 0; i < tracksSize; ++i) {
    389         const GridTrackSize& trackSize = gridTrackSize(direction, i);
    390         if (!trackSize.maxTrackBreadth().isFlex())
    391             continue;
    392 
    393         tracks[i].m_usedBreadth = std::max<LayoutUnit>(tracks[i].m_usedBreadth, normalizedFractionBreadth * trackSize.maxTrackBreadth().flex());
    394     }
    395 }
    396 
    397 LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(TrackSizingDirection direction, const GridLength& gridLength) const
    398 {
    399     if (gridLength.isFlex())
    400         return 0;
    401 
    402     const Length& trackLength = gridLength.length();
    403     ASSERT(!trackLength.isAuto());
    404     if (trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage())
    405         return computeUsedBreadthOfSpecifiedLength(direction, trackLength);
    406 
    407     ASSERT(trackLength.isMinContent() || trackLength.isMaxContent());
    408     return 0;
    409 }
    410 
    411 LayoutUnit RenderGrid::computeUsedBreadthOfMaxLength(TrackSizingDirection direction, const GridLength& gridLength, LayoutUnit usedBreadth) const
    412 {
    413     if (gridLength.isFlex())
    414         return usedBreadth;
    415 
    416     const Length& trackLength = gridLength.length();
    417     ASSERT(!trackLength.isAuto());
    418     if (trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage()) {
    419         LayoutUnit computedBreadth = computeUsedBreadthOfSpecifiedLength(direction, trackLength);
    420         ASSERT(computedBreadth != infinity);
    421         return computedBreadth;
    422     }
    423 
    424     ASSERT(trackLength.isMinContent() || trackLength.isMaxContent());
    425     return infinity;
    426 }
    427 
    428 LayoutUnit RenderGrid::computeUsedBreadthOfSpecifiedLength(TrackSizingDirection direction, const Length& trackLength) const
    429 {
    430     // FIXME: We still need to support calc() here (https://webkit.org/b/103761).
    431     ASSERT(trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage());
    432     // FIXME: The -1 here should be replaced by whatever the intrinsic height of the grid is.
    433     return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : computeContentLogicalHeight(style()->logicalHeight(), -1), view());
    434 }
    435 
    436 static bool sortByGridNormalizedFlexValue(const GridTrackForNormalization& track1, const GridTrackForNormalization& track2)
    437 {
    438     return track1.m_normalizedFlexValue < track2.m_normalizedFlexValue;
    439 }
    440 
    441 double RenderGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, TrackSizingDirection direction, LayoutUnit availableLogicalSpace) const
    442 {
    443     // |availableLogicalSpace| already accounts for the used breadths so no need to remove it here.
    444 
    445     Vector<GridTrackForNormalization> tracksForNormalization;
    446     for (size_t i = 0; i < tracks.size(); ++i) {
    447         const GridTrackSize& trackSize = gridTrackSize(direction, i);
    448         if (!trackSize.maxTrackBreadth().isFlex())
    449             continue;
    450 
    451         tracksForNormalization.append(GridTrackForNormalization(tracks[i], trackSize.maxTrackBreadth().flex()));
    452     }
    453 
    454     // FIXME: Ideally we shouldn't come here without any <flex> grid track.
    455     if (tracksForNormalization.isEmpty())
    456         return LayoutUnit();
    457 
    458     std::sort(tracksForNormalization.begin(), tracksForNormalization.end(), sortByGridNormalizedFlexValue);
    459 
    460     // These values work together: as we walk over our grid tracks, we increase fractionValueBasedOnGridItemsRatio
    461     // to match a grid track's usedBreadth to <flex> ratio until the total fractions sized grid tracks wouldn't
    462     // fit into availableLogicalSpaceIgnoringFractionTracks.
    463     double accumulatedFractions = 0;
    464     LayoutUnit fractionValueBasedOnGridItemsRatio = 0;
    465     LayoutUnit availableLogicalSpaceIgnoringFractionTracks = availableLogicalSpace;
    466 
    467     for (size_t i = 0; i < tracksForNormalization.size(); ++i) {
    468         const GridTrackForNormalization& track = tracksForNormalization[i];
    469         if (track.m_normalizedFlexValue > fractionValueBasedOnGridItemsRatio) {
    470             // If the normalized flex value (we ordered |tracksForNormalization| by increasing normalized flex value)
    471             // will make us overflow our container, then stop. We have the previous step's ratio is the best fit.
    472             if (track.m_normalizedFlexValue * accumulatedFractions > availableLogicalSpaceIgnoringFractionTracks)
    473                 break;
    474 
    475             fractionValueBasedOnGridItemsRatio = track.m_normalizedFlexValue;
    476         }
    477 
    478         accumulatedFractions += track.m_flex;
    479         // This item was processed so we re-add its used breadth to the available space to accurately count the remaining space.
    480         availableLogicalSpaceIgnoringFractionTracks += track.m_track->m_usedBreadth;
    481     }
    482 
    483     return availableLogicalSpaceIgnoringFractionTracks / accumulatedFractions;
    484 }
    485 
    486 const GridTrackSize& RenderGrid::gridTrackSize(TrackSizingDirection direction, size_t i) const
    487 {
    488     const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridDefinitionColumns() : style()->gridDefinitionRows();
    489     if (i >= trackStyles.size())
    490         return (direction == ForColumns) ? style()->gridAutoColumns() : style()->gridAutoRows();
    491 
    492     return trackStyles[i];
    493 }
    494 
    495 size_t RenderGrid::explicitGridColumnCount() const
    496 {
    497     return style()->gridDefinitionColumns().size();
    498 }
    499 
    500 size_t RenderGrid::explicitGridRowCount() const
    501 {
    502     return style()->gridDefinitionRows().size();
    503 }
    504 
    505 size_t RenderGrid::explicitGridSizeForSide(GridPositionSide side) const
    506 {
    507     return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount() : explicitGridRowCount();
    508 }
    509 
    510 LayoutUnit RenderGrid::logicalContentHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
    511 {
    512     // FIXME: We shouldn't force a layout every time this function is called but
    513     // 1) Return computeLogicalHeight's value if it's available. Unfortunately computeLogicalHeight
    514     // doesn't return if the logical height is available so would need to be changed.
    515     // 2) Relayout if the column track's used breadth changed OR the logical height is unavailable.
    516     if (!child->needsLayout())
    517         child->setNeedsLayout(MarkOnlyThis);
    518 
    519     child->setOverrideContainingBlockContentLogicalWidth(gridAreaBreadthForChild(child, ForColumns, columnTracks));
    520     // If |child| has a percentage logical height, we shouldn't let it override its intrinsic height, which is
    521     // what we are interested in here. Thus we need to set the override logical height to -1 (no possible resolution).
    522     child->setOverrideContainingBlockContentLogicalHeight(-1);
    523     child->layout();
    524     return child->logicalHeight();
    525 }
    526 
    527 LayoutUnit RenderGrid::minContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
    528 {
    529     bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
    530     // FIXME: Properly support orthogonal writing mode.
    531     if (hasOrthogonalWritingMode)
    532         return 0;
    533 
    534     if (direction == ForColumns) {
    535         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
    536         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
    537         return child->minPreferredLogicalWidth();
    538     }
    539 
    540     return logicalContentHeightForChild(child, columnTracks);
    541 }
    542 
    543 LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
    544 {
    545     bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
    546     // FIXME: Properly support orthogonal writing mode.
    547     if (hasOrthogonalWritingMode)
    548         return LayoutUnit();
    549 
    550     if (direction == ForColumns) {
    551         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
    552         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
    553         return child->maxPreferredLogicalWidth();
    554     }
    555 
    556     return logicalContentHeightForChild(child, columnTracks);
    557 }
    558 
    559 void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace)
    560 {
    561     // FIXME: Split the grid tracks into groups that doesn't overlap a <flex> grid track (crbug.com/235258).
    562 
    563     Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
    564 
    565     // FIXME: Per step 2 of the specification, we should order the grid items by increasing span.
    566     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    567         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
    568         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
    569         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
    570         resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
    571     }
    572 
    573     for (size_t i = 0; i < tracks.size(); ++i) {
    574         GridTrack& track = tracks[i];
    575         if (track.m_maxBreadth == infinity)
    576             track.m_maxBreadth = track.m_usedBreadth;
    577 
    578         availableLogicalSpace -= track.m_usedBreadth;
    579     }
    580 }
    581 
    582 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
    583 {
    584     const GridCoordinate coordinate = cachedGridCoordinate(gridItem);
    585     const size_t initialTrackIndex = (direction == ForColumns) ? coordinate.columns.initialPositionIndex : coordinate.rows.initialPositionIndex;
    586     const size_t finalTrackIndex = (direction == ForColumns) ? coordinate.columns.finalPositionIndex : coordinate.rows.finalPositionIndex;
    587 
    588     Vector<GridTrack*> tracks;
    589     for (size_t trackIndex = initialTrackIndex; trackIndex <= finalTrackIndex; ++trackIndex) {
    590         const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
    591         if (!(trackSize.*filterFunction)())
    592             continue;
    593 
    594         GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndex] : rowTracks[trackIndex];
    595         tracks.append(&track);
    596     }
    597 
    598     LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, columnTracks);
    599     for (size_t trackIndexForSpace = initialTrackIndex; trackIndexForSpace <= finalTrackIndex; ++trackIndexForSpace) {
    600         GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndexForSpace] : rowTracks[trackIndexForSpace];
    601         additionalBreadthSpace -= (track.*trackGetter)();
    602     }
    603 
    604     // FIXME: We should pass different values for |tracksForGrowthAboveMaxBreadth|.
    605     distributeSpaceToTracks(tracks, &tracks, trackGetter, trackGrowthFunction, additionalBreadthSpace);
    606 }
    607 
    608 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTrack* track2)
    609 {
    610     return (track1->m_maxBreadth - track1->m_usedBreadth) < (track2->m_maxBreadth - track2->m_usedBreadth);
    611 }
    612 
    613 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, LayoutUnit& availableLogicalSpace)
    614 {
    615     std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
    616 
    617     size_t tracksSize = tracks.size();
    618     Vector<LayoutUnit> updatedTrackBreadths(tracksSize);
    619 
    620     for (size_t i = 0; i < tracksSize; ++i) {
    621         GridTrack& track = *tracks[i];
    622         LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i);
    623         LayoutUnit trackBreadth = (tracks[i]->*trackGetter)();
    624         LayoutUnit growthShare = std::max(LayoutUnit(), std::min(availableLogicalSpaceShare, track.m_maxBreadth - trackBreadth));
    625         // We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function.
    626         updatedTrackBreadths[i] = trackBreadth + growthShare;
    627         availableLogicalSpace -= growthShare;
    628     }
    629 
    630     if (availableLogicalSpace > 0 && tracksForGrowthAboveMaxBreadth) {
    631         tracksSize = tracksForGrowthAboveMaxBreadth->size();
    632         for (size_t i = 0; i < tracksSize; ++i) {
    633             LayoutUnit growthShare = availableLogicalSpace / (tracksSize - i);
    634             updatedTrackBreadths[i] += growthShare;
    635             availableLogicalSpace -= growthShare;
    636         }
    637     }
    638 
    639     for (size_t i = 0; i < tracksSize; ++i) {
    640         LayoutUnit growth = updatedTrackBreadths[i] - (tracks[i]->*trackGetter)();
    641         if (growth >= 0)
    642             (tracks[i]->*trackGrowthFunction)(growth);
    643     }
    644 }
    645 
    646 #ifndef NDEBUG
    647 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(TrackSizingDirection direction, const Vector<GridTrack>& tracks)
    648 {
    649     for (size_t i = 0; i < tracks.size(); ++i) {
    650         const GridTrackSize& trackSize = gridTrackSize(direction, i);
    651         const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
    652         if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i].m_usedBreadth)
    653             return false;
    654     }
    655     return true;
    656 }
    657 #endif
    658 
    659 void RenderGrid::growGrid(TrackSizingDirection direction)
    660 {
    661     if (direction == ForColumns) {
    662         const size_t oldColumnSize = m_grid[0].size();
    663         for (size_t row = 0; row < m_grid.size(); ++row)
    664             m_grid[row].grow(oldColumnSize + 1);
    665     } else {
    666         const size_t oldRowSize = m_grid.size();
    667         m_grid.grow(oldRowSize + 1);
    668         m_grid[oldRowSize].grow(m_grid[0].size());
    669     }
    670 }
    671 
    672 void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
    673 {
    674     m_grid[coordinate.rows.initialPositionIndex][coordinate.columns.initialPositionIndex].append(child);
    675     m_gridItemCoordinate.set(child, coordinate);
    676 }
    677 
    678 void RenderGrid::insertItemIntoGrid(RenderBox* child, size_t rowTrack, size_t columnTrack)
    679 {
    680     const GridSpan& rowSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForRows, rowTrack);
    681     const GridSpan& columnSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForColumns, columnTrack);
    682     insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
    683 }
    684 
    685 void RenderGrid::placeItemsOnGrid()
    686 {
    687     if (!gridIsDirty())
    688         return;
    689 
    690     ASSERT(m_gridItemCoordinate.isEmpty());
    691 
    692     populateExplicitGridAndOrderIterator();
    693 
    694     // We clear the dirty bit here as the grid sizes have been updated, this means
    695     // that we can safely call gridRowCount() / gridColumnCount().
    696     m_gridIsDirty = false;
    697 
    698     Vector<RenderBox*> autoMajorAxisAutoGridItems;
    699     Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
    700     GridAutoFlow autoFlow = style()->gridAutoFlow();
    701     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
    702         // FIXME: We never re-resolve positions if the grid is grown during auto-placement which may lead auto / <integer>
    703         // positions to not match the author's intent. The specification is unclear on what should be done in this case.
    704         OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
    705         OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
    706         if (!rowPositions || !columnPositions) {
    707             GridSpan* majorAxisPositions = (autoPlacementMajorAxisDirection() == ForColumns) ? columnPositions.get() : rowPositions.get();
    708             if (!majorAxisPositions)
    709                 autoMajorAxisAutoGridItems.append(child);
    710             else
    711                 specifiedMajorAxisAutoGridItems.append(child);
    712             continue;
    713         }
    714         insertItemIntoGrid(child, GridCoordinate(*rowPositions, *columnPositions));
    715     }
    716 
    717     ASSERT(gridRowCount() >= style()->gridDefinitionRows().size());
    718     ASSERT(gridColumnCount() >= style()->gridDefinitionColumns().size());
    719 
    720     if (autoFlow == AutoFlowNone) {
    721         // If we did collect some grid items, they won't be placed thus never laid out.
    722         ASSERT(!autoMajorAxisAutoGridItems.size());
    723         ASSERT(!specifiedMajorAxisAutoGridItems.size());
    724         return;
    725     }
    726 
    727     placeSpecifiedMajorAxisItemsOnGrid(specifiedMajorAxisAutoGridItems);
    728     placeAutoMajorAxisItemsOnGrid(autoMajorAxisAutoGridItems);
    729 
    730     m_grid.shrinkToFit();
    731 }
    732 
    733 void RenderGrid::populateExplicitGridAndOrderIterator()
    734 {
    735     OrderIteratorPopulator populator(m_orderIterator);
    736 
    737     size_t maximumRowIndex = std::max<size_t>(1, explicitGridRowCount());
    738     size_t maximumColumnIndex = std::max<size_t>(1, explicitGridColumnCount());
    739 
    740     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    741         populator.collectChild(child);
    742 
    743         // This function bypasses the cache (cachedGridCoordinate()) as it is used to build it.
    744         OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
    745         OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
    746 
    747         // |positions| is 0 if we need to run the auto-placement algorithm. Our estimation ignores
    748         // this case as the auto-placement algorithm will grow the grid as needed.
    749         if (rowPositions)
    750             maximumRowIndex = std::max(maximumRowIndex, rowPositions->finalPositionIndex + 1);
    751         if (columnPositions)
    752             maximumColumnIndex = std::max(maximumColumnIndex, columnPositions->finalPositionIndex + 1);
    753     }
    754 
    755     m_grid.grow(maximumRowIndex);
    756     for (size_t i = 0; i < m_grid.size(); ++i)
    757         m_grid[i].grow(maximumColumnIndex);
    758 }
    759 
    760 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
    761 {
    762     for (size_t i = 0; i < autoGridItems.size(); ++i) {
    763         OwnPtr<GridSpan> majorAxisPositions = resolveGridPositionsFromStyle(autoGridItems[i], autoPlacementMajorAxisDirection());
    764         GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->initialPositionIndex);
    765         if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
    766             insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
    767             continue;
    768         }
    769 
    770         growGrid(autoPlacementMinorAxisDirection());
    771         OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
    772         ASSERT(emptyGridArea);
    773         insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
    774     }
    775 }
    776 
    777 void RenderGrid::placeAutoMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
    778 {
    779     for (size_t i = 0; i < autoGridItems.size(); ++i)
    780         placeAutoMajorAxisItemOnGrid(autoGridItems[i]);
    781 }
    782 
    783 void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
    784 {
    785     OwnPtr<GridSpan> minorAxisPositions = resolveGridPositionsFromStyle(gridItem, autoPlacementMinorAxisDirection());
    786     ASSERT(!resolveGridPositionsFromStyle(gridItem, autoPlacementMajorAxisDirection()));
    787     size_t minorAxisIndex = 0;
    788     if (minorAxisPositions) {
    789         minorAxisIndex = minorAxisPositions->initialPositionIndex;
    790         GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisIndex);
    791         if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
    792             insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
    793             return;
    794         }
    795     } else {
    796         const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : gridRowCount();
    797         for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) {
    798             GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisIndex);
    799             if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
    800                 insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
    801                 return;
    802             }
    803         }
    804     }
    805 
    806     // We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it.
    807     const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? m_grid[0].size() : minorAxisIndex;
    808     const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : m_grid.size();
    809     growGrid(autoPlacementMajorAxisDirection());
    810     insertItemIntoGrid(gridItem, rowIndex, columnIndex);
    811 }
    812 
    813 RenderGrid::TrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
    814 {
    815     GridAutoFlow flow = style()->gridAutoFlow();
    816     ASSERT(flow != AutoFlowNone);
    817     return (flow == AutoFlowColumn) ? ForColumns : ForRows;
    818 }
    819 
    820 RenderGrid::TrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
    821 {
    822     GridAutoFlow flow = style()->gridAutoFlow();
    823     ASSERT(flow != AutoFlowNone);
    824     return (flow == AutoFlowColumn) ? ForRows : ForColumns;
    825 }
    826 
    827 void RenderGrid::dirtyGrid()
    828 {
    829     m_grid.resize(0);
    830     m_gridItemCoordinate.clear();
    831     m_gridIsDirty = true;
    832 }
    833 
    834 void RenderGrid::layoutGridItems()
    835 {
    836     placeItemsOnGrid();
    837 
    838     Vector<GridTrack> columnTracks(gridColumnCount());
    839     Vector<GridTrack> rowTracks(gridRowCount());
    840     computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks);
    841     ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks));
    842     computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks);
    843     ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, rowTracks));
    844 
    845     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    846         LayoutPoint childPosition = findChildLogicalPosition(child, columnTracks, rowTracks);
    847 
    848         // Because the grid area cannot be styled, we don't need to adjust
    849         // the grid breadth to account for 'box-sizing'.
    850         LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
    851         LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();
    852 
    853         // FIXME: For children in a content sized track, we clear the overrideContainingBlockContentLogicalHeight
    854         // in minContentForChild / maxContentForChild which means that we will always relayout the child.
    855         LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, columnTracks);
    856         LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, rowTracks);
    857         if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight)
    858             child->setNeedsLayout(MarkOnlyThis);
    859 
    860         child->setOverrideContainingBlockContentLogicalWidth(overrideContainingBlockContentLogicalWidth);
    861         child->setOverrideContainingBlockContentLogicalHeight(overrideContainingBlockContentLogicalHeight);
    862 
    863         LayoutRect oldChildRect = child->frameRect();
    864 
    865         // FIXME: Grid items should stretch to fill their cells. Once we
    866         // implement grid-{column,row}-align, we can also shrink to fit. For
    867         // now, just size as if we were a regular child.
    868         child->layoutIfNeeded();
    869 
    870         // FIXME: Handle border & padding on the grid element.
    871         child->setLogicalLocation(childPosition);
    872 
    873         // If the child moved, we have to repaint it as well as any floating/positioned
    874         // descendants. An exception is if we need a layout. In this case, we know we're going to
    875         // repaint ourselves (and the child) anyway.
    876         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
    877             child->repaintDuringLayoutIfMoved(oldChildRect);
    878     }
    879 
    880     for (size_t i = 0; i < rowTracks.size(); ++i)
    881         setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);
    882 
    883     // FIXME: We should handle min / max logical height.
    884 
    885     setLogicalHeight(logicalHeight() + borderAndPaddingLogicalHeight());
    886 }
    887 
    888 GridCoordinate RenderGrid::cachedGridCoordinate(const RenderBox* gridItem) const
    889 {
    890     ASSERT(m_gridItemCoordinate.contains(gridItem));
    891     return m_gridItemCoordinate.get(gridItem);
    892 }
    893 
    894 GridSpan RenderGrid::resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, TrackSizingDirection, size_t initialPosition) const
    895 {
    896     // FIXME: We don't support spanning with auto positions yet. Once we do, this is wrong. Also we should make
    897     // sure the grid can accomodate the new item as we only grow 1 position in a given direction.
    898     return GridSpan(initialPosition, initialPosition);
    899 }
    900 
    901 PassOwnPtr<GridSpan> RenderGrid::resolveGridPositionsFromStyle(const RenderBox* gridItem, TrackSizingDirection direction) const
    902 {
    903     const GridPosition& initialPosition = (direction == ForColumns) ? gridItem->style()->gridColumnStart() : gridItem->style()->gridRowStart();
    904     const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide;
    905     const GridPosition& finalPosition = (direction == ForColumns) ? gridItem->style()->gridColumnEnd() : gridItem->style()->gridRowEnd();
    906     const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide;
    907 
    908     // We should NEVER see both spans as they should have been handled during style resolve.
    909     ASSERT(!initialPosition.isSpan() || !finalPosition.isSpan());
    910 
    911     if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
    912         if (style()->gridAutoFlow() == AutoFlowNone)
    913             return adoptPtr(new GridSpan(0, 0));
    914 
    915         // We can't get our grid positions without running the auto placement algorithm.
    916         return nullptr;
    917     }
    918 
    919     if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
    920         // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
    921         const size_t finalResolvedPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
    922         return resolveGridPositionAgainstOppositePosition(finalResolvedPosition, initialPosition, initialPositionSide);
    923     }
    924 
    925     if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
    926         // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
    927         const size_t initialResolvedPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
    928         return resolveGridPositionAgainstOppositePosition(initialResolvedPosition, finalPosition, finalPositionSide);
    929     }
    930 
    931     size_t resolvedInitialPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
    932     size_t resolvedFinalPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
    933 
    934     // If 'grid-after' specifies a line at or before that specified by 'grid-before', it computes to 'span 1'.
    935     if (resolvedFinalPosition < resolvedInitialPosition)
    936         resolvedFinalPosition = resolvedInitialPosition;
    937 
    938     return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
    939 }
    940 
    941 inline static size_t adjustGridPositionForAfterEndSide(size_t resolvedPosition)
    942 {
    943     return resolvedPosition ? resolvedPosition - 1 : 0;
    944 }
    945 
    946 static size_t adjustGridPositionForSide(size_t resolvedPosition, GridPositionSide side)
    947 {
    948     // An item finishing on the N-th line belongs to the N-1-th cell.
    949     if (side == ColumnEndSide || side == RowEndSide)
    950         return adjustGridPositionForAfterEndSide(resolvedPosition);
    951 
    952     return resolvedPosition;
    953 }
    954 
    955 size_t RenderGrid::resolveNamedGridLinePositionFromStyle(const GridPosition& position, GridPositionSide side) const
    956 {
    957     ASSERT(!position.namedGridLine().isNull());
    958 
    959     const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
    960     NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
    961     if (it == gridLinesNames.end()) {
    962         if (position.isPositive())
    963             return 0;
    964         const size_t lastLine = explicitGridSizeForSide(side);
    965         return adjustGridPositionForSide(lastLine, side);
    966     }
    967 
    968     size_t namedGridLineIndex;
    969     if (position.isPositive())
    970         namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
    971     else
    972         namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
    973     return adjustGridPositionForSide(it->value[namedGridLineIndex], side);
    974 }
    975 
    976 size_t RenderGrid::resolveGridPositionFromStyle(const GridPosition& position, GridPositionSide side) const
    977 {
    978     switch (position.type()) {
    979     case ExplicitPosition: {
    980         ASSERT(position.integerPosition());
    981 
    982         if (!position.namedGridLine().isNull())
    983             return resolveNamedGridLinePositionFromStyle(position, side);
    984 
    985         // Handle <integer> explicit position.
    986         if (position.isPositive())
    987             return adjustGridPositionForSide(position.integerPosition() - 1, side);
    988 
    989         size_t resolvedPosition = abs(position.integerPosition()) - 1;
    990         const size_t endOfTrack = explicitGridSizeForSide(side);
    991 
    992         // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
    993         if (endOfTrack < resolvedPosition)
    994             return 0;
    995 
    996         return adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
    997     }
    998     case NamedGridAreaPosition:
    999     {
   1000         NamedGridAreaMap::const_iterator it = style()->namedGridArea().find(position.namedGridLine());
   1001         // Unknown grid area should have been computed to 'auto' by now.
   1002         ASSERT(it != style()->namedGridArea().end());
   1003         const GridCoordinate& gridAreaCoordinate = it->value;
   1004         switch (side) {
   1005         case ColumnStartSide:
   1006             return gridAreaCoordinate.columns.initialPositionIndex;
   1007         case ColumnEndSide:
   1008             return gridAreaCoordinate.columns.finalPositionIndex;
   1009         case RowStartSide:
   1010             return gridAreaCoordinate.rows.initialPositionIndex;
   1011         case RowEndSide:
   1012             return gridAreaCoordinate.rows.finalPositionIndex;
   1013         }
   1014         ASSERT_NOT_REACHED();
   1015         return 0;
   1016     }
   1017     case AutoPosition:
   1018     case SpanPosition:
   1019         // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
   1020         ASSERT_NOT_REACHED();
   1021         return 0;
   1022     }
   1023     ASSERT_NOT_REACHED();
   1024     return 0;
   1025 }
   1026 
   1027 PassOwnPtr<GridSpan> RenderGrid::resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
   1028 {
   1029     if (position.isAuto())
   1030         return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
   1031 
   1032     ASSERT(position.isSpan());
   1033     ASSERT(position.spanPosition() > 0);
   1034 
   1035     if (!position.namedGridLine().isNull()) {
   1036         // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
   1037         return resolveNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, side);
   1038     }
   1039 
   1040     // 'span 1' is contained inside a single grid track regardless of the direction.
   1041     // That's why the CSS span value is one more than the offset we apply.
   1042     size_t positionOffset = position.spanPosition() - 1;
   1043     if (side == ColumnStartSide || side == RowStartSide) {
   1044         size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition - positionOffset);
   1045         return GridSpan::create(initialResolvedPosition, resolvedOppositePosition);
   1046     }
   1047 
   1048     return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition + positionOffset);
   1049 }
   1050 
   1051 PassOwnPtr<GridSpan> RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
   1052 {
   1053     ASSERT(position.isSpan());
   1054     ASSERT(!position.namedGridLine().isNull());
   1055     // Negative positions are not allowed per the specification and should have been handled during parsing.
   1056     ASSERT(position.spanPosition() > 0);
   1057 
   1058     const NamedGridLinesMap& gridLinesNames = (side == ColumnStartSide || side == ColumnEndSide) ? style()->namedGridColumnLines() : style()->namedGridRowLines();
   1059     NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
   1060 
   1061     // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
   1062     // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
   1063     if (it == gridLinesNames.end())
   1064         return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
   1065 
   1066     if (side == RowStartSide || side == ColumnStartSide)
   1067         return resolveBeforeStartNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
   1068 
   1069     return resolveAfterEndNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
   1070 }
   1071 
   1072 PassOwnPtr<GridSpan> RenderGrid::resolveBeforeStartNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) const
   1073 {
   1074     // The grid line inequality needs to be strict (which doesn't match the after / end case) because |resolvedOppositePosition|
   1075     // is already converted to an index in our grid representation (ie one was removed from the grid line to account for the side).
   1076     // FIXME: This could be a binary search as |gridLines| is ordered.
   1077     int firstLineBeforeOppositePositionIndex = gridLines.size() - 1;
   1078     for (; firstLineBeforeOppositePositionIndex >= 0 && gridLines[firstLineBeforeOppositePositionIndex] > resolvedOppositePosition; --firstLineBeforeOppositePositionIndex) { }
   1079 
   1080     size_t gridLineIndex = std::max<int>(0, firstLineBeforeOppositePositionIndex - position.spanPosition() + 1);
   1081     size_t resolvedGridLinePosition = gridLines[gridLineIndex];
   1082     if (resolvedGridLinePosition > resolvedOppositePosition)
   1083         resolvedGridLinePosition = resolvedOppositePosition;
   1084     return GridSpan::create(resolvedGridLinePosition, resolvedOppositePosition);
   1085 }
   1086 
   1087 PassOwnPtr<GridSpan> RenderGrid::resolveAfterEndNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) const
   1088 {
   1089     // FIXME: This could be a binary search as |gridLines| is ordered.
   1090     size_t firstLineAfterOppositePositionIndex = 0;
   1091     for (; firstLineAfterOppositePositionIndex < gridLines.size() && gridLines[firstLineAfterOppositePositionIndex] <= resolvedOppositePosition; ++firstLineAfterOppositePositionIndex) { }
   1092 
   1093     size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
   1094     size_t resolvedGridLinePosition = adjustGridPositionForAfterEndSide(gridLines[gridLineIndex]);
   1095     if (resolvedGridLinePosition < resolvedOppositePosition)
   1096         resolvedGridLinePosition = resolvedOppositePosition;
   1097     return GridSpan::create(resolvedOppositePosition, resolvedGridLinePosition);
   1098 }
   1099 
   1100 LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox* child, TrackSizingDirection direction, const Vector<GridTrack>& tracks) const
   1101 {
   1102     const GridCoordinate& coordinate = cachedGridCoordinate(child);
   1103     const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
   1104     LayoutUnit gridAreaBreadth = 0;
   1105     for (size_t trackIndex = span.initialPositionIndex; trackIndex <= span.finalPositionIndex; ++trackIndex)
   1106         gridAreaBreadth += tracks[trackIndex].m_usedBreadth;
   1107     return gridAreaBreadth;
   1108 }
   1109 
   1110 LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
   1111 {
   1112     const GridCoordinate& coordinate = cachedGridCoordinate(child);
   1113 
   1114     // The grid items should be inside the grid container's border box, that's why they need to be shifted.
   1115     LayoutPoint offset(borderAndPaddingStart(), borderAndPaddingBefore());
   1116     // FIXME: |columnTrack| and |rowTrack| should be smaller than our column / row count.
   1117     for (size_t i = 0; i < coordinate.columns.initialPositionIndex && i < columnTracks.size(); ++i)
   1118         offset.setX(offset.x() + columnTracks[i].m_usedBreadth);
   1119     for (size_t i = 0; i < coordinate.rows.initialPositionIndex && i < rowTracks.size(); ++i)
   1120         offset.setY(offset.y() + rowTracks[i].m_usedBreadth);
   1121 
   1122     // FIXME: Handle margins on the grid item.
   1123     return offset;
   1124 }
   1125 
   1126 void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
   1127 {
   1128     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next())
   1129         paintChild(child, paintInfo, paintOffset);
   1130 }
   1131 
   1132 const char* RenderGrid::renderName() const
   1133 {
   1134     if (isFloating())
   1135         return "RenderGrid (floating)";
   1136     if (isOutOfFlowPositioned())
   1137         return "RenderGrid (positioned)";
   1138     if (isAnonymous())
   1139         return "RenderGrid (generated)";
   1140     if (isRelPositioned())
   1141         return "RenderGrid (relative positioned)";
   1142     return "RenderGrid";
   1143 }
   1144 
   1145 } // namespace WebCore
   1146