Chromium Code Reviews| Index: Source/core/rendering/RenderGrid.cpp |
| diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp |
| index 163edcffe0754ba440f5c24fba58f1a10b62528a..092df3bf39ebe4670b54e77408d767472fd7d8d6 100644 |
| --- a/Source/core/rendering/RenderGrid.cpp |
| +++ b/Source/core/rendering/RenderGrid.cpp |
| @@ -121,16 +121,37 @@ public: |
| return 0; |
| } |
| - PassOwnPtr<GridCoordinate> nextEmptyGridArea() |
| + bool checkEmptyCells(size_t rowSpan, size_t columnSpan) const |
| + { |
| + // Ignore cells outside current grid as we will grow it later if needed. |
| + size_t maxRows = std::min(m_rowIndex + rowSpan, m_grid.size()); |
| + size_t maxColumns = std::min(m_columnIndex + columnSpan, m_grid[0].size()); |
| + |
| + // 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 = m_rowIndex; row < maxRows; ++row) { |
| + for (size_t column = m_columnIndex; column < maxColumns; ++column) { |
| + const GridCell& children = m_grid[row][column]; |
| + if (!children.isEmpty()) |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| + } |
| + |
| + PassOwnPtr<GridCoordinate> nextEmptyGridArea(size_t fixedTrackSpan, size_t varyingTrackSpan) |
| { |
| ASSERT(!m_grid.isEmpty()); |
| + ASSERT(fixedTrackSpan >= 1 && varyingTrackSpan >= 1); |
| + |
| + size_t rowSpan = (m_direction == ForColumns) ? varyingTrackSpan : fixedTrackSpan; |
| + size_t columnSpan = (m_direction == ForColumns) ? fixedTrackSpan : varyingTrackSpan; |
| size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex; |
| const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size(); |
| for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) { |
| - const GridCell& children = m_grid[m_rowIndex][m_columnIndex]; |
| - if (children.isEmpty()) { |
| - OwnPtr<GridCoordinate> result = adoptPtr(new GridCoordinate(GridSpan(m_rowIndex, m_rowIndex), GridSpan(m_columnIndex, m_columnIndex))); |
| + if (checkEmptyCells(rowSpan, columnSpan)) { |
| + OwnPtr<GridCoordinate> result = adoptPtr(new GridCoordinate(GridSpan(m_rowIndex, m_rowIndex + rowSpan - 1), GridSpan(m_columnIndex, m_columnIndex + columnSpan - 1))); |
| // Advance the iterator to avoid an infinite loop where we would return the same grid area over and over. |
| ++varyingTrackIndex; |
| return result.release(); |
| @@ -847,24 +868,6 @@ 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; |
| @@ -873,30 +876,14 @@ PassOwnPtr<GridCoordinate> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOu |
| 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()); |
| - OwnPtr<GridCoordinate> emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(autoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPositions); |
| + GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *autoGridItems[i], autoPlacementMinorAxisDirection(), GridResolvedPosition(0)); |
| + |
| + GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->resolvedInitialPosition.toInt()); |
| + OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions->integerSpan(), minorAxisPositions.integerSpan()); |
| if (!emptyGridArea) |
| emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(autoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPositions); |
| insertItemIntoGrid(autoGridItems[i], *emptyGridArea); |
| @@ -915,16 +902,20 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem) |
| ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMajorAxisDirection())); |
| OwnPtr<GridCoordinate> emptyGridArea; |
| if (minorAxisPositions) { |
| - emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions); |
| + GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMajorAxisDirection(), GridResolvedPosition(0)); |
| + |
| + GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisPositions->resolvedInitialPosition.toInt()); |
| + emptyGridArea = iterator.nextEmptyGridArea(minorAxisPositions->integerSpan(), majorAxisPositions.integerSpan()); |
| if (!emptyGridArea) |
| emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions); |
| } else { |
| + GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMajorAxisDirection(), GridResolvedPosition(0)); |
|
Julien - ping for review
2014/06/16 20:31:35
This line is now common to the 2 branches and it c
Manuel Rego
2014/06/16 21:15:34
Yeah, you're right. I'm moving it outside the if.
|
| + GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMinorAxisDirection(), GridResolvedPosition(0)); |
| + |
| const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : gridRowCount(); |
| for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) { |
| - // 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); |
| + GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisIndex); |
| + emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions.integerSpan(), minorAxisPositions.integerSpan()); |
| 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()). |
| @@ -935,10 +926,8 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem) |
| } |
| } |
| - if (!emptyGridArea) { |
| - GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMinorAxisDirection(), GridResolvedPosition(0)); |
| + if (!emptyGridArea) |
| emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions); |
| - } |
| } |
| insertItemIntoGrid(gridItem, *emptyGridArea); |