Title: [143535] trunk
Revision
143535
Author
jchaffr...@webkit.org
Date
2013-02-20 16:33:49 -0800 (Wed, 20 Feb 2013)

Log Message

[CSS Grid Layout] Implement the auto-placement algorithm without grid growth
https://bugs.webkit.org/show_bug.cgi?id=110277

Reviewed by Tony Chang.

Source/WebCore:

Tests: fast/css-grid-layout/grid-item-addition-auto-placement-update.html
       fast/css-grid-layout/grid-item-removal-auto-placement-update.html
       fast/css-grid-layout/grid-auto-flow-resolution.html (extended to cover more cases)

This change implements most of the auto-placement algorithm per
http://dev.w3.org/csswg/css3-grid-layout/#auto-placement-algo

To limit the size of the code change, it doesn't implement growing the grid if there
are no empty grid areas. If we don't find any empty grid areas, we just insert in the first
one, like what grid-auto-flow: none would do (which explains the test failures).

* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::GridIterator::nextEmptyGridArea):
Added this function to return the GridCoordinate of the next empty grid area along
the iterator's direction.

(WebCore::RenderGrid::placeItemsOnGrid):
Split this function into the different steps below. For efficiency, collect the auto vs specified
major axis grid items in different Vectors.

(WebCore::RenderGrid::placeSpecifiedMajorAxisItemsOnGrid):
Added this function that implements part of step 1 of the algorithm (the grid items without
auto row / column are already handled in placeItemsOnGrid).

(WebCore::RenderGrid::placeAutoMajorAxisItemsOnGrid):
Added this function that iterates over the auto grid items and call placeAutoMajorAxisItemOnGrid.

(WebCore::RenderGrid::placeAutoMajorAxisItemOnGrid):
Added this method to handle the step 4 of the algorithm. Based on the minor axis's position,
it either walks along the major axis once or several times until it finds an empty grid area
for the grid item.

(WebCore::RenderGrid::autoPlacementMajorAxisPositionForChild):
(WebCore::RenderGrid::autoPlacementMinorAxisPositionForChild):
(WebCore::RenderGrid::autoPlacementMajorAxisDirection):
(WebCore::RenderGrid::autoPlacementMinorAxisDirection):
Added these helper functions that return minor / major axis positions & direction.

* rendering/RenderGrid.h:
Added the previous new RenderGrid functions.

LayoutTests:

* fast/css-grid-layout/grid-auto-flow-resolution-expected.txt:
* fast/css-grid-layout/grid-auto-flow-resolution.html:

* fast/css-grid-layout/grid-item-addition-auto-placement-update-expected.txt: Added.
* fast/css-grid-layout/grid-item-addition-auto-placement-update.html: Added.
* fast/css-grid-layout/grid-item-removal-auto-placement-update-expected.txt: Added.
* fast/css-grid-layout/grid-item-removal-auto-placement-update.html: Added.
The current algorithm doesn't grow the grid but falls back to inserting the element at
position (1, 1). The failures in these tests are due to that.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (143534 => 143535)


--- trunk/LayoutTests/ChangeLog	2013-02-21 00:32:33 UTC (rev 143534)
+++ trunk/LayoutTests/ChangeLog	2013-02-21 00:33:49 UTC (rev 143535)
@@ -1,3 +1,20 @@
+2013-02-20  Julien Chaffraix  <jchaffr...@webkit.org>
+
+        [CSS Grid Layout] Implement the auto-placement algorithm without grid growth
+        https://bugs.webkit.org/show_bug.cgi?id=110277
+
+        Reviewed by Tony Chang.
+
+        * fast/css-grid-layout/grid-auto-flow-resolution-expected.txt:
+        * fast/css-grid-layout/grid-auto-flow-resolution.html:
+
+        * fast/css-grid-layout/grid-item-addition-auto-placement-update-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-addition-auto-placement-update.html: Added.
+        * fast/css-grid-layout/grid-item-removal-auto-placement-update-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-removal-auto-placement-update.html: Added.
+        The current algorithm doesn't grow the grid but falls back to inserting the element at
+        position (1, 1). The failures in these tests are due to that.
+
 2013-02-20  Vincent Scheib  <sch...@chromium.org>
 
         Accept 'allowfullscreen' in addition to 'webkitallowfullscreen'.

