1a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// found in the LICENSE file.
4a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
5a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "config.h"
6a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "core/rendering/style/GridResolvedPosition.h"
7a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
8a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "core/rendering/RenderBox.h"
9a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "core/rendering/style/GridCoordinate.h"
10a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
11c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
12a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
13d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)static const NamedGridLinesMap& gridLinesForSide(const RenderStyle& style, GridPositionSide side)
14d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
15d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return (side == ColumnStartSide || side == ColumnEndSide) ? style.namedGridColumnLines() : style.namedGridRowLines();
16d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
17d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
185d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static inline String implicitNamedGridLineForSide(const String& lineName, GridPositionSide side)
19d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
205d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-start" : "-end");
215d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
225d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static bool isValidNamedLineOrArea(const String& lineName, const RenderStyle& style, GridPositionSide side)
245d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles){
255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side);
265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return gridLineNames.contains(implicitNamedGridLineForSide(lineName, side)) || gridLineNames.contains(lineName);
28d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
29d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
30f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)static GridPositionSide calculateInitialPositionSide(GridTrackSizingDirection direction)
31f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
32f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return (direction == ForColumns) ? ColumnStartSide : RowStartSide;
33f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
34f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
35f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)static GridPositionSide calculateFinalPositionSide(GridTrackSizingDirection direction)
36f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
37f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return (direction == ForColumns) ? ColumnEndSide : RowEndSide;
38f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
39f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
40f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)void GridResolvedPosition::initialAndFinalPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, GridPosition& initialPosition, GridPosition& finalPosition)
41a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
42f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnStart() : gridItem.style()->gridRowStart();
43f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd() : gridItem.style()->gridRowEnd();
44f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPositionSide initialPositionSide = calculateInitialPositionSide(direction);
45f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPositionSide finalPositionSide = calculateFinalPositionSide(direction);
46a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
47a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // We must handle the placement error handling code here instead of in the StyleAdjuster because we don't want to
48a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // overwrite the specified values.
49a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (initialPosition.isSpan() && finalPosition.isSpan())
50a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        finalPosition.setAutoPosition();
51a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
525d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Try to early detect the case of non existing named grid lines. This way we could assume later that
535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // GridResolvedPosition::resolveGrisPositionFromStyle() always return a valid resolved position.
545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (initialPosition.isNamedGridArea() && !isValidNamedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, initialPositionSide))
55a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        initialPosition.setAutoPosition();
56a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
575d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (finalPosition.isNamedGridArea() && !isValidNamedLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, finalPositionSide))
58a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        finalPosition.setAutoPosition();
595d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // 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.
615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.namedGridLine().isNull())
625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        finalPosition.setSpanPosition(1, String());
635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.namedGridLine().isNull())
645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        initialPosition.setSpanPosition(1, String());
65f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
66f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
67f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction, const GridResolvedPosition& resolvedInitialPosition)
68f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
69f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPosition initialPosition, finalPosition;
70f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, initialPosition, finalPosition);
71f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
72f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPositionSide finalPositionSide = calculateFinalPositionSide(direction);
73f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
74f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    // This method will only be used when both positions need to be resolved against the opposite one.
75f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition());
76f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
77f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition;
78f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
79f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (initialPosition.isSpan()) {
80f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, initialPosition, finalPositionSide)->resolvedFinalPosition;
81f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    } else if (finalPosition.isSpan()) {
82f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        resolvedFinalPosition = resolveGridPositionAgainstOppositePosition(gridContainerStyle, resolvedInitialPosition, finalPosition, finalPositionSide)->resolvedFinalPosition;
83f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
84f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
85f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return GridSpan(resolvedInitialPosition, resolvedFinalPosition);
86f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
87f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
88f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const RenderStyle& gridContainerStyle, const RenderBox& gridItem, GridTrackSizingDirection direction)
89f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
90f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPosition initialPosition, finalPosition;
91f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, initialPosition, finalPosition);
92f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
93f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPositionSide initialPositionSide = calculateInitialPositionSide(direction);
94f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    GridPositionSide finalPositionSide = calculateFinalPositionSide(direction);
95a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
96a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPosition.shouldBeResolvedAgainstOppositePosition()) {
97197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // FIXME: Implement properly "stack" value in auto-placement algorithm.
98197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (gridContainerStyle.isGridAutoFlowAlgorithmStack())
99a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return adoptPtr(new GridSpan(0, 0));
100a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // We can't get our grid positions without running the auto placement algorithm.
102a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return nullptr;
103a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
105a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
106a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
107a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide);
108a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return resolveGridPositionAgainstOppositePosition(gridContainerStyle, finalResolvedPosition, initialPosition, initialPositionSide);
109a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
110a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
111a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
112a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
113a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        GridResolvedPosition initialResolvedPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide);
114a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return resolveGridPositionAgainstOppositePosition(gridContainerStyle, initialResolvedPosition, finalPosition, finalPositionSide);
115a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
116a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
117a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerStyle, initialPosition, initialPositionSide);
118a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalPositionSide);
119a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
120a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // If 'grid-after' specifies a line at or before that specified by 'grid-before', it computes to 'span 1'.
121a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (resolvedFinalPosition < resolvedInitialPosition)
122a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        resolvedFinalPosition = resolvedInitialPosition;
123a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
124a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
125a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
126a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
127a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochsize_t GridResolvedPosition::explicitGridColumnCount(const RenderStyle& gridContainerStyle)
128a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
129a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return gridContainerStyle.gridTemplateColumns().size();
130a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
132a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochsize_t GridResolvedPosition::explicitGridRowCount(const RenderStyle& gridContainerStyle)
133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return gridContainerStyle.gridTemplateRows().size();
135a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochsize_t GridResolvedPosition::explicitGridSizeForSide(const RenderStyle& gridContainerStyle, GridPositionSide side)
138a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
139a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColumnCount(gridContainerStyle) : explicitGridRowCount(gridContainerStyle);
140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochGridResolvedPosition GridResolvedPosition::resolveNamedGridLinePositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(!position.namedGridLine().isNull());
145a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
146d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyle, side);
147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (it == gridLinesNames.end()) {
149a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (position.isPositive())
150a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return GridResolvedPosition(0);
151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side);
152a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return adjustGridPositionForSide(lastLine, side);
153a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
154a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    size_t namedGridLineIndex;
156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (position.isPositive())
157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->value.size()) - 1;
158a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    else
159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integerPosition()), 0);
160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return adjustGridPositionForSide(it->value[namedGridLineIndex], side);
161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
163a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochGridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const RenderStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
164a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
165a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (position.type()) {
166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case ExplicitPosition: {
167a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ASSERT(position.integerPosition());
168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (!position.namedGridLine().isNull())
170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return resolveNamedGridLinePositionFromStyle(gridContainerStyle, position, side);
171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
172a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // Handle <integer> explicit position.
173a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (position.isPositive())
174a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return adjustGridPositionForSide(position.integerPosition() - 1, side);
175a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        size_t resolvedPosition = abs(position.integerPosition()) - 1;
177a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, side);
178a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
179a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
180a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (endOfTrack < resolvedPosition)
181a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return GridResolvedPosition(0);
182a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
183a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return adjustGridPositionForSide(endOfTrack - resolvedPosition, side);
184a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
185a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case NamedGridAreaPosition:
186a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    {
187d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // First attempt to match the grid area’s edge to a named grid area: if there is a named line with the name
188d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such
189d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // line to the grid item’s placement.
190d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        String namedGridLine = position.namedGridLine();
1915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        ASSERT(isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side));
1925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
193d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerStyle, side);
1945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find(implicitNamedGridLineForSide(namedGridLine, side));
195d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (implicitLineIter != gridLineNames.end())
196d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return adjustGridPositionForSide(implicitLineIter->value[0], side);
197d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
198d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // Otherwise, if there is a named line with the specified name, contributes the first such line to the grid
199d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        // item’s placement.
200d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        NamedGridLinesMap::const_iterator explicitLineIter = gridLineNames.find(namedGridLine);
201d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        if (explicitLineIter != gridLineNames.end())
202d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            return adjustGridPositionForSide(explicitLineIter->value[0], side);
203d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // If none of the above works specs mandate us to treat it as auto BUT we should have detected it before calling
2055d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // this function in GridResolvedPosition::resolveGridPositionsFromStyle(). We should be also covered by the
2065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        // ASSERT at the beginning of this block.
2075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        ASSERT_NOT_REACHED();
208a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return GridResolvedPosition(0);
209a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
210a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case AutoPosition:
211a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case SpanPosition:
212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ASSERT_NOT_REACHED();
214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return GridResolvedPosition(0);
215a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
216a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT_NOT_REACHED();
217a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return GridResolvedPosition(0);
218a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
219a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
220a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochPassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
221a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
222a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (position.isAuto())
223a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
224a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
225a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(position.isSpan());
226a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(position.spanPosition() > 0);
227a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
228a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (!position.namedGridLine().isNull()) {
229a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        // span 2 'c' -> we need to find the appropriate grid line before / after our opposite position.
230a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return resolveNamedGridLinePositionAgainstOppositePosition(gridContainerStyle, resolvedOppositePosition, position, side);
231a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
232a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
233a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return GridSpan::createWithSpanAgainstOpposite(resolvedOppositePosition, position, side);
234a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
235a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
236a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochPassOwnPtr<GridSpan> GridResolvedPosition::resolveNamedGridLinePositionAgainstOppositePosition(const RenderStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
237a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
238a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(position.isSpan());
239a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(!position.namedGridLine().isNull());
240a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // Negative positions are not allowed per the specification and should have been handled during parsing.
241a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(position.spanPosition() > 0);
242a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
243d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyle, side);
244a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGridLine());
245a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
246a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // 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).
247a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html.
248a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (it == gridLinesNames.end())
249a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
250a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
251a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return GridSpan::createWithNamedSpanAgainstOpposite(resolvedOppositePosition, position, side, it->value);
252a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
253a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
254c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
255