Modified: trunk/Source/WebCore/ChangeLog (142897 => 142898)
--- trunk/Source/WebCore/ChangeLog 2013-02-14 19:53:11 UTC (rev 142897)
+++ trunk/Source/WebCore/ChangeLog 2013-02-14 20:15:30 UTC (rev 142898)
@@ -1,3 +1,44 @@
+2013-02-14 Julien Chaffraix <[email protected]>
+
+ [CSS Grid Layout] Add an internal 2D grid representation to RenderGrid
+ https://bugs.webkit.org/show_bug.cgi?id=109714
+
+ Reviewed by Ojan Vafai.
+
+ This change introduces a 2D grid representation of the grid areas. Our implementation
+ is a straight Vector of Vectors for the grid areas, each grid area able to hold an
+ arbitrary number of RenderBox* so they hold a Vector of RenderBoxes. As an optimization,
+ each grid area has enough inline storage to hold one grid item which should cover
+ most cases.
+
+ In order to keep the code readable, a GridIterator was introduced to hide the new grid.
+
+ Refactoring, covered by existing tests.
+
+ * rendering/RenderGrid.cpp:
+ (RenderGrid::GridIterator):
+ (WebCore::RenderGrid::GridIterator::GridIterator):
+ (WebCore::RenderGrid::GridIterator::nextGridItem):
+ Added a mono-directional iterator. In order to be more aligned with the rest of the code,
+ this iterator actually walks orthogonally to the |direction| (ie fixing the |direction|'s track).
+
+ * rendering/RenderGrid.cpp:
+ (WebCore::RenderGrid::computePreferredLogicalWidths):
+ (WebCore::RenderGrid::layoutGridItems):
+ Updated these 2 functions to place the items on the grid and clear it at the end.
+
+ (WebCore::RenderGrid::computePreferredTrackWidth):
+ (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
+ Updated to use the GridIterator to walk over the rows / columns.
+
+ (WebCore::RenderGrid::placeItemsOnGrid):
+ Added this function that inserts the grid items into the right grid area.
+
+ * rendering/RenderGrid.h:
+ (WebCore::RenderGrid::gridColumnCount):
+ (WebCore::RenderGrid::gridRowCount):
+ Added these helper functions.
+
2013-02-14 Sheriff Bot <[email protected]>
Unreviewed, rolling out r141990.
Modified: trunk/Source/WebCore/rendering/RenderGrid.cpp (142897 => 142898)
--- trunk/Source/WebCore/rendering/RenderGrid.cpp 2013-02-14 19:53:11 UTC (rev 142897)
+++ trunk/Source/WebCore/rendering/RenderGrid.cpp 2013-02-14 20:15:30 UTC (rev 142898)
@@ -66,6 +66,44 @@
LayoutUnit m_maxBreadth;
};
+class RenderGrid::GridIterator {
+ WTF_MAKE_NONCOPYABLE(GridIterator);
+public:
+ // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
+ // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd column.
+ GridIterator(const Vector<Vector<Vector<RenderBox*, 1> > >& grid, TrackSizingDirection direction, size_t fixedTrackIndex)
+ : m_grid(grid)
+ , m_direction(direction)
+ , m_rowIndex((direction == ForColumns) ? 0 : fixedTrackIndex)
+ , m_columnIndex((direction == ForColumns) ? fixedTrackIndex : 0)
+ , m_childIndex(0)
+ {
+ }
+
+ RenderBox* nextGridItem()
+ {
+ if (!m_grid.size())
+ return 0;
+
+ 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 Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
+ if (m_childIndex < children.size())
+ return children[m_childIndex++];
+
+ m_childIndex = 0;
+ }
+ return 0;
+ }
+private:
+ const Vector<Vector<Vector<RenderBox*, 1> > >& m_grid;
+ TrackSizingDirection m_direction;
+ size_t m_rowIndex;
+ size_t m_columnIndex;
+ size_t m_childIndex;
+};
+
RenderGrid::RenderGrid(Element* element)
: RenderBlock(element)
{
@@ -134,6 +172,8 @@
{
ASSERT(preferredLogicalWidthsDirty());
+ placeItemsOnGrid();
+
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
@@ -159,6 +199,7 @@
m_maxPreferredLogicalWidth += borderAndPaddingInInlineDirection;
setPreferredLogicalWidthsDirty(false);
+ m_grid.clear();
}
LayoutUnit RenderGrid::computePreferredTrackWidth(const Length& length, size_t trackIndex) const
@@ -170,28 +211,20 @@
if (length.isMinContent()) {
LayoutUnit minContentSize = 0;
- // FIXME: It's inefficient to iterate over our grid items. We should be able to
- // get the subset of grid items in the current row / column faster.
- for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
- size_t cellIndex = resolveGridPosition(ForColumns, child);
- if (cellIndex != trackIndex)
- continue;
-
+ GridIterator iterator(m_grid, ForColumns, trackIndex);
+ while (RenderBox* gridItem = iterator.nextGridItem()) {
// FIXME: We should include the child's fixed margins like RenderFlexibleBox.
- minContentSize = std::max(minContentSize, child->minPreferredLogicalWidth());
+ minContentSize = std::max(minContentSize, gridItem->minPreferredLogicalWidth());
}
return minContentSize;
}
if (length.isMaxContent()) {
LayoutUnit maxContentSize = 0;
- for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
- size_t cellIndex = resolveGridPosition(ForColumns, child);
- if (cellIndex != trackIndex)
- continue;
-
+ GridIterator iterator(m_grid, ForColumns, trackIndex);
+ while (RenderBox* gridItem = iterator.nextGridItem()) {
// FIXME: We should include the child's fixed margins like RenderFlexibleBox.
- maxContentSize = std::max(maxContentSize, child->maxPreferredLogicalWidth());
+ maxContentSize = std::max(maxContentSize, gridItem->maxPreferredLogicalWidth());
}
return maxContentSize;
}
@@ -369,15 +402,12 @@
}
}
-void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, size_t i, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
+void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, size_t trackIndex, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
{
- GridTrack& track = (direction == ForColumns) ? columnTracks[i] : rowTracks[i];
- for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
- size_t cellIndex = resolveGridPosition(direction, child);
- if (cellIndex != i)
- continue;
-
- LayoutUnit contentSize = (this->*sizingFunction)(child, direction, columnTracks);
+ GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndex] : rowTracks[trackIndex];
+ GridIterator iterator(m_grid, direction, trackIndex);
+ while (RenderBox* gridItem = iterator.nextGridItem()) {
+ LayoutUnit contentSize = (this->*sizingFunction)(gridItem, direction, columnTracks);
LayoutUnit additionalBreadthSpace = contentSize - (track.*trackGetter)();
Vector<GridTrack*> tracks;
tracks.append(&track);
@@ -436,10 +466,28 @@
}
#endif
+void RenderGrid::placeItemsOnGrid()
+{
+ ASSERT(m_grid.isEmpty());
+ m_grid.grow(maximumIndexInDirection(ForRows));
+ size_t maximumColumnIndex = maximumIndexInDirection(ForColumns);
+ for (size_t i = 0; i < gridRowCount(); ++i)
+ m_grid[i].grow(maximumColumnIndex);
+
+ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ size_t columnTrack = resolveGridPosition(child->style()->gridItemColumn());
+ size_t rowTrack = resolveGridPosition(child->style()->gridItemRow());
+
+ m_grid[rowTrack][columnTrack].append(child);
+ }
+}
+
void RenderGrid::layoutGridItems()
{
- Vector<GridTrack> columnTracks(maximumIndexInDirection(ForColumns));
- Vector<GridTrack> rowTracks(maximumIndexInDirection(ForRows));
+ placeItemsOnGrid();
+
+ Vector<GridTrack> columnTracks(gridColumnCount());
+ Vector<GridTrack> rowTracks(gridRowCount());
computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks);
ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks));
computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks);
@@ -479,6 +527,7 @@
// FIXME: We should handle min / max logical height.
setLogicalHeight(logicalHeight() + borderAndPaddingLogicalHeight());
+ m_grid.clear();
}
size_t RenderGrid::resolveGridPosition(TrackSizingDirection direction, const RenderObject* gridItem) const
Modified: trunk/Source/WebCore/rendering/RenderGrid.h (142897 => 142898)
--- trunk/Source/WebCore/rendering/RenderGrid.h 2013-02-14 19:53:11 UTC (rev 142897)
+++ trunk/Source/WebCore/rendering/RenderGrid.h 2013-02-14 20:15:30 UTC (rev 142898)
@@ -50,12 +50,14 @@
LayoutUnit computePreferredTrackWidth(const Length&, size_t) const;
+ class GridIterator;
enum TrackSizingDirection { ForColumns, ForRows };
void computedUsedBreadthOfGridTracks(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks);
LayoutUnit computeUsedBreadthOfMinLength(TrackSizingDirection, const Length&) const;
LayoutUnit computeUsedBreadthOfMaxLength(TrackSizingDirection, const Length&) const;
LayoutUnit computeUsedBreadthOfSpecifiedLength(TrackSizingDirection, const Length&) const;
void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace);
+ void placeItemsOnGrid();
void layoutGridItems();
typedef LayoutUnit (RenderGrid::* SizingFunction)(RenderBox*, TrackSizingDirection, Vector<GridTrack>&);
@@ -77,6 +79,11 @@
#ifndef NDEBUG
bool tracksAreWiderThanMinTrackBreadth(TrackSizingDirection, const Vector<GridTrack>&);
#endif
+
+ size_t gridColumnCount() const { return m_grid.isEmpty() ? 0 : m_grid[0].size(); }
+ size_t gridRowCount() const { return m_grid.size(); }
+
+ Vector<Vector<Vector<RenderBox*, 1> > > m_grid;
};
} // namespace WebCore