[CSS Grid Layout] Introduce an explicit type for resolved grid positions
authorrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Jun 2014 13:09:58 +0000 (13:09 +0000)
committerrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Jun 2014 13:09:58 +0000 (13:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131732

Reviewed by Sergio Villar Senin.

We were using simple size_t integers to represent resolved grid
positions in our internal data structures. This change allows us to
clarify the code, avoid potential off by one mistakes, and move the
resolving code to a central place.

A new class GridResolvedPosition has been created and the related
methods have been moved there from RenderGrid.
GridSpan is now defined by two GridResolvedPosition, so all the code
using it has been modified to adapt it to GridResolvedPosition.

No new tests as it is already covered by current tests
(fast/css-grid-layout/).

* CMakeLists.txt:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSGridTemplateAreasValue.cpp:
(WebCore::stringForPosition):
* css/CSSParser.cpp:
(WebCore::CSSParser::parseGridTemplateAreasRow):
* css/StyleResolver.cpp:
(WebCore::createImplicitNamedGridLinesFromGridArea):
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::computeUsedBreadthOfGridTracks):
(WebCore::RenderGrid::computeNormalizedFractionBreadth):
(WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
(WebCore::RenderGrid::insertItemIntoGrid):
(WebCore::RenderGrid::placeItemsOnGrid):
(WebCore::RenderGrid::populateExplicitGridAndOrderIterator):
(WebCore::RenderGrid::placeSpecifiedMajorAxisItemsOnGrid):
(WebCore::RenderGrid::placeAutoMajorAxisItemOnGrid):
(WebCore::RenderGrid::autoPlacementMajorAxisDirection):
(WebCore::RenderGrid::autoPlacementMinorAxisDirection):
(WebCore::RenderGrid::gridAreaBreadthForChild):
(WebCore::RenderGrid::findChildLogicalPosition):
(WebCore::RenderGrid::explicitGridColumnCount): Deleted.
(WebCore::RenderGrid::explicitGridRowCount): Deleted.
(WebCore::isColumnSide): Deleted.
(WebCore::isStartSide): Deleted.
(WebCore::RenderGrid::explicitGridSizeForSide): Deleted.
(WebCore::RenderGrid::resolveGridPositionsFromAutoPlacementPosition): Deleted.
(WebCore::gridLinesForSide): Deleted.
(WebCore::implicitNamedGridLineForSide): Deleted.
(WebCore::isNonExistentNamedLineOrArea): Deleted.
(WebCore::RenderGrid::adjustGridPositionsFromStyle): Deleted.
(WebCore::RenderGrid::resolveGridPositionsFromStyle): Deleted.
(WebCore::RenderGrid::resolveNamedGridLinePositionFromStyle): Deleted.
(WebCore::RenderGrid::resolveGridPositionFromStyle): Deleted.
(WebCore::RenderGrid::resolveGridPositionAgainstOppositePosition): Deleted.
(WebCore::RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition): Deleted.
(WebCore::firstNamedGridLineBeforePosition): Deleted.
(WebCore::RenderGrid::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition): Deleted.
(WebCore::RenderGrid::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition): Deleted.
* rendering/RenderGrid.h:
* rendering/style/GridCoordinate.h:
(WebCore::GridSpan::GridSpan):
(WebCore::GridSpan::operator==):
* rendering/style/GridPosition.h:
(WebCore::GridPosition::adjustGridPositionForRowEndColumnEndSide): Deleted.
(WebCore::GridPosition::adjustGridPositionForSide): Deleted.
* rendering/style/GridResolvedPosition.cpp: Added.
(WebCore::isColumnSide):
(WebCore::isStartSide):
(WebCore::explicitGridSizeForSide):
(WebCore::GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition):
(WebCore::gridLinesForSide):
(WebCore::implicitNamedGridLineForSide):
(WebCore::isNonExistentNamedLineOrArea):
(WebCore::GridResolvedPosition::adjustGridPositionsFromStyle):
(WebCore::GridResolvedPosition::resolveGridPositionsFromStyle):
(WebCore::GridResolvedPosition::resolveNamedGridLinePositionFromStyle):
(WebCore::GridResolvedPosition::resolveGridPositionFromStyle):
(WebCore::GridResolvedPosition::resolveGridPositionAgainstOppositePosition):
(WebCore::GridResolvedPosition::resolveNamedGridLinePositionAgainstOppositePosition):
(WebCore::firstNamedGridLineBeforePosition):
(WebCore::GridResolvedPosition::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition):
(WebCore::GridResolvedPosition::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition):
* rendering/style/GridResolvedPosition.h: Added.
(WebCore::GridResolvedPosition::adjustGridPositionForRowEndColumnEndSide):
(WebCore::GridResolvedPosition::adjustGridPositionForSide):
(WebCore::GridResolvedPosition::GridResolvedPosition):
(WebCore::GridResolvedPosition::operator++):
(WebCore::GridResolvedPosition::operator==):
(WebCore::GridResolvedPosition::operator<):
(WebCore::GridResolvedPosition::operator>):
(WebCore::GridResolvedPosition::operator<=):
(WebCore::GridResolvedPosition::operator>=):
(WebCore::GridResolvedPosition::toInt):
(WebCore::GridResolvedPosition::next):

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

14 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSGridTemplateAreasValue.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h
Source/WebCore/rendering/style/GridCoordinate.h
Source/WebCore/rendering/style/GridPosition.h
Source/WebCore/rendering/style/GridResolvedPosition.cpp [new file with mode: 0644]
Source/WebCore/rendering/style/GridResolvedPosition.h [new file with mode: 0644]

index 57eb8d2..de48284 100644 (file)
@@ -2387,6 +2387,7 @@ set(WebCore_SOURCES
     rendering/style/ContentData.cpp
     rendering/style/CounterDirectives.cpp
     rendering/style/FillLayer.cpp
+    rendering/style/GridResolvedPosition.cpp
     rendering/style/KeyframeList.cpp
     rendering/style/NinePieceImage.cpp
     rendering/style/QuotesData.cpp
index a40b7e7..4942d9f 100644 (file)
@@ -1,3 +1,101 @@
+2014-06-13  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [CSS Grid Layout] Introduce an explicit type for resolved grid positions
+        https://bugs.webkit.org/show_bug.cgi?id=131732
+
+        Reviewed by Sergio Villar Senin.
+
+        We were using simple size_t integers to represent resolved grid
+        positions in our internal data structures. This change allows us to
+        clarify the code, avoid potential off by one mistakes, and move the
+        resolving code to a central place.
+
+        A new class GridResolvedPosition has been created and the related
+        methods have been moved there from RenderGrid.
+        GridSpan is now defined by two GridResolvedPosition, so all the code
+        using it has been modified to adapt it to GridResolvedPosition.
+
+        No new tests as it is already covered by current tests
+        (fast/css-grid-layout/).
+
+        * CMakeLists.txt:
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.vcxproj/WebCore.vcxproj.filters:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSGridTemplateAreasValue.cpp:
+        (WebCore::stringForPosition):
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseGridTemplateAreasRow):
+        * css/StyleResolver.cpp:
+        (WebCore::createImplicitNamedGridLinesFromGridArea):
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::computeUsedBreadthOfGridTracks):
+        (WebCore::RenderGrid::computeNormalizedFractionBreadth):
+        (WebCore::RenderGrid::resolveContentBasedTrackSizingFunctionsForItems):
+        (WebCore::RenderGrid::insertItemIntoGrid):
+        (WebCore::RenderGrid::placeItemsOnGrid):
+        (WebCore::RenderGrid::populateExplicitGridAndOrderIterator):
+        (WebCore::RenderGrid::placeSpecifiedMajorAxisItemsOnGrid):
+        (WebCore::RenderGrid::placeAutoMajorAxisItemOnGrid):
+        (WebCore::RenderGrid::autoPlacementMajorAxisDirection):
+        (WebCore::RenderGrid::autoPlacementMinorAxisDirection):
+        (WebCore::RenderGrid::gridAreaBreadthForChild):
+        (WebCore::RenderGrid::findChildLogicalPosition):
+        (WebCore::RenderGrid::explicitGridColumnCount): Deleted.
+        (WebCore::RenderGrid::explicitGridRowCount): Deleted.
+        (WebCore::isColumnSide): Deleted.
+        (WebCore::isStartSide): Deleted.
+        (WebCore::RenderGrid::explicitGridSizeForSide): Deleted.
+        (WebCore::RenderGrid::resolveGridPositionsFromAutoPlacementPosition): Deleted.
+        (WebCore::gridLinesForSide): Deleted.
+        (WebCore::implicitNamedGridLineForSide): Deleted.
+        (WebCore::isNonExistentNamedLineOrArea): Deleted.
+        (WebCore::RenderGrid::adjustGridPositionsFromStyle): Deleted.
+        (WebCore::RenderGrid::resolveGridPositionsFromStyle): Deleted.
+        (WebCore::RenderGrid::resolveNamedGridLinePositionFromStyle): Deleted.
+        (WebCore::RenderGrid::resolveGridPositionFromStyle): Deleted.
+        (WebCore::RenderGrid::resolveGridPositionAgainstOppositePosition): Deleted.
+        (WebCore::RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition): Deleted.
+        (WebCore::firstNamedGridLineBeforePosition): Deleted.
+        (WebCore::RenderGrid::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition): Deleted.
+        (WebCore::RenderGrid::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition): Deleted.
+        * rendering/RenderGrid.h:
+        * rendering/style/GridCoordinate.h:
+        (WebCore::GridSpan::GridSpan):
+        (WebCore::GridSpan::operator==):
+        * rendering/style/GridPosition.h:
+        (WebCore::GridPosition::adjustGridPositionForRowEndColumnEndSide): Deleted.
+        (WebCore::GridPosition::adjustGridPositionForSide): Deleted.
+        * rendering/style/GridResolvedPosition.cpp: Added.
+        (WebCore::isColumnSide):
+        (WebCore::isStartSide):
+        (WebCore::explicitGridSizeForSide):
+        (WebCore::GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition):
+        (WebCore::gridLinesForSide):
+        (WebCore::implicitNamedGridLineForSide):
+        (WebCore::isNonExistentNamedLineOrArea):
+        (WebCore::GridResolvedPosition::adjustGridPositionsFromStyle):
+        (WebCore::GridResolvedPosition::resolveGridPositionsFromStyle):
+        (WebCore::GridResolvedPosition::resolveNamedGridLinePositionFromStyle):
+        (WebCore::GridResolvedPosition::resolveGridPositionFromStyle):
+        (WebCore::GridResolvedPosition::resolveGridPositionAgainstOppositePosition):
+        (WebCore::GridResolvedPosition::resolveNamedGridLinePositionAgainstOppositePosition):
+        (WebCore::firstNamedGridLineBeforePosition):
+        (WebCore::GridResolvedPosition::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition):
+        (WebCore::GridResolvedPosition::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition):
+        * rendering/style/GridResolvedPosition.h: Added.
+        (WebCore::GridResolvedPosition::adjustGridPositionForRowEndColumnEndSide):
+        (WebCore::GridResolvedPosition::adjustGridPositionForSide):
+        (WebCore::GridResolvedPosition::GridResolvedPosition):
+        (WebCore::GridResolvedPosition::operator++):
+        (WebCore::GridResolvedPosition::operator==):
+        (WebCore::GridResolvedPosition::operator<):
+        (WebCore::GridResolvedPosition::operator>):
+        (WebCore::GridResolvedPosition::operator<=):
+        (WebCore::GridResolvedPosition::operator>=):
+        (WebCore::GridResolvedPosition::toInt):
+        (WebCore::GridResolvedPosition::next):
+
 2014-06-12  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Remove all deprecated API from GObject DOM bindings