Modified: trunk/LayoutTests/fast/css-grid-layout/grid-auto-flow-resolution-expected.txt (143534 => 143535)


--- trunk/LayoutTests/fast/css-grid-layout/grid-auto-flow-resolution-expected.txt	2013-02-21 00:32:33 UTC (rev 143534)
+++ trunk/LayoutTests/fast/css-grid-layout/grid-auto-flow-resolution-expected.txt	2013-02-21 00:33:49 UTC (rev 143535)
@@ -1,4 +1,4 @@
-This test checks that the tracks' auto position are properly resolved on a static grid.
+This test checks that the tracks' auto positions are properly resolved on a static grid.
 
 XXXXX XXXXX XXXXX
 XXXXX XXXXX XXXXX
@@ -7,3 +7,27 @@
 XXXXX XXXXX XXXXX
 XXXXX XXXXX XXXXX
 PASS
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+PASS
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+PASS
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+PASS
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+XXXXX XXXXX XXXXX
+PASS

Modified: trunk/LayoutTests/fast/css-grid-layout/grid-auto-flow-resolution.html (143534 => 143535)


--- trunk/LayoutTests/fast/css-grid-layout/grid-auto-flow-resolution.html	2013-02-21 00:32:33 UTC (rev 143534)
+++ trunk/LayoutTests/fast/css-grid-layout/grid-auto-flow-resolution.html	2013-02-21 00:33:49 UTC (rev 143535)
@@ -11,6 +11,11 @@
     -webkit-grid-rows: 50px 100px;
 }
 
