[CSS Grid Layout] Interaction between auto-placement and column / row spanning
authorrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jun 2014 16:41:08 +0000 (16:41 +0000)
committerrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jun 2014 16:41:08 +0000 (16:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=110633

Reviewed by Sergio Villar Senin.

Source/WebCore:
Modify auto-placement algorithm in order to support span in both
definite and automatic positions.

This patch fixes examples like:
grid-row: auto;
grid-column: 2 / span 3;

And also:
grid-row: auto;
grid-column: span 3;

Tests: fast/css-grid-layout/grid-item-auto-placement-automatic-span.html
       fast/css-grid-layout/grid-item-auto-placement-definite-span.html

* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::GridIterator::isEmptyAreaEnough): New method that
checks if a grid area is or not empty.
(WebCore::RenderGrid::GridIterator::nextEmptyGridArea): Updated method
that now receives two arguments with the span value in both directions.
(WebCore::RenderGrid::ensureGridSize): Renamed from gridRow(). Adapted
method to grow in both directions at the same time if needed. It ensures
that the grid is big enough to insert a new item.
(WebCore::RenderGrid::insertItemIntoGrid): Only leave the method that
receives a GridCoordinate. It uses ensureGridSize() before inserting the
item in the grid.
(WebCore::RenderGrid::populateExplicitGridAndOrderIterator): Ensure that
the grid is big enough to place the largest span for auto-positioned
items.
(WebCore::RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid):
New method that returns a GridCoordinate outside current grid with the
requested dimensions.
(WebCore::RenderGrid::placeSpecifiedMajorAxisItemsOnGrid): Adapted
method to calculate the item's span and use the new version of
nextEmptyGridArea(). If an empty area is not found it uses
createEmptyGridAreaAtSpecifiedPositionsOutsideGrid() to place the item.
(WebCore::RenderGrid::placeAutoMajorAxisItemOnGrid): Ditto.
(WebCore::RenderGrid::growGrid): Renamed to ensureGridSize().
* rendering/RenderGrid.h: Modify methods headers and add new method
signature.
* rendering/style/GridCoordinate.h:
(WebCore::GridSpan::integerSpan): Add new simple method to return the
span value of a position.
* rendering/style/GridResolvedPosition.cpp:
(WebCore::GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition):
Implement method to take into account span in auto-placement algorithm.
(WebCore::GridResolvedPosition::adjustGridPositionsFromStyle): Add new
checks related with named grid line spans in auto-positioned items,
which is not allowed according to the spec.
* rendering/style/GridResolvedPosition.h: Update method header.

LayoutTests:
Add new specific test cases for span in auto-placement algorithm.

* fast/css-grid-layout/grid-item-auto-placement-automatic-span-expected.txt: Added.
* fast/css-grid-layout/grid-item-auto-placement-automatic-span.html: Added.
* fast/css-grid-layout/grid-item-auto-placement-definite-span-expected.txt: Added.
* fast/css-grid-layout/grid-item-auto-placement-definite-span.html: Added.
* fast/css-grid-layout/grid-item-spanning-resolution.html: Update test
case now that span in auto-positioned items is supported.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@170531 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-item-auto-placement-automatic-span-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-placement-automatic-span.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-placement-definite-span-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-placement-definite-span.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-spanning-resolution.html
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h
Source/WebCore/rendering/style/GridCoordinate.h
Source/WebCore/rendering/style/GridResolvedPosition.cpp
Source/WebCore/rendering/style/GridResolvedPosition.h