index 2450991..0cc2de1 100644 (file)
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\rendering\style\GridResolvedPosition.cpp" />
     <ClCompile Include="..\rendering\style\KeyframeList.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
     <ClInclude Include="..\rendering\style\GridCoordinate.h" />
     <ClInclude Include="..\rendering\style\GridLength.h" />
     <ClInclude Include="..\rendering\style\GridPosition.h" />
+    <ClInclude Include="..\rendering\style\GridResolvedPosition.h" />
     <ClInclude Include="..\rendering\style\GridTrackSize.h" />
     <ClInclude Include="..\rendering\style\KeyframeList.h" />
     <ClInclude Include="..\rendering\style\NinePieceImage.h" />
index 23eb6f8..7974d64 100644 (file)
     <ClCompile Include="..\rendering\style\FillLayer.cpp">
       <Filter>rendering\style</Filter>
     </ClCompile>
+    <ClCompile Include="..\rendering\style\GridResolvedPosition.cpp">
+      <Filter>rendering\style</Filter>
+    </ClCompile>
     <ClCompile Include="..\rendering\style\KeyframeList.cpp">
       <Filter>rendering\style</Filter>
     </ClCompile>
     <ClInclude Include="..\rendering\style\GridPosition.h">
       <Filter>rendering\style</Filter>
     </ClInclude>
+    <ClInclude Include="..\rendering\style\GridResolvedPosition.h">
+      <Filter>rendering\style</Filter>
+    </ClInclude>
     <ClInclude Include="..\rendering\style\GridTrackSize.h">
       <Filter>rendering\style</Filter>
     </ClInclude>
index 071d138..0aea705 100644 (file)
                CDF2B0191820540700F2B424 /* MockTracks.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF2B00F1820540600F2B424 /* MockTracks.h */; };
                CDF65CC8145B1E7500C4C7AA /* MediaController.h in Headers */ = {isa = PBXBuildFile; fileRef = CD27F6E4145767870078207D /* MediaController.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CDF65CCA145B448800C4C7AA /* MediaControllerInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF65CC9145B43A700C4C7AA /* MediaControllerInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               CDF7483E18FEBCEC0006ECC0 /* GridResolvedPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDF7483C18FEBCEC0006ECC0 /* GridResolvedPosition.cpp */; };
+               CDF7483F18FEBCEC0006ECC0 /* GridResolvedPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF7483D18FEBCEC0006ECC0 /* GridResolvedPosition.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CDFC360518CA61C20026E56F /* RemoteCommandListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDFC360318CA61C20026E56F /* RemoteCommandListener.cpp */; };
                CDFC360618CA61C20026E56F /* RemoteCommandListener.h in Headers */ = {isa = PBXBuildFile; fileRef = CDFC360418CA61C20026E56F /* RemoteCommandListener.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CDFC360718CA696C0026E56F /* RemoteCommandListenerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDFC360218CA61630026E56F /* RemoteCommandListenerIOS.mm */; };
                CDF2B00F1820540600F2B424 /* MockTracks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockTracks.h; sourceTree = "<group>"; };
                CDF65CC9145B43A700C4C7AA /* MediaControllerInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaControllerInterface.h; sourceTree = "<group>"; };
                CDF65CCC145B6AFE00C4C7AA /* JSHTMLMediaElementCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLMediaElementCustom.cpp; sourceTree = "<group>"; };
+               CDF7483C18FEBCEC0006ECC0 /* GridResolvedPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GridResolvedPosition.cpp; path = style/GridResolvedPosition.cpp; sourceTree = "<group>"; };
+               CDF7483D18FEBCEC0006ECC0 /* GridResolvedPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GridResolvedPosition.h; path = style/GridResolvedPosition.h; sourceTree = "<group>"; };
                CDFC360118CA61630026E56F /* RemoteCommandListenerIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RemoteCommandListenerIOS.h; path = ios/RemoteCommandListenerIOS.h; sourceTree = "<group>"; };
                CDFC360218CA61630026E56F /* RemoteCommandListenerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RemoteCommandListenerIOS.mm; path = ios/RemoteCommandListenerIOS.mm; sourceTree = "<group>"; };
                CDFC360318CA61C20026E56F /* RemoteCommandListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteCommandListener.cpp; sourceTree = "<group>"; };
                                CD3E251B18046B0600E27F56 /* GridCoordinate.h */,
                                CDEF4FD617E85C8F00AEE24B /* GridLength.h */,
                                A12705C21656BD6500C2E27C /* GridPosition.h */,