+.bigGrid {
+    -webkit-grid-columns: 50px 100px 150px 200px;
+    -webkit-grid-rows: 50px 100px 150px 200px;
+}
+
 .unconstrainedContainer {
     /* For accurate x / y offset. */
     position: relative;
@@ -19,7 +24,7 @@
 <script src=""
 <body _onload_="checkLayout('.grid')">
 
-<p>This test checks that the tracks' auto position are properly resolved on a static grid.</p>
+<p>This test checks that the tracks' auto positions are properly resolved on a static grid.</p>
 
 <div class="unconstrainedContainer">
     <div class="grid smallGrid gridAutoFlowNone" id="gridAutoFlowNone">
@@ -32,5 +37,45 @@
     </div>
 </div>
 
+<div class="unconstrainedContainer">
+    <div class="grid bigGrid gridAutoFlowColumn">
+        <div class="sizedToGridArea secondRowSecondColumn" data-offset-x="50" data-offset-y="50" data-expected-width="100" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="150" data-expected-width="50" data-expected-height="150">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid bigGrid gridAutoFlowRow">
+        <div class="sizedToGridArea firstRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowSecondColumn" data-offset-x="50" data-offset-y="50" data-expected-width="100" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowFirstColumn" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="150" data-offset-y="0" data-expected-width="150" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid bigGrid gridAutoFlowColumn">
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="150" data-offset-y="0" data-expected-width="150" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="150" data-expected-width="50" data-expected-height="150">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid bigGrid gridAutoFlowRow">
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="150" data-expected-width="50" data-expected-height="150">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowSecondColumn" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="150" data-offset-y="0" data-expected-width="150" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
 </body>
 </html>

Added: trunk/LayoutTests/fast/css-grid-layout/grid-item-addition-auto-placement-update-expected.txt (0 => 143535)


--- trunk/LayoutTests/fast/css-grid-layout/grid-item-addition-auto-placement-update-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css-grid-layout/grid-item-addition-auto-placement-update-expected.txt	2013-02-21 00:33:49 UTC (rev 143535)
@@ -0,0 +1,35 @@
+This test checks that the tracks' auto positions are recomputed after adding a grid item.
+
+XXXXX XXXXX XXXXX
+FAIL:
+Expected 170 for width, but got 50. 
+
+<div class="sizedToGridArea autoRowAutoColumn" id="autoFlowColumnElement" data-expected-width="170" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+PASS
+PASS
+PASS
+PASS
+XXXXX XXXXX XXXXX
+FAIL:
+Expected 30 for height, but got 50. 
+
+<div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElement" data-expected-width="50" data-expected-height="30">XXXXX XXXXX XXXXX</div>
+PASS
+PASS
+PASS
+PASS
+XXXXX XXXXX XXXXX
+FAIL:
+Expected 170 for width, but got 50. 
+
+<div class="sizedToGridArea autoRowAutoColumn" id="autoFlowColumnElementWithAuto" data-expected-width="170" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+PASS
+PASS
+PASS
+PASS
+XXXXX XXXXX XXXXX
+PASS
+PASS
+PASS
+PASS
+PASS

Added: trunk/LayoutTests/fast/css-grid-layout/grid-item-addition-auto-placement-update.html (0 => 143535)


--- trunk/LayoutTests/fast/css-grid-layout/grid-item-addition-auto-placement-update.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css-grid-layout/grid-item-addition-auto-placement-update.html	2013-02-21 00:33:49 UTC (rev 143535)
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="" rel="stylesheet">
+<style>
+.grid {
+    -webkit-grid-columns: 50px 100px;
+    -webkit-grid-rows: 50px 100px;
+}
+</style>
+<script src=""
+<script>
+function testAddition(gridElementID, position, autoFlowElementID, size)
+{
+    var gridElement = document.getElementById(gridElementID);
+
+    var gridItem = document.createElement("div");
+    gridItem.style.webkitGridRow = position.row;
+    gridItem.style.webkitGridColumn = position.column;
+    gridElement.appendChild(gridItem);
+
+    var autoFlowElement = document.getElementById(autoFlowElementID);
+    autoFlowElement.setAttribute("data-expected-width", size.width);
+    autoFlowElement.setAttribute("data-expected-height", size.height);
+    checkLayout("#" + autoFlowElementID);
+}
+
+function testAdditions()
+{
+    checkLayout("#autoFlowColumnElement");
+    testAddition("gridAutoFlowColumn", { 'row': '1', 'column': '1' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' });
+    testAddition("gridAutoFlowColumn", { 'row': '1', 'column': '2' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' });
+    testAddition("gridAutoFlowColumn", { 'row': '2', 'column': '2' }, "autoFlowColumnElement", { 'width': '50', 'height': '100' });
+    testAddition("gridAutoFlowColumn", { 'row': '2', 'column': '1' }, "autoFlowColumnElement", { 'width': '170', 'height': '50' });
+
+    checkLayout("#autoFlowRowElement");
+    testAddition("gridAutoFlowRow", { 'row': '1', 'column': '1' }, "autoFlowRowElement", { 'width': '100', 'height': '50' });
+    testAddition("gridAutoFlowRow", { 'row': '2', 'column': '1' }, "autoFlowRowElement", { 'width': '100', 'height': '50' });
+    testAddition("gridAutoFlowRow", { 'row': '2', 'column': '2' }, "autoFlowRowElement", { 'width': '100', 'height': '50' });
+    testAddition("gridAutoFlowRow", { 'row': '1', 'column': '2' }, "autoFlowRowElement", { 'width': '50', 'height': '30' });
+
+    checkLayout("#gridAutoFlowColumnWithAuto");
+    testAddition("gridAutoFlowColumnWithAuto", { 'row': 'auto', 'column': '1' }, "autoFlowColumnElementWithAuto", { 'width': '50', 'height': '100' });
+    testAddition("gridAutoFlowColumnWithAuto", { 'row': '1', 'column': '1' }, "autoFlowColumnElementWithAuto", { 'width': '100', 'height': '50' });
+    testAddition("gridAutoFlowColumnWithAuto", { 'row': 'auto', 'column': '2' }, "autoFlowColumnElementWithAuto", { 'width': '100', 'height': '100' });
+    testAddition("gridAutoFlowColumnWithAuto", { 'row': '2', 'column': '2' }, "autoFlowColumnElementWithAuto", { 'width': '170', 'height': '50' });
+
+    checkLayout("#gridAutoFlowRowWithAuto");
+    testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': 'auto' }, "autoFlowRowElementWithAuto", { 'width': '100', 'height': '50' });
+    testAddition("gridAutoFlowRowWithAuto", { 'row': 'auto', 'column': '1' }, "autoFlowRowElementWithAuto", { 'width': '100', 'height': '50' });
+    testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': '2' }, "autoFlowRowElementWithAuto", { 'width': '50', 'height': '100' });
+    testAddition("gridAutoFlowRowWithAuto", { 'row': '1', 'column': '1' }, "autoFlowRowElementWithAuto", { 'width': '50', 'height': '100' });
+}
+window.addEventListener("load", testAdditions, false);
+</script>
+<body>
+
+<p>This test checks that the tracks' auto positions are recomputed after adding a grid item.</p>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowColumn" id="gridAutoFlowColumn">
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowColumnElement" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowRow" id="gridAutoFlowRow">
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElement" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowColumn" id="gridAutoFlowColumnWithAuto">
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowColumnElementWithAuto" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowRow" id="gridAutoFlowRowWithAuto">
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElementWithAuto" data-expected-width="50" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+</body>
+</html>

Added: trunk/LayoutTests/fast/css-grid-layout/grid-item-removal-auto-placement-update-expected.txt (0 => 143535)


--- trunk/LayoutTests/fast/css-grid-layout/grid-item-removal-auto-placement-update-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css-grid-layout/grid-item-removal-auto-placement-update-expected.txt	2013-02-21 00:33:49 UTC (rev 143535)
@@ -0,0 +1,32 @@
+This test checks that the tracks' auto positions are recomputed after removing a grid item.
+
+XXXXX XXXXX XXXXX
+FAIL:
+Expected 170 for width, but got 50. 
+
+<div class="sizedToGridArea autoRowAutoColumn" id="autoFlowColumnElement" data-expected-width="170" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+PASS
+PASS
+PASS
+PASS
+XXXXX XXXXX XXXXX
+FAIL:
+Expected 30 for height, but got 50. 
+
+<div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElement" data-expected-width="50" data-expected-height="30">XXXXX XXXXX XXXXX</div>
+PASS
+PASS
+PASS
+PASS
+XXXXX XXXXX XXXXX
+PASS
+PASS
+PASS
+PASS
+PASS
+XXXXX XXXXX XXXXX
+PASS
+PASS
+PASS
+PASS
+PASS

Added: trunk/LayoutTests/fast/css-grid-layout/grid-item-removal-auto-placement-update.html (0 => 143535)


--- trunk/LayoutTests/fast/css-grid-layout/grid-item-removal-auto-placement-update.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css-grid-layout/grid-item-removal-auto-placement-update.html	2013-02-21 00:33:49 UTC (rev 143535)
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<script>
+if (window.testRunner)
+    testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1);
+</script>
+<link href="" rel="stylesheet">
+<style>
+.grid {
+    -webkit-grid-columns: 50px 100px;
+    -webkit-grid-rows: 50px 100px;
+}
+</style>
+<script src=""
+<script>
+function testRemoval(gridElementID, autoFlowElementID, size)
+{
+    var gridElement = document.getElementById(gridElementID);
+    var autoFlowElement = document.getElementById(autoFlowElementID);
+
+    // Remove the white space and the first grid item.
+    gridElement.removeChild(gridElement.firstChild);
+    gridElement.removeChild(gridElement.firstChild);
+
+    autoFlowElement.setAttribute("data-expected-width", size.width);
+    autoFlowElement.setAttribute("data-expected-height", size.height);
+    checkLayout("#" + gridElementID);
+}
+
+function testRemovals()
+{
+    checkLayout("#autoFlowColumnElement");
+    testRemoval("gridAutoFlowColumn", "autoFlowColumnElement", { 'width': '100', 'height': '100' });
+    testRemoval("gridAutoFlowColumn", "autoFlowColumnElement", { 'width': '100', 'height': '50' });
+    testRemoval("gridAutoFlowColumn", "autoFlowColumnElement", { 'width': '50', 'height': '100' });
+    testRemoval("gridAutoFlowColumn", "autoFlowColumnElement", { 'width': '50', 'height': '50' });
+
+    checkLayout("#autoFlowRowElement");
+    testRemoval("gridAutoFlowRow", "autoFlowRowElement", { 'width': '100', 'height': '100' });
+    testRemoval("gridAutoFlowRow", "autoFlowRowElement", { 'width': '100', 'height': '50' });
+    testRemoval("gridAutoFlowRow", "autoFlowRowElement", { 'width': '50', 'height': '50' });
+    testRemoval("gridAutoFlowRow", "autoFlowRowElement", { 'width': '50', 'height': '50' });
+
+    checkLayout("#gridAutoFlowColumnWithAutoItems");
+    testRemoval("gridAutoFlowColumnWithAutoItems", "autoFlowRowElementWithAutoItems", { 'width': '100', 'height': '100' });
+    testRemoval("gridAutoFlowColumnWithAutoItems", "autoFlowRowElementWithAutoItems", { 'width': '100', 'height': '50' });
+    testRemoval("gridAutoFlowColumnWithAutoItems", "autoFlowRowElementWithAutoItems", { 'width': '50', 'height': '100' });
+    testRemoval("gridAutoFlowColumnWithAutoItems", "autoFlowRowElementWithAutoItems", { 'width': '50', 'height': '50' });
+
+    checkLayout("#gridAutoFlowRowWithAutoAndFixedItems");
+    testRemoval("gridAutoFlowRowWithAutoAndFixedItems", "autoFlowRowElementWithAutoAndFixedItems", { 'width': '100', 'height': '100' });
+    testRemoval("gridAutoFlowRowWithAutoAndFixedItems", "autoFlowRowElementWithAutoAndFixedItems", { 'width': '100', 'height': '50' });
+    testRemoval("gridAutoFlowRowWithAutoAndFixedItems", "autoFlowRowElementWithAutoAndFixedItems", { 'width': '100', 'height': '50' });
+    testRemoval("gridAutoFlowRowWithAutoAndFixedItems", "autoFlowRowElementWithAutoAndFixedItems", { 'width': '50', 'height': '50' });
+}
+window.addEventListener("load", testRemovals, false);
+</script>
+<body>
+
+<p>This test checks that the tracks' auto positions are recomputed after removing a grid item.</p>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowColumn" id="gridAutoFlowColumn">
+        <div class="sizedToGridArea secondRowSecondColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowSecondColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowFirstColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowFirstColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowColumnElement" data-expected-width="170" data-expected-height="50">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowRow" id="gridAutoFlowRow">
+        <div class="sizedToGridArea secondRowSecondColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowSecondColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowFirstColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowFirstColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElement" data-expected-width="50" data-expected-height="30">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowColumn" id="gridAutoFlowColumnWithAutoItems">
+        <div class="sizedToGridArea autoRowFirstColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowSecondColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowAutoColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowAutoColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElementWithAutoItems" data-expected-width="100" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+<div class="unconstrainedContainer">
+    <div class="grid gridAutoFlowRow" id="gridAutoFlowRowWithAutoAndFixedItems">
+        <div class="sizedToGridArea autoRowFirstColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowSecondColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea secondRowAutoColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea firstRowAutoColumn">XXXXX XXXXX XXXXX</div>
+        <div class="sizedToGridArea autoRowAutoColumn" id="autoFlowRowElementWithAutoAndFixedItems" data-expected-width="100" data-expected-height="100">XXXXX XXXXX XXXXX</div>
+    </div>
+</div>
+
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (143534 => 143535)


--- trunk/Source/WebCore/ChangeLog	2013-02-21 00:32:33 UTC (rev 143534)
+++ trunk/Source/WebCore/ChangeLog	2013-02-21 00:33:49 UTC (rev 143535)
@@ -1,3 +1,51 @@
+2013-02-20  Julien Chaffraix  <jchaffr...@webkit.org>
+
+        [CSS Grid Layout] Implement the auto-placement algorithm without grid growth
+        https://bugs.webkit.org/show_bug.cgi?id=110277
+
+        Reviewed by Tony Chang.
+
+        Tests: fast/css-grid-layout/grid-item-addition-auto-placement-update.html
+               fast/css-grid-layout/grid-item-removal-auto-placement-update.html
+               fast/css-grid-layout/grid-auto-flow-resolution.html (extended to cover more cases)
+
+        This change implements most of the auto-placement algorithm per
+        http://dev.w3.org/csswg/css3-grid-layout/#auto-placement-algo
+
+        To limit the size of the code change, it doesn't implement growing the grid if there
+        are no empty grid areas. If we don't find any empty grid areas, we just insert in the first
+        one, like what grid-auto-flow: none would do (which explains the test failures).
+
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::GridIterator::nextEmptyGridArea):
+        Added this function to return the GridCoordinate of the next empty grid area along
+        the iterator's direction.
+
+        (WebCore::RenderGrid::placeItemsOnGrid):
+        Split this function into the different steps below. For efficiency, collect the auto vs specified
+        major axis grid items in different Vectors.
+
+        (WebCore::RenderGrid::placeSpecifiedMajorAxisItemsOnGrid):
+        Added this function that implements part of step 1 of the algorithm (the grid items without
+        auto row / column are already handled in placeItemsOnGrid).
+
+        (WebCore::RenderGrid::placeAutoMajorAxisItemsOnGrid):
+        Added this function that iterates over the auto grid items and call placeAutoMajorAxisItemOnGrid.
+
+        (WebCore::RenderGrid::placeAutoMajorAxisItemOnGrid):
+        Added this method to handle the step 4 of the algorithm. Based on the minor axis's position,
+        it either walks along the major axis once or several times until it finds an empty grid area
+        for the grid item.
+
+        (WebCore::RenderGrid::autoPlacementMajorAxisPositionForChild):
+        (WebCore::RenderGrid::autoPlacementMinorAxisPositionForChild):
+        (WebCore::RenderGrid::autoPlacementMajorAxisDirection):
+        (WebCore::RenderGrid::autoPlacementMinorAxisDirection):
+        Added these helper functions that return minor / major axis positions & direction.
+
+        * rendering/RenderGrid.h:
+        Added the previous new RenderGrid functions.
+
 2013-02-20  Vincent Scheib  <sch...@chromium.org>
 
         Accept 'allowfullscreen' in addition to 'webkitallowfullscreen'.

Modified: trunk/Source/WebCore/rendering/RenderGrid.cpp (143534 => 143535)


--- trunk/Source/WebCore/rendering/RenderGrid.cpp	2013-02-21 00:32:33 UTC (rev 143534)
+++ trunk/Source/WebCore/rendering/RenderGrid.cpp	2013-02-21 00:33:49 UTC (rev 143535)
@@ -96,6 +96,26 @@
         }
         return 0;
     }
+
+    PassOwnPtr<GridCoordinate> nextEmptyGridArea()
+    {
+        if (m_grid.isEmpty())
+            return nullptr;
+
+        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 (children.isEmpty()) {
+                PassOwnPtr<GridCoordinate> result =  adoptPtr(new GridCoordinate(m_rowIndex, m_columnIndex));
+                // Advance the iterator to avoid an infinite loop where we would return the same grid area over and over.
+                ++varyingTrackIndex;
+                return result;
+            }
+        }
+        return nullptr;
+    }
+
 private:
     const Vector<Vector<Vector<RenderBox*, 1> > >& m_grid;
     TrackSizingDirection m_direction;