index a9314ff..70bdfb1 100644 (file)
@@ -1,3 +1,19 @@
+2014-06-27  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [CSS Grid Layout] Interaction between auto-placement and column / row spanning
+        https://bugs.webkit.org/show_bug.cgi?id=110633
+
+        Reviewed by Sergio Villar Senin.
+
+        Add new specific test cases for span in auto-placement algorithm.
+
+        * fast/css-grid-layout/grid-item-auto-placement-automatic-span-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-auto-placement-automatic-span.html: Added.
+        * fast/css-grid-layout/grid-item-auto-placement-definite-span-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-auto-placement-definite-span.html: Added.
+        * fast/css-grid-layout/grid-item-spanning-resolution.html: Update test
+        case now that span in auto-positioned items is supported.
+
 2014-06-27  Mahesh Kulkarni  <mahesh.kk@samsung.com>
 
         [XHR] open method must uppercase only standard method types
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-automatic-span-expected.txt b/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-automatic-span-expected.txt
new file mode 100644 (file)
index 0000000..0d212e5
--- /dev/null
@@ -0,0 +1,10 @@
+Thist test checks that span is supported in auto-placement for automatic positions.
+
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-automatic-span.html b/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-automatic-span.html
new file mode 100644 (file)
index 0000000..6c2cf11
--- /dev/null
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    -webkit-grid-auto-rows: 50px;
+    -webkit-grid-auto-columns: 100px;
+}
+
+.gridNamedGridLinesColumns {
+    -webkit-grid-template-columns: 50px 100px (line) 200px (line);
+}
+
+.gridNamedGridLinesRows {
+    -webkit-grid-template-rows: 50px 100px (line) 200px (line);
+}
+
+.autoRowAutoColumnSpanning2 {
+    background-color: maroon;
+    -webkit-grid-column: span 2;
+    -webkit-grid-row: auto;
+}
+
+.autoRowAutoColumnSpanning3 {
+    background-color: teal;
+    -webkit-grid-column: span 3;
+    -webkit-grid-row: auto;
+}
+
+.autoRowSpanning2AutoColumn {
+    background-color: aqua;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: span 2;
+}
+
+.autoRowSpanning3AutoColumn {
+    background-color: salmon;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: span 3;
+}
+
+.autoRowSpanning2AutoColumnSpanning2 {
+    background-color: olive;
+    -webkit-grid-column: span 2;
+    -webkit-grid-row: span 2;
+}
+
+.autoRowAutoColumnSpanningLine {
+    background-color: indigo;
+    -webkit-grid-column: span line; /* This is treated as "span 1". */
+    -webkit-grid-row: auto;
+}
+
+.autoRowSpanningLineAutoColumn {
+    background-color: moccasin;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: span line; /* This is treated as "span 1". */
+}
+
+.autoRowAutoColumnSpanning2Line {
+    background-color: sienna;
+    -webkit-grid-column: span 2 line; /* This is treated as "span 1". */
+    -webkit-grid-row: auto;
+}
+
+.autoRowSpanning2LineAutoColumn {
+    background-color: tomato;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: span 2 line; /* This is treated as "span 1". */
+}
+</style>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.grid');">
+
+<p>Thist test checks that span is supported in auto-placement for automatic positions.</p>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowRow">
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2" data-offset-x="100" data-offset-y="50" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning3" data-offset-x="0" data-offset-y="100" data-expected-width="300" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="0" data-offset-y="150" data-expected-width="200" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="200" data-offset-y="150" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="200" data-offset-y="200" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="250" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="100" data-offset-y="250" data-expected-width="200" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="300" data-expected-width="100" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowRow">
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowThirdColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning3" data-offset-x="0" data-offset-y="100" data-expected-width="300" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSecondColumn" data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2" data-offset-x="0" data-offset-y="150" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2" data-offset-x="0" data-offset-y="200" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="250" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning3" data-offset-x="0" data-offset-y="300" data-expected-width="300" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2" data-offset-x="100" data-offset-y="250" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="0" data-offset-y="350" data-expected-width="200" data-expected-height="100"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowRow">
+        <div class="sizedToGridArea autoRowSpanning2AutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSecondColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowThirdColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="100" data-offset-y="50" data-expected-width="200" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSpanning3AutoColumn" data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="150"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="100" data-offset-y="150" data-expected-width="200" data-expected-height="100"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowRow gridNamedGridLinesColumns">
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="0" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2Line" data-offset-x="50" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSecondColumn" data-offset-x="50" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2Line" data-offset-x="150" data-offset-y="0" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowThirdColumn" data-offset-x="150" data-offset-y="50" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanningLine" data-offset-x="0" data-offset-y="50" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2Line" data-offset-x="0" data-offset-y="100" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowFirstColumn" data-offset-x="0" data-offset-y="150" data-expected-width="50" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanningLine" data-offset-x="50" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowThirdColumn" data-offset-x="150" data-offset-y="100" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanningLine" data-offset-x="50" data-offset-y="150" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanningLine" data-offset-x="150" data-offset-y="150" data-expected-width="200" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowColumn">
+        <div class="sizedToGridArea autoRowSpanning2AutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumn" data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSpanning3AutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="150"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="300" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="300" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="400" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="500" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="500" data-offset-y="50" data-expected-width="200" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="600" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowColumn">
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea thirdRowAutoColumn" data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning3AutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="150"></div>
+        <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumn" data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumn" data-offset-x="400" data-offset-y="0" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="500" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning3AutoColumn" data-offset-x="600" data-offset-y="0" data-expected-width="100" data-expected-height="150"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumn" data-offset-x="500" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="700" data-offset-y="0" data-expected-width="200" data-expected-height="100"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowColumn">
+        <div class="sizedToGridArea autoRowAutoColumnSpanning2" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea thirdRowAutoColumn" data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="100" data-offset-y="50" data-expected-width="200" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowAutoColumnSpanning3" data-offset-x="200" data-offset-y="0" data-expected-width="300" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2AutoColumnSpanning2" data-offset-x="300" data-offset-y="50" data-expected-width="200" data-expected-height="100"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowColumn gridNamedGridLinesRows">
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2LineAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea secondRowAutoColumn" data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSpanning2LineAutoColumn" data-offset-x="0" data-offset-y="150" data-expected-width="100" data-expected-height="200"></div>
+        <div class="sizedToGridArea thirdRowAutoColumn" data-offset-x="100" data-offset-y="150" data-expected-width="100" data-expected-height="200"></div>
+        <div class="sizedToGridArea autoRowSpanningLineAutoColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanning2LineAutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea firstRowAutoColumn" data-offset-x="300" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSpanningLineAutoColumn" data-offset-x="200" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea thirdRowAutoColumn" data-offset-x="200" data-offset-y="150" data-expected-width="100" data-expected-height="200"></div>
+        <div class="sizedToGridArea autoRowSpanningLineAutoColumn" data-offset-x="300" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea autoRowSpanningLineAutoColumn" data-offset-x="300" data-offset-y="150" data-expected-width="100" data-expected-height="200"></div-->
+    </div>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-definite-span-expected.txt b/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-definite-span-expected.txt
new file mode 100644 (file)
index 0000000..4a38b32
--- /dev/null
@@ -0,0 +1,6 @@
+Thist test checks that span is supported in auto-placement for definite positions.
+
+PASS
+PASS
+PASS
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-definite-span.html b/LayoutTests/fast/css-grid-layout/grid-item-auto-placement-definite-span.html
new file mode 100644 (file)
index 0000000..9fe5c0f
--- /dev/null
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<link href="resources/grid.css" rel="stylesheet">
+<style>
+.grid {
+    -webkit-grid-auto-rows: 50px;
+    -webkit-grid-auto-columns: 100px;
+}
+
+.autoRowFirstColumnSpanning2 {
+    background-color: maroon;
+    -webkit-grid-column: 1 / span 2;
+    -webkit-grid-row: auto;
+}
+
+.autoRowSecondColumnSpanning2 {
+    background-color: olive;
+    -webkit-grid-column: 2 / span 2;
+    -webkit-grid-row: auto;
+}
+
+.autoRowFirstColumnSpanning3 {
+    background-color: teal;
+    -webkit-grid-column: 1 / span 3;
+    -webkit-grid-row: auto;
+}
+
+.firstRowSpanning2AutoColumn {
+    background-color: maroon;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: 1 / span 2;
+    height: 100%;
+}
+
+.secondRowSpanning2AutoColumn {
+    background-color: olive;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: 2 / span 2;
+    height: 100%;
+}
+
+.firstRowSpanning3AutoColumn {
+    background-color: teal;
+    -webkit-grid-column: auto;
+    -webkit-grid-row: 1 / span 3;
+    height: 100%;
+}
+</style>
+<script src="../../resources/check-layout.js"></script>
+<body onload="checkLayout('.grid');">
+
+<p>Thist test checks that span is supported in auto-placement for definite positions.</p>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowRow">
+        <div class="sizedToGridArea autoRowFirstColumnSpanning2" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSecondColumnSpanning2" data-offset-x="100" data-offset-y="50" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowFirstColumnSpanning3" data-offset-x="0" data-offset-y="100" data-expected-width="300" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowRow">
+        <div class="sizedToGridArea firstRowSpanning2AutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea secondRowSpanning2AutoColumn" data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea firstRowSpanning3AutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="150"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowColumn">
+        <div class="sizedToGridArea firstRowSpanning2AutoColumn" data-offset-x="0" data-offset-y="0" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea secondRowSpanning2AutoColumn" data-offset-x="100" data-offset-y="50" data-expected-width="100" data-expected-height="100"></div>
+        <div class="sizedToGridArea firstRowSpanning3AutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="150"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="100" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="100" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+    </div>
+</div>
+
+<div style="position: relative">
+    <div class="grid gridAutoFlowColumn">
+        <div class="sizedToGridArea autoRowFirstColumnSpanning2" data-offset-x="0" data-offset-y="0" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowSecondColumnSpanning2" data-offset-x="100" data-offset-y="50" data-expected-width="200" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowFirstColumnSpanning3" data-offset-x="0" data-offset-y="100" data-expected-width="300" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="0" data-offset-y="50" data-expected-width="100" data-expected-height="50"></div>
+        <div class="sizedToGridArea autoRowAutoColumn" data-offset-x="200" data-offset-y="0" data-expected-width="100" data-expected-height="50"></div>
+    </div>
+</div>
+
+</body>
+</html>
index ed0aa54..49e45ea 100644 (file)
 <div style="position: relative">
 <div class="grid" id="fixedGrid" style="-webkit-grid-auto-flow: row;">
     <div class="sizedToGridArea" style="-webkit-grid-column: 1; -webkit-grid-row: 1;" data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="15"></div>
