Index: Source/core/rendering/RenderGrid.cpp |
diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp |
index 83059ac6bcbe342ba9848fdeb3416ab3463c5ccd..a1de68202177f4dafa8c7e86d0569ead6c56f4df 100644 |
--- a/Source/core/rendering/RenderGrid.cpp |
+++ b/Source/core/rendering/RenderGrid.cpp |
@@ -122,16 +122,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(); |
@@ -846,24 +867,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; |
@@ -872,30 +875,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); |
@@ -912,18 +899,20 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem) |
{ |
OwnPtr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMinorAxisDirection()); |
ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridItem, autoPlacementMajorAxisDirection())); |
+ GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMajorAxisDirection(), GridResolvedPosition(0)); |
OwnPtr<GridCoordinate> emptyGridArea; |
if (minorAxisPositions) { |
- emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions); |
+ GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisPositions->resolvedInitialPosition.toInt()); |
+ emptyGridArea = iterator.nextEmptyGridArea(minorAxisPositions->integerSpan(), majorAxisPositions.integerSpan()); |
if (!emptyGridArea) |
emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions); |
} else { |
+ 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()). |
@@ -938,10 +927,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); |