@@ -491,13 +511,18 @@
     for (size_t i = 0; i < m_grid.size(); ++i)
         m_grid[i].grow(maximumColumnIndex);
 
-    Vector<RenderBox*> autoGridItems;
+    Vector<RenderBox*> autoMajorAxisAutoGridItems;
+    Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
     GridAutoFlow autoFlow = style()->gridAutoFlow();
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
         const GridPosition& columnPosition = child->style()->gridItemColumn();
         const GridPosition& rowPosition = child->style()->gridItemRow();
         if (autoFlow != AutoFlowNone && (columnPosition.isAuto() || rowPosition.isAuto())) {
-            autoGridItems.append(child);
+            const GridPosition& majorAxisPosition = autoPlacementMajorAxisPositionForChild(child);
+            if (majorAxisPosition.isAuto())
+                autoMajorAxisAutoGridItems.append(child);
+            else
+                specifiedMajorAxisAutoGridItems.append(child);
             continue;
         }
         size_t columnTrack = resolveGridPositionFromStyle(columnPosition);
@@ -510,13 +535,27 @@
 
     if (autoFlow == AutoFlowNone) {
         // If we did collect some grid items, they won't be placed thus never laid out.
-        ASSERT(!autoGridItems.size());
+        ASSERT(!autoMajorAxisAutoGridItems.size());
+        ASSERT(!specifiedMajorAxisAutoGridItems.size());
         return;
     }
 