-    <div class="sizedToGridArea doubleSpan" data-offset-x="10" data-offset-y="0" data-expected-width="20" data-expected-height="15"></div>
+    <div class="sizedToGridArea doubleSpan" data-offset-x="10" data-offset-y="0" data-expected-width="60" data-expected-height="105"></div>
 </div>
 
 <div style="position: relative">
 <div class="grid" id="fixedGrid" style="-webkit-grid-auto-flow: column;">
     <div class="sizedToGridArea" style="-webkit-grid-column: 1; -webkit-grid-row: 1;" data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="15"></div>
-    <div class="sizedToGridArea doubleSpan" data-offset-x="0" data-offset-y="15" data-expected-width="10" data-expected-height="30"></div>
+    <div class="sizedToGridArea doubleSpan" data-offset-x="0" data-offset-y="15" data-expected-width="30" data-expected-height="210"></div>
 </div>
 </body>
 </html>
index 288177f..0b935de 100644 (file)
@@ -1,3 +1,60 @@
+2014-06-27  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [CSS Grid Layout] Interaction between auto-placement and column / row spanning
+        https://bugs.webkit.org/show_bug.cgi?id=110633
+
+        Reviewed by Sergio Villar Senin.
+
+        Modify auto-placement algorithm in order to support span in both
+        definite and automatic positions.
+
+        This patch fixes examples like:
+        grid-row: auto;
+        grid-column: 2 / span 3;
+
+        And also:
+        grid-row: auto;
+        grid-column: span 3;
+
+        Tests: fast/css-grid-layout/grid-item-auto-placement-automatic-span.html
+               fast/css-grid-layout/grid-item-auto-placement-definite-span.html
+
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::GridIterator::isEmptyAreaEnough): New method that
+        checks if a grid area is or not empty.
+        (WebCore::RenderGrid::GridIterator::nextEmptyGridArea): Updated method
+        that now receives two arguments with the span value in both directions.
+        (WebCore::RenderGrid::ensureGridSize): Renamed from gridRow(). Adapted
+        method to grow in both directions at the same time if needed. It ensures
+        that the grid is big enough to insert a new item.
+        (WebCore::RenderGrid::insertItemIntoGrid): Only leave the method that
+        receives a GridCoordinate. It uses ensureGridSize() before inserting the
+        item in the grid.
+        (WebCore::RenderGrid::populateExplicitGridAndOrderIterator): Ensure that
+        the grid is big enough to place the largest span for auto-positioned
+        items.
+        (WebCore::RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid):
+        New method that returns a GridCoordinate outside current grid with the
+        requested dimensions.
+        (WebCore::RenderGrid::placeSpecifiedMajorAxisItemsOnGrid): Adapted
+        method to calculate the item's span and use the new version of
+        nextEmptyGridArea(). If an empty area is not found it uses
+        createEmptyGridAreaAtSpecifiedPositionsOutsideGrid() to place the item.
+        (WebCore::RenderGrid::placeAutoMajorAxisItemOnGrid): Ditto.
+        (WebCore::RenderGrid::growGrid): Renamed to ensureGridSize().
+        * rendering/RenderGrid.h: Modify methods headers and add new method
+        signature.
+        * rendering/style/GridCoordinate.h:
+        (WebCore::GridSpan::integerSpan): Add new simple method to return the
+        span value of a position.
+        * rendering/style/GridResolvedPosition.cpp:
+        (WebCore::GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition):
+        Implement method to take into account span in auto-placement algorithm.
+        (WebCore::GridResolvedPosition::adjustGridPositionsFromStyle): Add new
+        checks related with named grid line spans in auto-positioned items,
+        which is not allowed according to the spec.
+        * rendering/style/GridResolvedPosition.h: Update method header.
+
 2014-06-27  Mahesh Kulkarni  <mahesh.kk@samsung.com>
 
         [XHR] open method must uppercase only standard method types
