Index: third_party/WebKit/Source/core/style/GridResolvedPosition.cpp |
diff --git a/third_party/WebKit/Source/core/style/GridResolvedPosition.cpp b/third_party/WebKit/Source/core/style/GridResolvedPosition.cpp |
index 1f28d5a2cf32a0f6d1bf4b5c0d1090db12c3a67e..d002ce670f236a18160f689db7694b5b1a01ccaa 100644 |
--- a/third_party/WebKit/Source/core/style/GridResolvedPosition.cpp |
+++ b/third_party/WebKit/Source/core/style/GridResolvedPosition.cpp |
@@ -47,13 +47,14 @@ static void initialAndFinalPositionsFromStyle(const ComputedStyle& gridContainer |
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() always return a valid resolved position. |
- if (initialPosition.isNamedGridArea() && !GridResolvedPosition::isValidNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, GridResolvedPosition::initialPositionSide(direction))) |
- initialPosition.setAutoPosition(); |
+ if (gridItem.isOutOfFlowPositioned()) { |
+ // Early detect the case of non existing named grid lines for positioned items. |
+ if (initialPosition.isNamedGridArea() && !GridResolvedPosition::isValidNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, GridResolvedPosition::initialPositionSide(direction))) |
+ initialPosition.setAutoPosition(); |
- if (finalPosition.isNamedGridArea() && !GridResolvedPosition::isValidNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, GridResolvedPosition::finalPositionSide(direction))) |
- finalPosition.setAutoPosition(); |
+ if (finalPosition.isNamedGridArea() && !GridResolvedPosition::isValidNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, GridResolvedPosition::finalPositionSide(direction))) |
+ 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()) |
@@ -62,46 +63,80 @@ static void initialAndFinalPositionsFromStyle(const ComputedStyle& gridContainer |
initialPosition.setSpanPosition(1, String()); |
} |
-static GridSpan definiteGridSpanWithInitialNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) |
+static size_t lookAheadForNamedGridLine(int start, size_t numberOfLines, const Vector<size_t>* namedGridLinesIndexes, size_t gridLastLine) |
{ |
- if (resolvedOppositePosition == 0) |
- return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition, resolvedOppositePosition + 1); |
+ ASSERT(numberOfLines); |
+ |
+ // Only implicit lines on the search direction are assumed to have the given name, so we can start to look from first line. |
+ // See: https://drafts.csswg.org/css-grid/#grid-placement-span-int |
+ size_t end = std::max(start, 0); |
+ |
+ if (!namedGridLinesIndexes) { |
+ end = std::max(end, gridLastLine + 1); |
+ return end + numberOfLines - 1; |
+ } |
+ |
+ for (; numberOfLines; ++end) { |
+ if (end > gridLastLine || namedGridLinesIndexes->contains(end)) |
+ numberOfLines--; |
+ } |
- size_t firstLineBeforeOppositePositionIndex = 0; |
- const size_t* firstLineBeforeOppositePosition = std::lower_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition); |
- if (firstLineBeforeOppositePosition != gridLines.end()) |
- firstLineBeforeOppositePositionIndex = firstLineBeforeOppositePosition - gridLines.begin(); |
- size_t gridLineIndex = std::max<int>(0, firstLineBeforeOppositePositionIndex - position.spanPosition()); |
- size_t resolvedGridLinePosition = gridLines[gridLineIndex]; |
- if (resolvedGridLinePosition >= resolvedOppositePosition) |
- resolvedGridLinePosition = resolvedOppositePosition - 1; |
- return GridSpan::untranslatedDefiniteGridSpan(resolvedGridLinePosition, resolvedOppositePosition); |
+ ASSERT(end); |
+ return end - 1; |
} |
-static GridSpan definiteGridSpanWithFinalNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines) |
+static int lookBackForNamedGridLine(int end, size_t numberOfLines, const Vector<size_t>* namedGridLinesIndexes, int gridLastLine) |
{ |
- ASSERT(gridLines.size()); |
- 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 = gridLines[gridLineIndex]; |
- if (resolvedGridLinePosition <= resolvedOppositePosition) |
- resolvedGridLinePosition = resolvedOppositePosition + 1; |
- |
- return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition, resolvedGridLinePosition); |
+ ASSERT(numberOfLines); |
+ |
+ // Only implicit lines on the search direction are assumed to have the given name, so we can start to look from last line. |
+ // See: https://drafts.csswg.org/css-grid/#grid-placement-span-int |
+ int start = std::min(end, gridLastLine); |
+ |
+ if (!namedGridLinesIndexes) { |
+ start = std::min(start, -1); |
+ return start - numberOfLines + 1; |
+ } |
+ |
+ for (; numberOfLines; --start) { |
+ if (start < 0 || namedGridLinesIndexes->contains(static_cast<size_t>(start))) |
+ numberOfLines--; |
+ } |
+ |
+ return start + 1; |
} |
-static GridSpan definiteGridSpanWithNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side, const Vector<size_t>& gridLines) |
+static GridSpan definiteGridSpanWithNamedSpanAgainstOpposite(int resolvedOppositePosition, const GridPosition& position, GridPositionSide side, const Vector<size_t>* gridLines, int lastLine) |
{ |
- if (side == RowStartSide || side == ColumnStartSide) |
- return definiteGridSpanWithInitialNamedSpanAgainstOpposite(resolvedOppositePosition, position, gridLines); |
+ int start, end; |
+ |
+ if (side == RowStartSide || side == ColumnStartSide) { |
+ start = lookBackForNamedGridLine(resolvedOppositePosition - 1, position.spanPosition(), gridLines, lastLine); |
+ end = resolvedOppositePosition; |
+ } else { |
+ start = resolvedOppositePosition; |
+ end = lookAheadForNamedGridLine(resolvedOppositePosition + 1, position.spanPosition(), gridLines, lastLine); |
+ } |
- return definiteGridSpanWithFinalNamedSpanAgainstOpposite(resolvedOppositePosition, position, gridLines); |
+ return GridSpan::untranslatedDefiniteGridSpan(start, end); |
} |
-static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const ComputedStyle& gridContainerStyle, size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) |
+size_t GridResolvedPosition::explicitGridColumnCount(const ComputedStyle& gridContainerStyle) |
+{ |
+ return std::min<size_t>(gridContainerStyle.gridTemplateColumns().size(), kGridMaxTracks); |
+} |
+ |
+size_t GridResolvedPosition::explicitGridRowCount(const ComputedStyle& gridContainerStyle) |
+{ |
+ return std::min<size_t>(gridContainerStyle.gridTemplateRows().size(), kGridMaxTracks); |
+} |
+ |
+static size_t explicitGridSizeForSide(const ComputedStyle& gridContainerStyle, GridPositionSide side) |
+{ |
+ return (side == ColumnStartSide || side == ColumnEndSide) ? GridResolvedPosition::explicitGridColumnCount(gridContainerStyle) : GridResolvedPosition::explicitGridRowCount(gridContainerStyle); |
+} |
+ |
+static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const ComputedStyle& gridContainerStyle, int resolvedOppositePosition, const GridPosition& position, GridPositionSide side) |
{ |
ASSERT(position.isSpan()); |
ASSERT(!position.namedGridLine().isNull()); |
@@ -110,16 +145,9 @@ static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const Comput |
const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyle, 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()) { |
- if ((side == ColumnStartSide || side == RowStartSide) && resolvedOppositePosition) |
- return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition - 1, resolvedOppositePosition); |
- return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition, resolvedOppositePosition + 1); |
- } |
- |
- return definiteGridSpanWithNamedSpanAgainstOpposite(resolvedOppositePosition, position, side, it->value); |
+ const Vector<size_t>* gridLines = it == gridLinesNames.end() ? nullptr : &it->value; |
+ size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side); |
+ return definiteGridSpanWithNamedSpanAgainstOpposite(resolvedOppositePosition, position, side, gridLines, lastLine); |
} |
static GridSpan definiteGridSpanWithSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) |
@@ -131,7 +159,7 @@ static GridSpan definiteGridSpanWithSpanAgainstOpposite(size_t resolvedOppositeP |
return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition, resolvedOppositePosition + positionOffset); |
} |
-static GridSpan resolveGridPositionAgainstOppositePosition(const ComputedStyle& gridContainerStyle, size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) |
+static GridSpan resolveGridPositionAgainstOppositePosition(const ComputedStyle& gridContainerStyle, int resolvedOppositePosition, const GridPosition& position, GridPositionSide side) |
{ |
if (position.isAuto()) { |
if (side == ColumnStartSide || side == RowStartSide) |
@@ -167,40 +195,18 @@ size_t GridResolvedPosition::spanSizeForAutoPlacedItem(const ComputedStyle& grid |
return position.spanPosition(); |
} |
-size_t GridResolvedPosition::explicitGridColumnCount(const ComputedStyle& gridContainerStyle) |
-{ |
- return std::min<size_t>(gridContainerStyle.gridTemplateColumns().size(), kGridMaxTracks); |
-} |
- |
-size_t GridResolvedPosition::explicitGridRowCount(const ComputedStyle& gridContainerStyle) |
-{ |
- return std::min<size_t>(gridContainerStyle.gridTemplateRows().size(), kGridMaxTracks); |
-} |
- |
-static size_t explicitGridSizeForSide(const ComputedStyle& gridContainerStyle, GridPositionSide side) |
-{ |
- return (side == ColumnStartSide || side == ColumnEndSide) ? GridResolvedPosition::explicitGridColumnCount(gridContainerStyle) : GridResolvedPosition::explicitGridRowCount(gridContainerStyle); |
-} |
- |
-static size_t resolveNamedGridLinePositionFromStyle(const ComputedStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side) |
+static int resolveNamedGridLinePositionFromStyle(const ComputedStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side) |
{ |
ASSERT(!position.namedGridLine().isNull()); |
const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyle, side); |
NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine()); |
- if (it == gridLinesNames.end()) { |
- if (position.isPositive()) |
- return 0; |
- size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side); |
- return lastLine; |
- } |
- |
- size_t namedGridLineIndex; |
+ const Vector<size_t>* gridLines = it == gridLinesNames.end() ? nullptr : &it->value; |
+ size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side); |
if (position.isPositive()) |
- namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1; |
+ return lookAheadForNamedGridLine(0, abs(position.integerPosition()), gridLines, lastLine); |
else |
- namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0); |
- return it->value[namedGridLineIndex]; |
+ return lookBackForNamedGridLine(lastLine, abs(position.integerPosition()), gridLines, lastLine); |
} |
static int resolveGridPositionFromStyle(const ComputedStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side) |
@@ -227,7 +233,7 @@ static int resolveGridPositionFromStyle(const ComputedStyle& gridContainerStyle, |
// ''<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(GridResolvedPosition::isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side)); |
+ ASSERT(!position.namedGridLine().isNull()); |
const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerStyle, side); |
NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side)); |
@@ -240,11 +246,10 @@ static int resolveGridPositionFromStyle(const ComputedStyle& gridContainerStyle, |
if (explicitLineIter != gridLineNames.end()) |
return explicitLineIter->value[0]; |
- // 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 GridResolvedPosition::resolveGridPositionsFromStyle(). We should be also covered by the |
- // ASSERT at the beginning of this block. |
- ASSERT_NOT_REACHED(); |
- return 0; |
+ ASSERT(!GridResolvedPosition::isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side)); |
+ // If none of the above works specs mandate to assume that all the lines in the implicit grid have this name. |
+ size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side); |
+ return lastLine + 1; |
} |
case AutoPosition: |
case SpanPosition: |