-    // FIXME: This should implement the auto flow algorithm (https://bugs.webkit.org/b/103316).
-    // To keep our tests passing, we just insert them in the grid as if grid-auto-flow was none.
+    placeSpecifiedMajorAxisItemsOnGrid(specifiedMajorAxisAutoGridItems);
+    placeAutoMajorAxisItemsOnGrid(autoMajorAxisAutoGridItems);
+}
+
+void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
+{
     for (size_t i = 0; i < autoGridItems.size(); ++i) {
+        const GridPosition& majorAxisPosition = autoPlacementMajorAxisPositionForChild(autoGridItems[i]);
+        ASSERT(!majorAxisPosition.isAuto());
+        GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), resolveGridPositionFromStyle(majorAxisPosition));
+        if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
+            insertItemIntoGrid(autoGridItems[i], emptyGridArea->rowIndex, emptyGridArea->columnIndex);
+            continue;
+        }
+
+        // FIXME: Handle growing the grid in the minor axis instead of defaulting to the first row / column.
         const GridPosition& columnPosition = autoGridItems[i]->style()->gridItemColumn();
         const GridPosition& rowPosition = autoGridItems[i]->style()->gridItemRow();
         size_t columnTrack = columnPosition.isAuto() ? 0 : resolveGridPositionFromStyle(columnPosition);