index e6cd952..c61b4c1 100644 (file)
@@ -117,17 +117,39 @@ public:
         return 0;
     }
 
-    std::unique_ptr<GridCoordinate> nextEmptyGridArea()
+    bool isEmptyAreaEnough(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 Vector<RenderBox*>& children = m_grid[row][column];
+                if (!children.isEmpty())
+                    return false;
+            }
+        }
+
+        return true;
+    }
+
+    std::unique_ptr<GridCoordinate> nextEmptyGridArea(size_t fixedTrackSpan, size_t varyingTrackSpan)
+    {
+        ASSERT(fixedTrackSpan >= 1 && varyingTrackSpan >= 1);
+
         if (m_grid.isEmpty())
             return nullptr;
 
+        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 Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
-            if (children.isEmpty()) {
-                std::unique_ptr<GridCoordinate> result = std::make_unique<GridCoordinate>(GridSpan(m_rowIndex, m_rowIndex), GridSpan(m_columnIndex, m_columnIndex));
+            if (isEmptyAreaEnough(rowSpan, columnSpan)) {
+                std::unique_ptr<GridCoordinate> result = std::make_unique<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;
@@ -608,21 +630,25 @@ bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire
 }
 #endif
 
-void RenderGrid::growGrid(GridTrackSizingDirection direction)
+void RenderGrid::ensureGridSize(size_t maximumRowIndex, size_t maximumColumnIndex)
 {
-    if (direction == ForColumns) {
-        const size_t oldColumnSize = gridColumnCount();
+    const size_t oldRowCount = gridRowCount();
+    if (maximumRowIndex >= oldRowCount) {
+        m_grid.grow(maximumRowIndex + 1);
+        for (size_t row = oldRowCount; row < gridRowCount(); ++row)
+            m_grid[row].grow(gridColumnCount());
+    }
+
+    if (maximumColumnIndex >= gridColumnCount()) {
         for (size_t row = 0; row < gridRowCount(); ++row)
-            m_grid[row].grow(oldColumnSize + 1);
-    } else {
-        const size_t oldRowSize = gridRowCount();
-        m_grid.grow(oldRowSize + 1);
-        m_grid[oldRowSize].grow(gridColumnCount());
+            m_grid[row].grow(maximumColumnIndex + 1);
     }
 }
 
 void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
 {
+    ensureGridSize(coordinate.rows.resolvedFinalPosition.toInt(), coordinate.columns.resolvedFinalPosition.toInt());
+
     for (auto row : coordinate.rows) {
         for (auto column : coordinate.columns)
             m_grid[row.toInt()][column.toInt()].append(child);
@@ -630,13 +656,6 @@ void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coor
     m_gridItemCoordinate.set(child, coordinate);
 }
 
-void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridResolvedPosition& rowTrack, const GridResolvedPosition& columnTrack)
-{
-    const GridSpan& rowSpan = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*child, ForRows, rowTrack);
-    const GridSpan& columnSpan = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*child, ForColumns, columnTrack);
-    insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
-}
-
 void RenderGrid::placeItemsOnGrid()
 {
     ASSERT(!gridWasPopulated());
@@ -690,12 +709,22 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
         std::unique_ptr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *child, ForRows);
         std::unique_ptr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *child, ForColumns);
 