+                               CDF7483C18FEBCEC0006ECC0 /* GridResolvedPosition.cpp */,
+                               CDF7483D18FEBCEC0006ECC0 /* GridResolvedPosition.h */,
                                A12A104E166444DC008FA311 /* GridTrackSize.h */,
                                BC5EBA0E0E823E4700B25965 /* KeyframeList.cpp */,
                                BC5EBA0F0E823E4700B25965 /* KeyframeList.h */,
                                A80E7E9F0A1A83E3007FB8C5 /* JSHTMLButtonElement.h in Headers */,
                                938E666209F09B87008A48EC /* JSHTMLCanvasElement.h in Headers */,
                                BCCBAD410C18C14200CE890F /* JSHTMLCollection.h in Headers */,
+                               CDF7483F18FEBCEC0006ECC0 /* GridResolvedPosition.h in Headers */,
                                F5C041E70FFCA96D00839D4A /* JSHTMLDataListElement.h in Headers */,
                                D359D8BF129CA55C0006E5D2 /* JSHTMLDetailsElement.h in Headers */,
                                76808B50159DADFA002B5233 /* JSHTMLDialogElement.h in Headers */,
                                A4226E961163D73A008B8397 /* DOMHTMLProgressElement.mm in Sources */,
                                85183B4B0AA6926100F19FA3 /* DOMHTMLQuoteElement.mm in Sources */,
                                85DF819C0AA77E4B00486AD7 /* DOMHTMLScriptElement.mm in Sources */,
+                               CDF7483E18FEBCEC0006ECC0 /* GridResolvedPosition.cpp in Sources */,
                                85F32AF10AA63B8700FF3184 /* DOMHTMLSelectElement.mm in Sources */,
                                859A9C500AA5E3BD00B694B2 /* DOMHTMLStyleElement.mm in Sources */,
                                85DF821E0AA7849E00486AD7 /* DOMHTMLTableCaptionElement.mm in Sources */,
index b353822..5ad71fb 100644 (file)
@@ -55,13 +55,13 @@ static String stringForPosition(const NamedGridAreaMap& gridAreaMap, size_t row,
 
     for (const auto& it : gridAreaMap) {
         const GridCoordinate& coordinate = it.value;
-        if (row >= coordinate.rows.initialPositionIndex && row <= coordinate.rows.finalPositionIndex)
+        if (row >= coordinate.rows.resolvedInitialPosition.toInt() && row <= coordinate.rows.resolvedFinalPosition.toInt())
             candidates.append(it.key);
     }
 
     for (const auto& it : gridAreaMap) {
         const GridCoordinate& coordinate = it.value;
-        if (column >= coordinate.columns.initialPositionIndex && column <= coordinate.columns.finalPositionIndex && candidates.contains(it.key))
+        if (column >= coordinate.columns.resolvedInitialPosition.toInt() && column <= coordinate.columns.resolvedFinalPosition.toInt() && candidates.contains(it.key))
             return it.key;
     }
 
index 00e9b2f..3b5a385 100644 (file)
@@ -5352,18 +5352,18 @@ bool CSSParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, const u
 
             // The following checks test that the grid area is a single filled-in rectangle.
             // 1. The new row is adjacent to the previously parsed row.
-            if (rowCount != gridCoordinate.rows.finalPositionIndex + 1)
+            if (rowCount != gridCoordinate.rows.resolvedFinalPosition.next().toInt())
                 return 0;
 
             // 2. The new area starts at the same position as the previously parsed area.
-            if (currentColumn != gridCoordinate.columns.initialPositionIndex)
+            if (currentColumn != gridCoordinate.columns.resolvedInitialPosition.toInt())
                 return 0;
 
             // 3. The new area ends at the same position as the previously parsed area.
-            if (lookAheadColumn != gridCoordinate.columns.finalPositionIndex)
+            if (lookAheadColumn != gridCoordinate.columns.resolvedFinalPosition.toInt())
                 return 0;
 
-            ++gridCoordinate.rows.finalPositionIndex;
+            ++gridCoordinate.rows.resolvedFinalPosition;
         }
         currentColumn = lookAheadColumn;
     }
index cc2a707..5d53128 100644 (file)
@@ -1864,12 +1864,12 @@ static void createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap& nam
         GridSpan areaSpan = direction == ForRows ? area.value.rows : area.value.columns;
         {
             auto& startVector = namedGridLines.add(area.key + "-start", Vector<size_t>()).iterator->value;
-            startVector.append(areaSpan.initialPositionIndex);
+            startVector.append(areaSpan.resolvedInitialPosition.toInt());
             std::sort(startVector.begin(), startVector.end());
         }
         {
             auto& endVector = namedGridLines.add(area.key + "-end", Vector<size_t>()).iterator->value;
-            endVector.append(areaSpan.finalPositionIndex + 1);
+            endVector.append(areaSpan.resolvedFinalPosition.next().toInt());
             std::sort(endVector.begin(), endVector.end());
         }
     }
index 421e950..61cd26c 100644 (file)
@@ -30,6 +30,7 @@
 #if ENABLE(CSS_GRID_LAYOUT)
 
 #include "GridCoordinate.h"
+#include "GridResolvedPosition.h"
 #include "LayoutRepainter.h"
 #include "RenderLayer.h"
 #include "RenderView.h"
@@ -341,7 +342,7 @@ void RenderGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi
                 const GridSpan span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
 
                 // Do not include already processed items.
-                if (i > 0 && span.initialPositionIndex <= flexibleSizedTracksIndex[i - 1])
+                if (i > 0 && span.resolvedInitialPosition.toInt() <= flexibleSizedTracksIndex[i - 1])
                     continue;
 
                 double itemNormalizedFlexBreadth = computeNormalizedFractionBreadth(tracks, span, direction, maxContentForChild(gridItem, direction, sizingData.columnTracks));