@@ -526,6 +565,73 @@
     }
 }
 
+void RenderGrid::placeAutoMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
+{
+    for (size_t i = 0; i < autoGridItems.size(); ++i) {
+        ASSERT(autoPlacementMajorAxisPositionForChild(autoGridItems[i]).isAuto());
+        placeAutoMajorAxisItemOnGrid(autoGridItems[i]);
+    }
+}
+
+void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
+{
+    ASSERT(autoPlacementMajorAxisPositionForChild(gridItem).isAuto());
+    const GridPosition& minorAxisPosition = autoPlacementMinorAxisPositionForChild(gridItem);
+    if (!minorAxisPosition.isAuto()) {
+        GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), resolveGridPositionFromStyle(minorAxisPosition));
+        if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
+            insertItemIntoGrid(gridItem, emptyGridArea->rowIndex, emptyGridArea->columnIndex);
+            return;
+        }
+    } 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->rowIndex, emptyGridArea->columnIndex);
+                return;
+            }
+        }
+    }
+
+
+    // FIXME: Handle extending the grid in the major direction instead of defaulting to the first row / column.
+    const GridPosition& columnPosition = gridItem->style()->gridItemColumn();
+    const GridPosition& rowPosition = gridItem->style()->gridItemRow();
+    size_t columnTrack = columnPosition.isAuto() ? 0 : resolveGridPositionFromStyle(columnPosition);
+    size_t rowTrack = rowPosition.isAuto() ? 0 : resolveGridPositionFromStyle(rowPosition);
+
+    insertItemIntoGrid(gridItem, rowTrack, columnTrack);
+}
+
+const GridPosition& RenderGrid::autoPlacementMajorAxisPositionForChild(const RenderBox* gridItem) const
+{
+    GridAutoFlow flow = style()->gridAutoFlow();
+    ASSERT(flow != AutoFlowNone);
+    return (flow == AutoFlowColumn) ? gridItem->style()->gridItemColumn() : gridItem->style()->gridItemRow();
+}
+
+const GridPosition& RenderGrid::autoPlacementMinorAxisPositionForChild(const RenderBox* gridItem) const
+{
+    GridAutoFlow flow = style()->gridAutoFlow();
+    ASSERT(flow != AutoFlowNone);
+    return (flow == AutoFlowColumn) ? gridItem->style()->gridItemRow() : gridItem->style()->gridItemColumn();
+}
+
+RenderGrid::TrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
+{
+    GridAutoFlow flow = style()->gridAutoFlow();
+    ASSERT(flow != AutoFlowNone);
+    return (flow == AutoFlowColumn) ? ForColumns : ForRows;
+}
+
+RenderGrid::TrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
+{
+    GridAutoFlow flow = style()->gridAutoFlow();
+    ASSERT(flow != AutoFlowNone);
+    return (flow == AutoFlowColumn) ? ForRows : ForColumns;
+}
+
 void RenderGrid::clearGrid()
 {
     m_grid.clear();

Modified: trunk/Source/WebCore/rendering/RenderGrid.h (143534 => 143535)


--- trunk/Source/WebCore/rendering/RenderGrid.h	2013-02-21 00:32:33 UTC (rev 143534)
+++ trunk/Source/WebCore/rendering/RenderGrid.h	2013-02-21 00:33:49 UTC (rev 143535)
@@ -75,8 +75,17 @@
     LayoutUnit computeUsedBreadthOfMaxLength(TrackSizingDirection, const Length&) const;
     LayoutUnit computeUsedBreadthOfSpecifiedLength(TrackSizingDirection, const Length&) const;
     void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace);
+
     void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack);
     void placeItemsOnGrid();
+    void placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*>);
+    void placeAutoMajorAxisItemsOnGrid(Vector<RenderBox*>);
+    void placeAutoMajorAxisItemOnGrid(RenderBox*);
+    const GridPosition& autoPlacementMajorAxisPositionForChild(const RenderBox*) const;
+    const GridPosition& autoPlacementMinorAxisPositionForChild(const RenderBox*) const;
+    TrackSizingDirection autoPlacementMajorAxisDirection() const;
+    TrackSizingDirection autoPlacementMinorAxisDirection() const;
+
     void layoutGridItems();
     void clearGrid();
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to