-        // |positions| is 0 if we need to run the auto-placement algorithm. Our estimation ignores
-        // this case as the auto-placement algorithm will grow the grid as needed.
+        // |positions| is 0 if we need to run the auto-placement algorithm.
         if (rowPositions)
             maximumRowIndex = std::max(maximumRowIndex, rowPositions->resolvedFinalPosition.next().toInt());
+        else {
+            // Grow the grid for items with a definite row span, getting the largest such span.
+            GridSpan positions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(style(), *child, ForRows, GridResolvedPosition(0));
+            maximumRowIndex = std::max<size_t>(maximumRowIndex, positions.resolvedFinalPosition.next().toInt());
+        }
+
         if (columnPositions)
             maximumColumnIndex = std::max(maximumColumnIndex, columnPositions->resolvedFinalPosition.next().toInt());
+        else {
+            // Grow the grid for items with a definite column span, getting the largest such span.
+            GridSpan positions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(style(), *child, ForColumns, GridResolvedPosition(0));
+            maximumColumnIndex = std::max<size_t>(maximumColumnIndex, positions.resolvedFinalPosition.next().toInt());
+        }
     }
 
     m_grid.grow(maximumRowIndex);
@@ -703,20 +732,25 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
         m_grid[i].grow(maximumColumnIndex);
 }
 