@@ -400,12 +401,12 @@ double RenderGrid::computeNormalizedFractionBreadth(Vector<GridTrack>& tracks, c
     // |availableLogicalSpace| already accounts for the used breadths so no need to remove it here.
 
     Vector<GridTrackForNormalization> tracksForNormalization;
-    for (size_t i = tracksSpan.initialPositionIndex; i <= tracksSpan.finalPositionIndex; ++i) {
-        const GridTrackSize& trackSize = gridTrackSize(direction, i);
+    for (GridResolvedPosition position = tracksSpan.resolvedInitialPosition; position <= tracksSpan.resolvedFinalPosition; ++position) {
+        const GridTrackSize& trackSize = gridTrackSize(direction, position.toInt());
         if (!trackSize.maxTrackBreadth().isFlex())
             continue;
 
-        tracksForNormalization.append(GridTrackForNormalization(tracks[i], trackSize.maxTrackBreadth().flex()));
+        tracksForNormalization.append(GridTrackForNormalization(tracks[position.toInt()], trackSize.maxTrackBreadth().flex()));
     }
 
     // The function is not called if we don't have <flex> grid tracks
@@ -461,31 +462,6 @@ const GridTrackSize& RenderGrid::gridTrackSize(GridTrackSizingDirection directio
     return trackSize;
 }
 
-size_t RenderGrid::explicitGridColumnCount() const
-{
-    return style().gridColumns().size();
-}
-
-size_t RenderGrid::explicitGridRowCount() const
-{
-    return style().gridRows().size();
-}
-
-static inline bool isColumnSide(GridPositionSide side)
-{
-    return side == ColumnStartSide || side == ColumnEndSide;
-}
-
-static inline bool isStartSide(GridPositionSide side)
-{
-    return side == ColumnStartSide || side == RowStartSide;
-}
-
-size_t RenderGrid::explicitGridSizeForSide(GridPositionSide side) const
-{
-    return isColumnSide(side) ? explicitGridColumnCount() : explicitGridRowCount();
-}
-
 LayoutUnit RenderGrid::logicalContentHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
 {
     LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
@@ -555,16 +531,16 @@ void RenderGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirectio
 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
 {
     const GridCoordinate coordinate = cachedGridCoordinate(gridItem);
-    const size_t initialTrackIndex = (direction == ForColumns) ? coordinate.columns.initialPositionIndex : coordinate.rows.initialPositionIndex;
-    const size_t finalTrackIndex = (direction == ForColumns) ? coordinate.columns.finalPositionIndex : coordinate.rows.finalPositionIndex;
+    const GridResolvedPosition initialTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedInitialPosition : coordinate.rows.resolvedInitialPosition;
+    const GridResolvedPosition finalTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedFinalPosition : coordinate.rows.resolvedFinalPosition;
 
     sizingData.filteredTracks.shrink(0);
-    for (size_t trackIndex = initialTrackIndex; trackIndex <= finalTrackIndex; ++trackIndex) {
-        const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
+    for (GridResolvedPosition trackIndex = initialTrackPosition; trackIndex <= finalTrackPosition; ++trackIndex) {
+        const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex.toInt());
         if (!(trackSize.*filterFunction)())
             continue;
 
-        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex];
+        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex.toInt()] : sizingData.rowTracks[trackIndex.toInt()];
         sizingData.filteredTracks.append(&track);
     }
 
@@ -572,8 +548,8 @@ void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing
         return;
 
     LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, sizingData.columnTracks);
-    for (size_t trackIndexForSpace = initialTrackIndex; trackIndexForSpace <= finalTrackIndex; ++trackIndexForSpace) {
-        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndexForSpace] : sizingData.rowTracks[trackIndexForSpace];
+    for (GridResolvedPosition trackPositionForSpace = initialTrackPosition; trackPositionForSpace <= finalTrackPosition; ++trackPositionForSpace) {
+        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackPositionForSpace.toInt()] : sizingData.rowTracks[trackPositionForSpace.toInt()];
         additionalBreadthSpace -= (track.*trackGetter)();
     }
 
@@ -647,17 +623,17 @@ void RenderGrid::growGrid(GridTrackSizingDirection direction)
 
 void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
 {
-    for (size_t row = coordinate.rows.initialPositionIndex; row <= coordinate.rows.finalPositionIndex; ++row) {
-        for (size_t column = coordinate.columns.initialPositionIndex; column <= coordinate.columns.finalPositionIndex; ++column)
-            m_grid[row][column].append(child);
+    for (GridResolvedPosition row = coordinate.rows.resolvedInitialPosition; row <= coordinate.rows.resolvedFinalPosition; ++row) {
+        for (GridResolvedPosition column = coordinate.columns.resolvedInitialPosition; column <= coordinate.columns.resolvedFinalPosition; ++column)
+            m_grid[row.toInt()][column.toInt()].append(child);
     }
     m_gridItemCoordinate.set(child, coordinate);
 }
 
-void RenderGrid::insertItemIntoGrid(RenderBox* child, size_t rowTrack, size_t columnTrack)
+void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridResolvedPosition& rowTrack, const GridResolvedPosition& columnTrack)
 {
-    const GridSpan& rowSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForRows, rowTrack);
-    const GridSpan& columnSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForColumns, columnTrack);
+    const GridSpan& rowSpan = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*child, ForRows, rowTrack);
+    const GridSpan& columnSpan = GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(*child, ForColumns, columnTrack);
     insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
 }
 
@@ -674,8 +650,8 @@ void RenderGrid::placeItemsOnGrid()
     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
         // FIXME: We never re-resolve positions if the grid is grown during auto-placement which may lead auto / <integer>
         // positions to not match the author's intent. The specification is unclear on what should be done in this case.
-        std::unique_ptr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
-        std::unique_ptr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
+        std::unique_ptr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *child, ForRows);
+        std::unique_ptr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *child, ForColumns);
         if (!rowPositions || !columnPositions) {
             GridSpan* majorAxisPositions = (autoPlacementMajorAxisDirection() == ForColumns) ? columnPositions.get() : rowPositions.get();
             if (!majorAxisPositions)
@@ -704,22 +680,22 @@ void RenderGrid::placeItemsOnGrid()
 void RenderGrid::populateExplicitGridAndOrderIterator()
 {
     OrderIteratorPopulator populator(m_orderIterator);
-    size_t maximumRowIndex = std::max<size_t>(1, explicitGridRowCount());
-    size_t maximumColumnIndex = std::max<size_t>(1, explicitGridColumnCount());
+    size_t maximumRowIndex = std::max<size_t>(1, style().gridRows().size());
+    size_t maximumColumnIndex = std::max<size_t>(1, style().gridColumns().size());
 
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
         populator.collectChild(*child);
 
         // This function bypasses the cache (cachedGridCoordinate()) as it is used to build it.
-        std::unique_ptr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
-        std::unique_ptr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
+        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.
         if (rowPositions)
-            maximumRowIndex = std::max(maximumRowIndex, rowPositions->finalPositionIndex + 1);
+            maximumRowIndex = std::max(maximumRowIndex, rowPositions->resolvedFinalPosition.next().toInt());
         if (columnPositions)
-            maximumColumnIndex = std::max(maximumColumnIndex, columnPositions->finalPositionIndex + 1);
+            maximumColumnIndex = std::max(maximumColumnIndex, columnPositions->resolvedFinalPosition.next().toInt());
     }
 
     m_grid.grow(maximumRowIndex);
@@ -730,17 +706,17 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGridItems)
 {
     for (auto& autoGridItem : autoGridItems) {
-        std::unique_ptr<GridSpan> majorAxisPositions = resolveGridPositionsFromStyle(autoGridItem, autoPlacementMajorAxisDirection());
-        GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->initialPositionIndex);
+        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.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+            insertItemIntoGrid(autoGridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
             continue;
         }
 
         growGrid(autoPlacementMinorAxisDirection());
         std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
         ASSERT(emptyGridArea);
-        insertItemIntoGrid(autoGridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+        insertItemIntoGrid(autoGridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
     }
 }
 
@@ -752,14 +728,14 @@ void RenderGrid::placeAutoMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGri
 
 void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
 {
-    std::unique_ptr<GridSpan> minorAxisPositions = resolveGridPositionsFromStyle(gridItem, autoPlacementMinorAxisDirection());
-    ASSERT(!resolveGridPositionsFromStyle(gridItem, autoPlacementMajorAxisDirection()));
+    std::unique_ptr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPositionsFromStyle(style(), *gridItem, autoPlacementMinorAxisDirection());
+    ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(style(), *gridItem, autoPlacementMajorAxisDirection()));
     size_t minorAxisIndex = 0;
     if (minorAxisPositions) {
-        minorAxisIndex = minorAxisPositions->initialPositionIndex;
+        minorAxisIndex = minorAxisPositions->resolvedInitialPosition.toInt();
         GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisIndex);
         if (std::unique_ptr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
-            insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+            insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
             return;
         }
     } else {
@@ -767,7 +743,7 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
         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.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+                insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosition, emptyGridArea->columns.resolvedInitialPosition);
                 return;
             }
         }
@@ -780,14 +756,14 @@ void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
     insertItemIntoGrid(gridItem, rowIndex, columnIndex);
 }
 
-RenderGrid::GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
+GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
 {
     GridAutoFlow flow = style().gridAutoFlow();
     ASSERT(flow != AutoFlowNone);
     return (flow == AutoFlowColumn) ? ForColumns : ForRows;
 }
 
-RenderGrid::GridTrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
+GridTrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
 {
     GridAutoFlow flow = style().gridAutoFlow();
     ASSERT(flow != AutoFlowNone);
@@ -856,256 +832,13 @@ GridCoordinate RenderGrid::cachedGridCoordinate(const RenderBox* gridItem) const
     return m_gridItemCoordinate.get(gridItem);
 }
 
