| Index: Source/core/rendering/RenderGrid.cpp
|
| diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp
|
| index 55a7ea36b7e903fa67ffbfae48291a4aff4597b1..163edcffe0754ba440f5c24fba58f1a10b62528a 100644
|
| --- a/Source/core/rendering/RenderGrid.cpp
|
| +++ b/Source/core/rendering/RenderGrid.cpp
|
| @@ -204,12 +204,6 @@ void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
|
| dirtyGrid();
|
| return;
|
| } else {
|
| - // Ensure that the grid is big enough to contain new grid item.
|
| - if (gridRowCount() <= rowPositions->resolvedFinalPosition.toInt())
|
| - growGrid(ForRows, rowPositions->resolvedFinalPosition.toInt());
|
| - if (gridColumnCount() <= columnPositions->resolvedFinalPosition.toInt())
|
| - growGrid(ForColumns, columnPositions->resolvedFinalPosition.toInt());
|
| -
|
| insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPositions));
|
| addChildToIndexesMap(newChildBox);
|
| }
|
| @@ -751,6 +745,12 @@ void RenderGrid::growGrid(GridTrackSizingDirection direction, size_t maximumPosi
|
|
|
| void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
|
| {
|
| + // Ensure that the grid is big enough to contain new grid item.
|
| + if (gridRowCount() <= coordinate.rows.resolvedFinalPosition.toInt())
|
| + growGrid(ForRows, coordinate.rows.resolvedFinalPosition.toInt());
|
| + if (gridColumnCount() <= coordinate.columns.resolvedFinalPosition.toInt())
|
| + growGrid(ForColumns, coordinate.columns.resolvedFinalPosition.toInt());
|
| +
|
| for (GridSpan::iterator row = coordinate.rows.begin(); row != coordinate.rows.end(); ++row) {
|
| for (GridSpan::iterator column = coordinate.columns.begin(); column != coordinate.columns.end(); ++column)
|
| m_grid[row.toInt()][column.toInt()].append(child);
|
| @@ -759,13 +759,6 @@ void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coor
|
| m_gridItemCoordinate.set(child, coordinate);
|
| }
|
|
|
| -void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridResolvedPosition& rowTrack, const GridResolvedPosition& columnTrack)
|
| -{
|
| - const GridSpan& rowSpan = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*child, ForRows, rowTrack);
|
| - const GridSpan& columnSpan = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*child, ForColumns, columnTrack);
|
| - insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
|
| -}
|
| -
|
| void RenderGrid::placeItemsOnGrid()
|
| {
|
| if (!gridIsDirty())
|
| @@ -831,12 +824,22 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
|
| OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForRows);
|
| OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForColumns);
|
|
|
| - // |positions| is 0 if we need to run the auto-placement algorithm. Our estimation ignores
|
| - // this case as the auto-placement algorithm will grow the grid as needed.
|
| - if (rowPositions)
|
| + // |positions| is 0 if we need to run the auto-placement algorithm.
|
| + if (rowPositions) {
|
| maximumRowIndex = std::max<size_t>(maximumRowIndex, rowPositions->resolvedFinalPosition.next().toInt());
|
| - if (columnPositions)
|
| + } else {
|
| + // Grow the grid for items with a definite row span, getting the largest such span.
|
| + GridSpan positions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *child, ForRows, GridResolvedPosition(0));
|
| + maximumRowIndex = std::max<size_t>(maximumRowIndex, positions.resolvedFinalPosition.next().toInt());
|
| + }
|
| +
|
| + if (columnPositions) {
|
| maximumColumnIndex = std::max<size_t>(maximumColumnIndex, columnPositions->resolvedFinalPosition.next().toInt());
|
| + } else {
|
| + // Grow the grid for items with a definite column span, getting the largest such span.
|
| + GridSpan positions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *child, ForColumns, GridResolvedPosition(0));
|
| + maximumColumnIndex = std::max<size_t>(maximumColumnIndex, positions.resolvedFinalPosition.next().toInt());
|
| + }
|
| }
|
|
|
| m_grid.grow(maximumRowIndex);
|
| @@ -844,20 +847,59 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
|
| m_grid[i].grow(maximumColumnIndex);
|
| }
|
|
|
| +bool RenderGrid::checkEmptyCells(const GridCoordinate& coordinate) const
|
| +{
|
| + // Ignore cells outside current grid as we will grow it later if needed.
|
| + size_t maxRows = std::min(coordinate.rows.resolvedFinalPosition.next().toInt(), gridRowCount());
|
| + size_t maxColumns = std::min(coordinate.columns.resolvedFinalPosition.next().toInt(), gridColumnCount());
|
| +
|
| + // This adds a O(N^2) behavior that shouldn't be a big deal as we expect spanning areas to be small.
|
| + for (size_t row = coordinate.rows.resolvedInitialPosition.toInt(); row < maxRows; ++row) {
|
| + for (size_t column = coordinate.columns.resolvedInitialPosition.toInt(); column < maxColumns; ++column) {
|
| + const GridCell& children = m_grid[row][column];
|
| + if (!children.isEmpty())
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +PassOwnPtr<GridCoordinate> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(const RenderBox* gridItem, GridTrackSizingDirection specifiedDirection, const GridSpan& specifiedPositions) const
|
| +{
|
| + GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
|
| + const size_t endOfCrossDirection = crossDirection == ForColumns ? gridColumnCount() : gridRowCount();
|
| + GridSpan crossDirectionPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, crossDirection, GridResolvedPosition(endOfCrossDirection));
|
| + return adoptPtr(new GridCoordinate(specifiedDirection == ForColumns ? crossDirectionPositions : specifiedPositions, specifiedDirection == ForColumns ? specifiedPositions : crossDirectionPositions));
|
| +}
|
| +
|
| +PassOwnPtr<GridCoordinate> RenderGrid::findEmptyGridAreaAtSpecifiedPositionsInsideGrid(const RenderBox* gridItem, GridTrackSizingDirection specifiedDirection, const GridSpan& specifiedPositions) const
|
| +{
|
| + GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
|
| +
|
| + GridIterator iterator(m_grid, specifiedDirection, specifiedPositions.resolvedInitialPosition.toInt());
|
| + OwnPtr<GridCoordinate> emptyGridArea;
|
| + for (emptyGridArea = iterator.nextEmptyGridArea(); emptyGridArea; emptyGridArea = iterator.nextEmptyGridArea()) {
|
| + GridResolvedPosition crossDirectionInitialPositionIndex = crossDirection == ForColumns ? emptyGridArea->columns.resolvedInitialPosition : emptyGridArea->rows.resolvedInitialPosition;
|
| + GridSpan crossDirectionPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, crossDirection, crossDirectionInitialPositionIndex);
|
| +
|
| + emptyGridArea->rows = specifiedDirection == ForColumns ? crossDirectionPositions : specifiedPositions;
|
| + emptyGridArea->columns = specifiedDirection == ForColumns ? specifiedPositions : crossDirectionPositions;
|
| + if (checkEmptyCells(*emptyGridArea))
|
| + break;
|
| + }
|
| +
|
| + return emptyGridArea.release();
|
| +}
|
| +
|
| void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGridItems)
|
| {
|
| for (size_t i = 0; i < autoGridItems.size(); ++i) {
|
| OwnPtr<GridSpan> majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *autoGridItems[i], autoPlacementMajorAxisDirection());
|
| - GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->resolvedInitialPosition.toInt());
|
| - if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
|
| - insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
|
| - continue;
|
| - }
|
| -
|
| - growGrid(autoPlacementMinorAxisDirection(), autoPlacementMinorAxisDirection() == ForColumns ? gridColumnCount() : gridRowCount());
|
| - OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
|
| - ASSERT(emptyGridArea);
|
| - insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
|
| + OwnPtr<GridCoordinate> emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(autoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPositions);
|
| + if (!emptyGridArea)
|
| + emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(autoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPositions);
|
| + insertItemIntoGrid(autoGridItems[i], *emptyGridArea);
|
| }
|
| }
|
|
|
| @@ -871,30 +913,35 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
|
| {
|
| OwnPtr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMinorAxisDirection());
|
| ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMajorAxisDirection()));
|
| - size_t minorAxisIndex = 0;
|
| + OwnPtr<GridCoordinate> emptyGridArea;
|
| if (minorAxisPositions) {
|
| - minorAxisIndex = minorAxisPositions->resolvedInitialPosition.toInt();
|
| - GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisIndex);
|
| - if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
|
| - insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
|
| - return;
|
| - }
|
| + emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions);
|
| + if (!emptyGridArea)
|
| + emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions);
|
| } else {
|
| const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : gridRowCount();
|
| for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) {
|
| - GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisIndex);
|
| - if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
|
| - insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
|
| - return;
|
| + // We need to resolve the position for every different index as the number of cells might vary depending on it.
|
| + // This will happen when we have "span <custom-indent>", which has a different resolution based on the position.
|
| + GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMajorAxisDirection(), majorAxisIndex);
|
| + emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(gridItem, autoPlacementMajorAxisDirection(), majorAxisPositions);
|
| +
|
| + if (emptyGridArea) {
|
| + // Check that it fits in the minor axis direction, as we shouldn't grow in that direction here (it was already managed in populateExplicitGridAndOrderIterator()).
|
| + GridResolvedPosition minorAxisFinalPositionIndex = autoPlacementMinorAxisDirection() == ForColumns ? emptyGridArea->columns.resolvedFinalPosition : emptyGridArea->rows.resolvedFinalPosition;
|
| + const size_t endOfMinorAxis = autoPlacementMinorAxisDirection() == ForColumns ? gridColumnCount() : gridRowCount();
|
| + if (minorAxisFinalPositionIndex.toInt() < endOfMinorAxis)
|
| + break;
|
| }
|
| }
|
| +
|
| + if (!emptyGridArea) {
|
| + GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMinorAxisDirection(), GridResolvedPosition(0));
|
| + emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions);
|
| + }
|
| }
|
|
|
| - // We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it.
|
| - const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : minorAxisIndex;
|
| - const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : gridRowCount();
|
| - growGrid(autoPlacementMajorAxisDirection(), autoPlacementMajorAxisDirection() == ForColumns ? gridColumnCount() : gridRowCount());
|
| - insertItemIntoGrid(gridItem, rowIndex, columnIndex);
|
| + insertItemIntoGrid(gridItem, *emptyGridArea);
|
| }
|
|
|
| GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
|
|
|