+std::unique_ptr<GridCoordinate> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(const RenderBox* gridItem, GridTrackSizingDirection specifiedDirection, const GridSpan& specifiedPositions) const
+{
+    GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
+    const size_t endOfCrossDirection = crossDirection == ForColumns ? gridColumnCount() : gridRowCount();
+    GridSpan crossDirectionPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(style(), *gridItem, crossDirection, GridResolvedPosition(endOfCrossDirection));
+    return std::make_unique<GridCoordinate>(specifiedDirection == ForColumns ? crossDirectionPositions : specifiedPositions, specifiedDirection == ForColumns ? specifiedPositions : crossDirectionPositions);
+}
+
 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGridItems)
 {
     for (auto& autoGridItem : autoGridItems) {
         std::unique_ptr<GridSpan> majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *autoGridItem, autoPlacementMajorAxisDirection());
-        GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->resolvedInitialPosition.toInt());
-        if (std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
-            insertItemIntoGrid(autoGridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
-            continue;
-        }
+        GridSpan minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(style(), *autoGridItem, autoPlacementMinorAxisDirection(), GridResolvedPosition(0));
 
-        growGrid(autoPlacementMinorAxisDirection());
-        std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
-        ASSERT(emptyGridArea);
-        insertItemIntoGrid(autoGridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
+        GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->resolvedInitialPosition.toInt());
+        std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea(majorAxisPositions->integerSpan(), minorAxisPositions.integerSpan());
+        if (!emptyGridArea)
+            emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(autoGridItem, autoPlacementMajorAxisDirection(), *majorAxisPositions);
+        insertItemIntoGrid(autoGridItem, *emptyGridArea);
     }
 }
 