-GridSpan RenderGrid::resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, GridTrackSizingDirection, size_t initialPosition) const
-{
-    // 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);
-}
-
-static inline const NamedGridLinesMap& gridLinesForSide(const RenderStyle& style, GridPositionSide side)
-{
-    return isColumnSide(side) ? style.namedGridColumnLines() : style.namedGridRowLines();
-}
-
-static inline const String implicitNamedGridLineForSide(const String& lineName, GridPositionSide side)
-{
-    return lineName + (isStartSide(side) ? "-start" : "-end");
-}
-
-static bool isNonExistentNamedLineOrArea(const String& lineName, const RenderStyle& style, GridPositionSide side)
-{
-    const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side);
-    return !gridLineNames.contains(implicitNamedGridLineForSide(lineName, side)) && !gridLineNames.contains(lineName);
-}
-
-void RenderGrid::adjustGridPositionsFromStyle(GridPosition& initialPosition, GridPosition& finalPosition, GridPositionSide initialPositionSide, GridPositionSide finalPositionSide) const
-{
-    ASSERT(isColumnSide(initialPositionSide) == isColumnSide(finalPositionSide));
-
-    // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to
-    // overwrite the specified values.
-    if (initialPosition.isSpan() && finalPosition.isSpan())
-        finalPosition.setAutoPosition();
-
-    // Try to early detect the case of non existing named grid lines. This way we could assume later that
-    // RenderGrid::resolveGrisPositionFromStyle() won't require the autoplacement to run, i.e., it'll always return a
-    // valid resolved position.
-    if (initialPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(initialPosition.namedGridLine(), style(), initialPositionSide))
-        initialPosition.setAutoPosition();
-
-    if (finalPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(finalPosition.namedGridLine(), style(), finalPositionSide))
-        finalPosition.setAutoPosition();
-}
-
-std::unique_ptr<GridSpan> RenderGrid::resolveGridPositionsFromStyle(const RenderBox* gridItem, GridTrackSizingDirection direction) const
-{
-    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(initialPosition, finalPosition, initialPositionSide, finalPositionSide);
-
-    if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
-        if (style().gridAutoFlow() == AutoFlowNone)
-            return std::make_unique<GridSpan>(0, 0);
-
-        // We can't get our grid positions without running the auto placement algorithm.
-        return nullptr;
-    }
-
-    if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
-        // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
-        const size_t finalResolvedPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
-        return resolveGridPositionAgainstOppositePosition(finalResolvedPosition, initialPosition, initialPositionSide);
-    }
-
-    if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
-        // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
-        const size_t initialResolvedPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
-        return resolveGridPositionAgainstOppositePosition(initialResolvedPosition, finalPosition, finalPositionSide);
-    }
-
-    size_t resolvedInitialPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
-    size_t resolvedFinalPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
-
-    // If 'grid-row-end' specifies a line at or before that specified by 'grid-row-start', it computes to 'span 1'.
-    if (resolvedFinalPosition < resolvedInitialPosition)
-        resolvedFinalPosition = resolvedInitialPosition;
-
-    return std::make_unique<GridSpan>(resolvedInitialPosition, resolvedFinalPosition);
-}
-
-size_t RenderGrid::resolveNamedGridLinePositionFromStyle(const GridPosition& position, GridPositionSide side) const
-{
-    ASSERT(!position.namedGridLine().isNull());
-
-    const NamedGridLinesMap& gridLinesNames = gridLinesForSide(style(), side);
-    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
-    if (it == gridLinesNames.end()) {
-        if (position.isPositive())
-            return 0;
-        const size_t lastLine = explicitGridSizeForSide(side);
-        return GridPosition::adjustGridPositionForSide(lastLine, side);
-    }
-
-    size_t namedGridLineIndex;
-    if (position.isPositive())
-        namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
-    else
-        namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
-    return GridPosition::adjustGridPositionForSide(it->value[namedGridLineIndex], side);
-}
-
-size_t RenderGrid::resolveGridPositionFromStyle(const GridPosition& position, GridPositionSide side) const
-{
-    switch (position.type()) {
-    case ExplicitPosition: {
-        ASSERT(position.integerPosition());
-
-        if (!position.namedGridLine().isNull())
-            return resolveNamedGridLinePositionFromStyle(position, side);
-
-        // Handle <integer> explicit position.
-        if (position.isPositive())
-            return GridPosition::adjustGridPositionForSide(position.integerPosition() - 1, side);
-
-        size_t resolvedPosition = abs(position.integerPosition()) - 1;
-        const size_t endOfTrack = explicitGridSizeForSide(side);
-
-        // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
-        if (endOfTrack < resolvedPosition)
-            return 0;
-
-        return GridPosition::adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
-    }
-    case NamedGridAreaPosition:
-    {
-        // First attempt to match the grid area's edge to a named grid area: if there is a named line with the name
-        // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such
-        // line to the grid item's placement.
-        String namedGridLine = position.namedGridLine();
-        ASSERT(!isNonExistentNamedLineOrArea(namedGridLine, style(), side));
-
-        const NamedGridLinesMap& gridLineNames = gridLinesForSide(style(), side);
-        auto implicitLine = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side));
-        if (implicitLine != gridLineNames.end())
-            return GridPosition::adjustGridPositionForSide(implicitLine->value[0], side);
-
-        // Otherwise, if there is a named line with the specified name, contributes the first such line to the grid
-        // item's placement.
-        auto explicitLine = gridLineNames.find(namedGridLine);
-        if (explicitLine != gridLineNames.end())
-            return GridPosition::adjustGridPositionForSide(explicitLine->value[0], side);
-
-        // If none of the above works specs mandate us to treat it as auto BUT we should have detected it before calling
-        // this function in resolveGridPositionsFromStyle(). We should be covered anyway by the ASSERT at the beginning
-        // of this case block.
-        ASSERT_NOT_REACHED();
-        return 0;
-    }
-    case AutoPosition:
-    case SpanPosition:
-        // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
-        ASSERT_NOT_REACHED();
-        return 0;
-    }
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-std::unique_ptr<GridSpan> RenderGrid::resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
-{
-    if (position.isAuto())
-        return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition);
-
-    ASSERT(position.isSpan());
-    ASSERT(position.spanPosition() > 0);
-
-    if (!position.namedGridLine().isNull()) {
-        // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
-        return resolveNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, side);
-    }
-
-    // 'span 1' is contained inside a single grid track regardless of the direction.
-    // That's why the CSS span value is one more than the offset we apply.
-    size_t positionOffset = position.spanPosition() - 1;
-    if (isStartSide(side)) {
-        size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition - positionOffset);
-        return std::make_unique<GridSpan>(initialResolvedPosition, resolvedOppositePosition);
-    }
-
-    return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition + positionOffset);
-}
-
-std::unique_ptr<GridSpan> RenderGrid::resolveNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
-{
-    ASSERT(position.isSpan());
-    ASSERT(!position.namedGridLine().isNull());
-    // Negative positions are not allowed per the specification and should have been handled during parsing.
-    ASSERT(position.spanPosition() > 0);
-
-    const NamedGridLinesMap& gridLinesNames = gridLinesForSide(style(), side);
-    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
-
-    // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
-    // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
-    if (it == gridLinesNames.end())
-        return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition);
-
-    if (isStartSide(side))
-        return resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
-
-    return resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
-}
-
-static inline size_t firstNamedGridLineBeforePosition(size_t position, const Vector<size_t>& gridLines)
-{
-    // The grid line inequality needs to be strict (which doesn't match the after / end case) because |position| is
-    // already converted to an index in our grid representation (ie one was removed from the grid line to account for
-    // the side).
-    size_t firstLineBeforePositionIndex = 0;
-    const size_t* firstLineBeforePosition = std::lower_bound(gridLines.begin(), gridLines.end(), position);
-    if (firstLineBeforePosition != gridLines.end()) {
-        if (*firstLineBeforePosition > position && firstLineBeforePosition != gridLines.begin())
-            --firstLineBeforePosition;
-
-        firstLineBeforePositionIndex = firstLineBeforePosition - gridLines.begin();
-    }
-    return firstLineBeforePositionIndex;
-}
-
-std::unique_ptr<GridSpan> RenderGrid::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) const
-{
-    size_t gridLineIndex = std::max<int>(0, firstNamedGridLineBeforePosition(resolvedOppositePosition, gridLines) - position.spanPosition() + 1);
-    size_t resolvedGridLinePosition = gridLines[gridLineIndex];
-    if (resolvedGridLinePosition > resolvedOppositePosition)
-        resolvedGridLinePosition = resolvedOppositePosition;
-    return std::make_unique<GridSpan>(resolvedGridLinePosition, resolvedOppositePosition);
-}
-
-std::unique_ptr<GridSpan> RenderGrid::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) const
-{
-    size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1;
-    const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition);
-    if (firstLineAfterOppositePosition != gridLines.end())
-        firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - gridLines.begin();
-
-    size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
-    size_t resolvedGridLinePosition = GridPosition::adjustGridPositionForRowEndColumnEndSide(gridLines[gridLineIndex]);
-    if (resolvedGridLinePosition < resolvedOppositePosition)
-        resolvedGridLinePosition = resolvedOppositePosition;
-    return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedGridLinePosition);
-}
-
 LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox* child, GridTrackSizingDirection direction, const Vector<GridTrack>& tracks) const
 {
     const GridCoordinate& coordinate = cachedGridCoordinate(child);
     const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
     LayoutUnit gridAreaBreadth = 0;
-    for (size_t trackIndex = span.initialPositionIndex; trackIndex <= span.finalPositionIndex; ++trackIndex)
-        gridAreaBreadth += tracks[trackIndex].m_usedBreadth;
+    for (GridResolvedPosition trackPosition = span.resolvedInitialPosition; trackPosition <= span.resolvedFinalPosition; ++trackPosition)
+        gridAreaBreadth += tracks[trackPosition.toInt()].m_usedBreadth;
     return gridAreaBreadth;
 }
 
