Title: [142898] trunk/Source/WebCore
Revision
142898
Author
[email protected]
Date
2013-02-14 12:15:30 -0800 (Thu, 14 Feb 2013)

Log Message

[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.

Modified Paths

Diff

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
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to