@@ -730,30 +764,39 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
 {
     std::unique_ptr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *gridItem, autoPlacementMinorAxisDirection());
     ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(style(), *gridItem, autoPlacementMajorAxisDirection()));
-    size_t minorAxisIndex = 0;
+    GridSpan majorAxisPositions = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(style(), *gridItem, autoPlacementMajorAxisDirection(), GridResolvedPosition(0));
+    std::unique_ptr<GridCoordinate> emptyGridArea;
     if (minorAxisPositions) {
-        minorAxisIndex = minorAxisPositions->resolvedInitialPosition.toInt();
-        GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisIndex);
-        if (std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
-            insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
-            return;
-        }
+        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) {
             GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisIndex);
-            if (std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
-                insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
-                return;
+            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()).
+                GridResolvedPosition minorAxisFinalPositionIndex = autoPlacementMinorAxisDirection() == ForColumns ? emptyGridArea->columns.resolvedFinalPosition : emptyGridArea->rows.resolvedFinalPosition;
+                const size_t endOfMinorAxis = autoPlacementMinorAxisDirection() == ForColumns ? gridColumnCount() : gridRowCount();
+                if (minorAxisFinalPositionIndex.toInt() < endOfMinorAxis)
+                    break;
+
+                // Discard empty grid area as it does not fit in the minor axis direction.
+                // We don't need to create a new empty grid area yet as we might find a valid one in the next iteration.
+                emptyGridArea = nullptr;
             }
         }
+
+        if (!emptyGridArea)
+            emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(gridItem, autoPlacementMinorAxisDirection(), minorAxisPositions);
     }
 
-    // We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it.
-    const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : minorAxisIndex;
-    const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : gridRowCount();
-    growGrid(autoPlacementMajorAxisDirection());
-    insertItemIntoGrid(gridItem, rowIndex, columnIndex);
+    insertItemIntoGrid(gridItem, *emptyGridArea);
 }
 
 GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
index 3b3b6eb..549a63f 100644 (file)
@@ -70,11 +70,11 @@ private:
     LayoutUnit computeUsedBreadthOfSpecifiedLength(GridTrackSizingDirection, const Length&) const;
     void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&);
 
-    void growGrid(GridTrackSizingDirection);
-    void insertItemIntoGrid(RenderBox*, const GridResolvedPosition& rowTrack, const GridResolvedPosition& columnTrack);
+    void ensureGridSize(size_t maximumRowIndex, size_t maximumColumnIndex);
     void insertItemIntoGrid(RenderBox*, const GridCoordinate&);
     void placeItemsOnGrid();
     void populateExplicitGridAndOrderIterator();
+    std::unique_ptr<GridCoordinate> createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(const RenderBox*, GridTrackSizingDirection, const GridSpan&) const;
     void placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>&);
     void placeAutoMajorAxisItemsOnGrid(const Vector<RenderBox*>&);
     void placeAutoMajorAxisItemOnGrid(RenderBox*);