@@ -1125,11 +858,11 @@ void RenderGrid::populateGridPositions(const GridSizingData& sizingData)
 LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const GridSizingData& sizingData)
 {
     const GridCoordinate& coordinate = cachedGridCoordinate(child);
-    ASSERT_UNUSED(sizingData, coordinate.columns.initialPositionIndex < sizingData.columnTracks.size());
-    ASSERT_UNUSED(sizingData, coordinate.rows.initialPositionIndex < sizingData.rowTracks.size());
+    ASSERT_UNUSED(sizingData, coordinate.columns.resolvedInitialPosition.toInt() < sizingData.columnTracks.size());
+    ASSERT_UNUSED(sizingData, coordinate.rows.resolvedInitialPosition.toInt() < sizingData.rowTracks.size());
 
     // The grid items should be inside the grid container's border box, that's why they need to be shifted.
-    return LayoutPoint(m_columnPositions[coordinate.columns.initialPositionIndex] + marginStartForChild(*child), m_rowPositions[coordinate.rows.initialPositionIndex] + marginBeforeForChild(*child));
+    return LayoutPoint(m_columnPositions[coordinate.columns.resolvedInitialPosition.toInt()] + marginStartForChild(*child), m_rowPositions[coordinate.rows.resolvedInitialPosition.toInt()] + marginBeforeForChild(*child));
 }
 
 void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect)
index 8184ecf..3b3b6eb 100644 (file)
@@ -29,6 +29,7 @@
 
 #if ENABLE(CSS_GRID_LAYOUT)
 
+#include "GridResolvedPosition.h"
 #include "OrderIterator.h"
 #include "RenderBlock.h"
 
@@ -38,11 +39,6 @@ class GridCoordinate;
 class GridSpan;
 class GridTrack;
 
-enum GridTrackSizingDirection {
-    ForColumns,
-    ForRows
-};
-
 class RenderGrid final : public RenderBlock {
 public:
     RenderGrid(Element&, PassRef<RenderStyle>);
@@ -66,7 +62,6 @@ private:
 
     class GridIterator;
     class GridSizingData;
-    enum GridTrackSizingDirection { ForColumns, ForRows };
     void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&);
     void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& availableLogicalSpace);
     bool gridElementIsShrinkToFit();
@@ -76,7 +71,7 @@ private:
     void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&);
 
     void growGrid(GridTrackSizingDirection);
-    void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack);
+    void insertItemIntoGrid(RenderBox*, const GridResolvedPosition& rowTrack, const GridResolvedPosition& columnTrack);
     void insertItemIntoGrid(RenderBox*, const GridCoordinate&);
     void placeItemsOnGrid();
     void populateExplicitGridAndOrderIterator();
@@ -100,9 +95,6 @@ private:
     double computeNormalizedFractionBreadth(Vector<GridTrack>&, const GridSpan& tracksSpan, GridTrackSizingDirection, LayoutUnit availableLogicalSpace) const;
 
     const GridTrackSize& gridTrackSize(GridTrackSizingDirection, size_t) const;
-    size_t explicitGridColumnCount() const;
-    size_t explicitGridRowCount() const;
-    size_t explicitGridSizeForSide(GridPositionSide) const;
 
     LayoutUnit logicalContentHeightForChild(RenderBox*, Vector<GridTrack>&);
     LayoutUnit minContentForChild(RenderBox*, GridTrackSizingDirection, Vector<GridTrack>& columnTracks);
@@ -110,17 +102,6 @@ private:
     LayoutPoint findChildLogicalPosition(RenderBox*, const GridSizingData&);
     GridCoordinate cachedGridCoordinate(const RenderBox*) const;
 
-    GridSpan resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, GridTrackSizingDirection, size_t) const;
-    void adjustNamedGridItemPosition(GridPosition&, GridPositionSide) const;
-    void adjustGridPositionsFromStyle(GridPosition& initialPosition, GridPosition& finalPosition, GridPositionSide initialPositionSide, GridPositionSide finalPositionSide) const;
-    std::unique_ptr<GridSpan> resolveGridPositionsFromStyle(const RenderBox*, GridTrackSizingDirection) const;
-    size_t resolveNamedGridLinePositionFromStyle(const GridPosition&, GridPositionSide) const;
-    size_t resolveGridPositionFromStyle(const GridPosition&, GridPositionSide) const;
-    std::unique_ptr<GridSpan> resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, GridPositionSide) const;
-    std::unique_ptr<GridSpan> resolveNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, GridPositionSide) const;
-    std::unique_ptr<GridSpan> resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, const Vector<size_t>&) const;
-    std::unique_ptr<GridSpan> resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, const Vector<size_t>&) const;
-
     LayoutUnit gridAreaBreadthForChild(const RenderBox* child, GridTrackSizingDirection, const Vector<GridTrack>&) const;
 
     virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect) override final;
index 44d200b..908f367 100644 (file)
 
 #if ENABLE(CSS_GRID_LAYOUT)
 
+#include "GridResolvedPosition.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
-// A span in a single direction (either rows or columns). Note that |initialPositionIndex|
-// and |finalPositionIndex| are grid areas' indexes, NOT grid lines'. Iterating over the
-// span should include both |initialPositionIndex| and |finalPositionIndex| to be correct.
+// A span in a single direction (either rows or columns). Note that |resolvedInitialPosition|
+// and |resolvedFinalPosition| are grid areas' indexes, NOT grid lines'. Iterating over the
+// span should include both |resolvedInitialPosition| and |resolvedFinalPosition| to be correct.
 class GridSpan {
 public:
-    GridSpan(size_t initialPosition, size_t finalPosition)
-        : initialPositionIndex(initialPosition)
-        , finalPositionIndex(finalPosition)
+    GridSpan(const GridResolvedPosition& resolvedInitialPosition, const GridResolvedPosition& resolvedFinalPosition)
+        : resolvedInitialPosition(resolvedInitialPosition)
+        , resolvedFinalPosition(resolvedFinalPosition)
     {
-        ASSERT(initialPositionIndex <= finalPositionIndex);
+        ASSERT(resolvedInitialPosition <= resolvedFinalPosition);
     }
 
     bool operator==(const GridSpan& o) const
     {
-        return initialPositionIndex == o.initialPositionIndex && finalPositionIndex == o.finalPositionIndex;
+        return resolvedInitialPosition == o.resolvedInitialPosition && resolvedFinalPosition == o.resolvedFinalPosition;
     }
 
-    size_t initialPositionIndex;
-    size_t finalPositionIndex;
+    GridResolvedPosition resolvedInitialPosition;
+    GridResolvedPosition resolvedFinalPosition;
 };
 
 // This represents a grid area that spans in both rows' and columns' direction.