index 39c4a3b..583af5b 100644 (file)
@@ -57,6 +57,11 @@ public:
         return resolvedInitialPosition == o.resolvedInitialPosition && resolvedFinalPosition == o.resolvedFinalPosition;
     }
 
+    size_t integerSpan() const
+    {
+        return resolvedFinalPosition.toInt() - resolvedInitialPosition.toInt() + 1;
+    }
+
     GridResolvedPosition resolvedInitialPosition;
     GridResolvedPosition resolvedFinalPosition;
 
index 7fb36cb..ed7c984 100644 (file)
@@ -53,11 +53,26 @@ static size_t explicitGridSizeForSide(const RenderStyle& gridContainerStyle, Gri
     return isColumnSide(side) ? gridContainerStyle.gridColumns().size() : gridContainerStyle.gridRows().size();
 }
 
-GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(const RenderBox&, GridTrackSizingDirection, const GridResolvedPosition& initialPosition)
+GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, const GridResolvedPosition& resolvedInitialPosition)
 {
-    // FIXME: We don't support spanning with auto positions yet. Once we do, this is wrong. Also we should make
-    // sure the grid can accomodate the new item as we only grow 1 position in a given direction.
-    return GridSpan(initialPosition, initialPosition);
+    GridPosition initialPosition = (direction == ForColumns) ? gridItem.style().gridItemColumnStart() : gridItem.style().gridItemRowStart();
+    const GridPositionSide initialPositionSide = (direction == ForColumns) ? ColumnStartSide : RowStartSide;
+    GridPosition finalPosition = (direction == ForColumns) ? gridItem.style().gridItemColumnEnd() : gridItem.style().gridItemRowEnd();
+    const GridPositionSide finalPositionSide = (direction == ForColumns) ? ColumnEndSide : RowEndSide;
+
+    adjustGridPositionsFromStyle(gridContainerStyle, initialPosition, finalPosition, initialPositionSide, finalPositionSide);
+
+    // This method will only be used when both positions need to be resolved against the opposite one.
+    ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition());
+
+    GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition;
+
+    if (initialPosition.isSpan())
+        resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, initialPosition, finalPositionSide)->resolvedFinalPosition;
+    else if (finalPosition.isSpan())
+        resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, finalPosition, finalPositionSide)->resolvedFinalPosition;
+
+    return GridSpan(resolvedInitialPosition, resolvedFinalPosition);
 }
 
 static inline const NamedGridLinesMap& gridLinesForSide(const RenderStyle& style, GridPositionSide side)
@@ -93,6 +108,12 @@ void GridResolvedPosition::adjustGridPositionsFromStyle(const RenderStyle& gridC
 
     if (finalPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide))
         finalPosition.setAutoPosition();
+
+    // If the grid item has an automatic position and a grid span for a named line in a given dimension, instead treat the grid span as one.
+    if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.namedGridLine().isNull())
+        finalPosition.setSpanPosition(1, String());
+    if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.namedGridLine().isNull())
+        initialPosition.setSpanPosition(1, String());
 }
 
 std::unique_ptr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction)
index db3d21a..263b524 100644 (file)
@@ -71,7 +71,7 @@ public:
         return GridResolvedPosition(resolvedPosition);
     }
 
-    static GridSpan resolveGridPositionsFromAutoPlacementPosition(const RenderBox&, GridTrackSizingDirection, const GridResolvedPosition&);
+    static GridSpan resolveGridPositionsFromAutoPlacementPosition(const RenderStyle&, const RenderBox&, GridTrackSizingDirection, const GridResolvedPosition&);
     static void adjustNamedGridItemPosition(const RenderStyle&, GridPosition&, GridPositionSide);
     static void adjustGridPositionsFromStyle(const RenderStyle&, GridPosition& initialPosition, GridPosition& finalPosition, GridPositionSide initialPositionSide, GridPositionSide finalPositionSide);
     static std::unique_ptr<GridSpan> resolveGridPositionsFromStyle(const RenderStyle&, const RenderBox&, GridTrackSizingDirection);