index 68f2f39..5a0af9e 100644 (file)
@@ -45,13 +45,6 @@ enum GridPositionType {
     NamedGridAreaPosition // <ident>
 };
 
-enum GridPositionSide {
-    ColumnStartSide,
-    ColumnEndSide,
-    RowStartSide,
-    RowEndSide
-};
-
 class GridPosition {
 public:
     GridPosition()
@@ -60,20 +53,6 @@ public:
     {
     }
 
-    static inline size_t adjustGridPositionForRowEndColumnEndSide(size_t resolvedPosition)
-    {
-        return resolvedPosition ? resolvedPosition - 1 : 0;
-    }
-
-    static size_t adjustGridPositionForSide(size_t resolvedPosition, GridPositionSide side)
-    {
-        // An item finishing on the N-th line belongs to the N-1-th cell.
-        if (side == ColumnEndSide || side == RowEndSide)
-            return adjustGridPositionForRowEndColumnEndSide(resolvedPosition);
-
-        return resolvedPosition;
-    }
-
     bool isPositive() const { return integerPosition() > 0; }
 
     GridPositionType type() const { return m_type; }
diff --git a/Source/WebCore/rendering/style/GridResolvedPosition.cpp b/Source/WebCore/rendering/style/GridResolvedPosition.cpp
new file mode 100644 (file)
index 0000000..7fb36cb
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GridResolvedPosition.h"
+
+#if ENABLE(CSS_GRID_LAYOUT)
+
+#include "GridCoordinate.h"
+#include "RenderBox.h"
+
+namespace WebCore {
+
+static inline bool isColumnSide(GridPositionSide side)
+{
+    return side == ColumnStartSide || side == ColumnEndSide;
+}
+
+static inline bool isStartSide(GridPositionSide side)
+{
+    return side == ColumnStartSide || side == RowStartSide;
+}
+
+static size_t explicitGridSizeForSide(const RenderStyle& gridContainerStyle, GridPositionSide side)
+{
+    return isColumnSide(side) ? gridContainerStyle.gridColumns().size() : gridContainerStyle.gridRows().size();
+}
+
+GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(const RenderBox&, GridTrackSizingDirection, const GridResolvedPosition& initialPosition)
+{
+    // 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);
+}
+
+static inline const NamedGridLinesMap& gridLinesForSide(const RenderStyle& style, GridPositionSide side)
+{
+    return isColumnSide(side) ? style.namedGridColumnLines() : style.namedGridRowLines();
+}
+
+static inline const String implicitNamedGridLineForSide(const String& lineName, GridPositionSide side)
+{
+    return lineName + (isStartSide(side) ? "-start" : "-end");
+}
+
+static bool isNonExistentNamedLineOrArea(const String& lineName, const RenderStyle& style, GridPositionSide side)
+{
+    const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side);
+    return !gridLineNames.contains(implicitNamedGridLineForSide(lineName, side)) && !gridLineNames.contains(lineName);
+}
+
+void GridResolvedPosition::adjustGridPositionsFromStyle(const RenderStyle& gridContainerStyle, GridPosition& initialPosition, GridPosition& finalPosition, GridPositionSide initialPositionSide, GridPositionSide finalPositionSide)
+{
+    ASSERT(isColumnSide(initialPositionSide) == isColumnSide(finalPositionSide));
+
+    // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to
+    // overwrite the specified values.
+    if (initialPosition.isSpan() && finalPosition.isSpan())
+        finalPosition.setAutoPosition();
+
+    // Try to early detect the case of non existing named grid lines. This way we could assume later that
+    // GridResolvedPosition::resolveGrisPositionFromStyle() won't require the autoplacement to run, i.e., it'll always return a
+    // valid resolved position.
+    if (initialPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, initialPositionSide))
+        initialPosition.setAutoPosition();
+
+    if (finalPosition.isNamedGridArea() && isNonExistentNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide))
+        finalPosition.setAutoPosition();
+}
+
+std::unique_ptr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction)
+{
+    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);
+
+    if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
+        if (gridContainerStyle.gridAutoFlow() == AutoFlowNone)
+            return std::make_unique<GridSpan>(0, 0);
+
+        // We can't get our grid positions without running the auto placement algorithm.
+        return nullptr;
+    }
+
+    if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
+        // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
+        const GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide);
+        return resolveGridPositionAgainstOppositePosition(gridContainerStyle, finalResolvedPosition, initialPosition, initialPositionSide);
+    }
+
+    if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
+        // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
+        const GridResolvedPosition initialResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide);
+        return resolveGridPositionAgainstOppositePosition(gridContainerStyle, initialResolvedPosition, finalPosition, finalPositionSide);
+    }
+
+    GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide);
+    GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide);
+
+    // If 'grid-row-end' specifies a line at or before that specified by 'grid-row-start', it computes to 'span 1'.
+    if (resolvedFinalPosition < resolvedInitialPosition)
+        resolvedFinalPosition = resolvedInitialPosition;
+
+    return std::make_unique<GridSpan>(resolvedInitialPosition, resolvedFinalPosition);
+}
+
+GridResolvedPosition GridResolvedPosition::resolveNamedGridLinePositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
+{
+    ASSERT(!position.namedGridLine().isNull());
+
+    const NamedGridLinesMap& gridLinesNames = isColumnSide(side) ? gridContainerStyle.namedGridColumnLines() : gridContainerStyle.namedGridRowLines();
+    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
+    if (it == gridLinesNames.end()) {
+        if (position.isPositive())
+            return 0;
+        const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side);
+        return GridResolvedPosition::adjustGridPositionForSide(lastLine, side);
+    }
+
+    size_t namedGridLineIndex;
+    if (position.isPositive())
+        namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
+    else
+        namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
+    return GridResolvedPosition::adjustGridPositionForSide(it->value[namedGridLineIndex], side);
+}
+
+GridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
+{
+    switch (position.type()) {
+    case ExplicitPosition: {
+        ASSERT(position.integerPosition());
+
+        if (!position.namedGridLine().isNull())
+            return resolveNamedGridLinePositionFromStyle(gridContainerStyle, position, side);
+
+        // Handle <integer> explicit position.
+        if (position.isPositive())
+            return GridResolvedPosition::adjustGridPositionForSide(position.integerPosition() - 1, side);
+
+        size_t resolvedPosition = abs(position.integerPosition()) - 1;
+        const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, side);
+
+        // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
+        if (endOfTrack < resolvedPosition)
+            return 0;
+
+        return GridResolvedPosition::adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
+    }
+    case NamedGridAreaPosition:
+    {
+        // First attempt to match the grid area's edge to a named grid area: if there is a named line with the name
+        // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such
+        // line to the grid item's placement.
+        String namedGridLine = position.namedGridLine();
+        ASSERT(!isNonExistentNamedLineOrArea(namedGridLine, gridContainerStyle, side));
+
+        const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerStyle, side);
+        auto implicitLine = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side));
+        if (implicitLine != gridLineNames.end())
+            return GridResolvedPosition::adjustGridPositionForSide(implicitLine->value[0], side);
+
+        // Otherwise, if there is a named line with the specified name, contributes the first such line to the grid
+        // item's placement.
+        auto explicitLine = gridLineNames.find(namedGridLine);
+        if (explicitLine != gridLineNames.end())
+            return GridResolvedPosition::adjustGridPositionForSide(explicitLine->value[0], side);
+
+        // If none of the above works specs mandate us to treat it as auto BUT we should have detected it before calling
+        // this function in resolveGridPositionsFromStyle(). We should be covered anyway by the ASSERT at the beginning
+        // of this case block.
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    case AutoPosition:
+    case SpanPosition:
+        // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
+        ASSERT_NOT_REACHED();
+        return GridResolvedPosition(0);
+    }
+    ASSERT_NOT_REACHED();
+    return GridResolvedPosition(0);
+}
+
+std::unique_ptr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
+{
+    if (position.isAuto())
+        return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition);
+
+    ASSERT(position.isSpan());
+    ASSERT(position.spanPosition() > 0);
+
+    if (!position.namedGridLine().isNull()) {
+        // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
+        return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, resolvedOppositePosition, position, side);
+    }
+
+    // 'span 1' is contained inside a single grid track regardless of the direction.
+    // That's why the CSS span value is one more than the offset we apply.
+    size_t positionOffset = position.spanPosition() - 1;
+    if (isStartSide(side)) {
+        size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition.toInt() - positionOffset);
+        return std::make_unique<GridSpan>(initialResolvedPosition, resolvedOppositePosition);
+    }
+
+    return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition.toInt() + positionOffset);
+}
+
+std::unique_ptr<GridSpan> GridResolvedPosition::resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
+{
+    ASSERT(position.isSpan());
+    ASSERT(!position.namedGridLine().isNull());
+    // Negative positions are not allowed per the specification and should have been handled during parsing.
+    ASSERT(position.spanPosition() > 0);
+
+    const NamedGridLinesMap& gridLinesNames = isColumnSide(side) ? gridContainerStyle.namedGridColumnLines() : gridContainerStyle.namedGridRowLines();
+    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
+
+    // If there is no named grid line of that name, we resolve the position to 'auto' (which is equivalent to 'span 1' in this case).
+    // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
+    if (it == gridLinesNames.end())
+        return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedOppositePosition);
+
+    if (side == RowStartSide || side == ColumnStartSide)
+        return resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
+
+    return resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(resolvedOppositePosition, position, it->value);
+}
+
+static inline size_t firstNamedGridLineBeforePosition(size_t position, const Vector<size_t>& gridLines)
+{
+    // The grid line inequality needs to be strict (which doesn't match the after / end case) because |position| is
+    // already converted to an index in our grid representation (ie one was removed from the grid line to account for
+    // the side).
+    size_t firstLineBeforePositionIndex = 0;
+    const size_t* firstLineBeforePosition = std::lower_bound(gridLines.begin(), gridLines.end(), position);
+    if (firstLineBeforePosition != gridLines.end()) {
+        if (*firstLineBeforePosition > position && firstLineBeforePosition != gridLines.begin())
+            --firstLineBeforePosition;
+
+        firstLineBeforePositionIndex = firstLineBeforePosition - gridLines.begin();
+    }
+    return firstLineBeforePositionIndex;
+}
+
+std::unique_ptr<GridSpan> GridResolvedPosition::resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
+{
+    size_t gridLineIndex = std::max<int>(0, firstNamedGridLineBeforePosition(resolvedOppositePosition.toInt(), gridLines) - position.spanPosition() + 1);
+    GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition(gridLines[gridLineIndex]);
+    if (resolvedGridLinePosition > resolvedOppositePosition)
+        resolvedGridLinePosition = resolvedOppositePosition;
+    return std::make_unique<GridSpan>(resolvedGridLinePosition, resolvedOppositePosition);
+}
+
+std::unique_ptr<GridSpan> GridResolvedPosition::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
+{
+    size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1;
+    const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition);
+    if (firstLineAfterOppositePosition != gridLines.end())
+        firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - gridLines.begin();
+
+    size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
+    GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition::adjustGridPositionForRowEndColumnEndSide(gridLines[gridLineIndex]);
+    if (resolvedGridLinePosition < resolvedOppositePosition)
+        resolvedGridLinePosition = resolvedOppositePosition;
+    return std::make_unique<GridSpan>(resolvedOppositePosition, resolvedGridLinePosition);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_GRID_LAYOUT)
diff --git a/Source/WebCore/rendering/style/GridResolvedPosition.h b/Source/WebCore/rendering/style/GridResolvedPosition.h
new file mode 100644 (file)
index 0000000..9016741
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GridResolvedPosition_h
+#define GridResolvedPosition_h
+
+#if ENABLE(CSS_GRID_LAYOUT)
+
+#include "GridPosition.h"
+
+namespace WebCore {
+
+class GridSpan;
+class RenderBox;
+class RenderStyle;
+
+enum GridPositionSide {
+    ColumnStartSide,
+    ColumnEndSide,
+    RowStartSide,
+    RowEndSide
+};
+
+enum GridTrackSizingDirection {
+    ForColumns,
+    ForRows
+};
+
+// This class represents an index into one of the dimensions of the grid array.
+// Wraps a size_t integer just for the purpose of knowing what we manipulate in the grid code.
+class GridResolvedPosition {
+public:
+    static GridResolvedPosition adjustGridPositionForRowEndColumnEndSide(size_t resolvedPosition)
+    {
+        return resolvedPosition ? GridResolvedPosition(resolvedPosition - 1) : GridResolvedPosition(0);
+    }
+
+    static GridResolvedPosition adjustGridPositionForSide(size_t resolvedPosition, GridPositionSide side)
+    {
+        // An item finishing on the N-th line belongs to the N-1-th cell.
+        if (side == ColumnEndSide || side == RowEndSide)
+            return adjustGridPositionForRowEndColumnEndSide(resolvedPosition);
+
+        return GridResolvedPosition(resolvedPosition);
+    }
+
+    static GridSpan resolveGridPositionsFromAutoPlacementPosition(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);
+    static GridResolvedPosition resolveNamedGridLinePositionFromStyle(const RenderStyle&, const GridPosition&, GridPositionSide);
+    static GridResolvedPosition resolveGridPositionFromStyle(const RenderStyle&, const GridPosition&, GridPositionSide);
+    static std::unique_ptr<GridSpan> resolveGridPositionAgainstOppositePosition(const RenderStyle&, const GridResolvedPosition&, const GridPosition&, GridPositionSide);
+    static std::unique_ptr<GridSpan> resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle&, const GridResolvedPosition&, const GridPosition&, GridPositionSide);
+    static std::unique_ptr<GridSpan> resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePosition(const GridResolvedPosition&, const GridPosition&, const Vector<size_t>&);
+    static std::unique_ptr<GridSpan> resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(const GridResolvedPosition&, const GridPosition&, const Vector<size_t>&);
+
+    GridResolvedPosition(size_t position)
+        : m_integerPosition(position)
+    {
+    }
+
+    GridResolvedPosition(const GridPosition& position, GridPositionSide side)
+    {
+        ASSERT(position.integerPosition());
+        size_t integerPosition = position.integerPosition() - 1;
+
+        m_integerPosition = adjustGridPositionForSide(integerPosition, side).m_integerPosition;
+    }
+
+    GridResolvedPosition& operator++()
+    {
+        m_integerPosition++;
+        return *this;
+    }
+
+    bool operator==(const GridResolvedPosition& other) const
+    {
+        return m_integerPosition == other.m_integerPosition;
+    }
+
+    bool operator<(const GridResolvedPosition& other) const
+    {
+        return m_integerPosition < other.m_integerPosition;
+    }
+
+    bool operator>(const GridResolvedPosition& other) const
+    {
+        return m_integerPosition > other.m_integerPosition;
+    }
+
+    bool operator<=(const GridResolvedPosition& other) const
+    {
+        return m_integerPosition <= other.m_integerPosition;
+    }
+
+    bool operator>=(const GridResolvedPosition& other) const
+    {
+        return m_integerPosition >= other.m_integerPosition;
+    }
+
+    size_t toInt() const
+    {
+        return m_integerPosition;
+    }
+
+    GridResolvedPosition next() const
+    {
+        return GridResolvedPosition(m_integerPosition + 1);
+    }
+
+private:
+
+    size_t m_integerPosition;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_GRID_LAYOUT)
+
+#endif // GridResolvedPosition_h