OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/style/GridResolvedPosition.h" | 6 #include "core/style/GridResolvedPosition.h" |
7 | 7 |
8 #include "core/layout/LayoutBox.h" | 8 #include "core/layout/LayoutBox.h" |
9 #include "core/style/GridCoordinate.h" | 9 #include "core/style/GridCoordinate.h" |
10 | 10 |
11 namespace blink { | 11 namespace blink { |
12 | 12 |
| 13 static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const Comput
edStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePositio
n, const GridPosition&, GridPositionSide); |
| 14 |
| 15 static bool isColumnSide(GridPositionSide side) |
| 16 { |
| 17 return side == ColumnStartSide || side == ColumnEndSide; |
| 18 } |
| 19 |
13 static const NamedGridLinesMap& gridLinesForSide(const ComputedStyle& style, Gri
dPositionSide side) | 20 static const NamedGridLinesMap& gridLinesForSide(const ComputedStyle& style, Gri
dPositionSide side) |
14 { | 21 { |
15 return (side == ColumnStartSide || side == ColumnEndSide) ? style.namedGridC
olumnLines() : style.namedGridRowLines(); | 22 return isColumnSide(side) ? style.namedGridColumnLines() : style.namedGridRo
wLines(); |
16 } | 23 } |
17 | 24 |
18 static inline String implicitNamedGridLineForSide(const String& lineName, GridPo
sitionSide side) | 25 static inline String implicitNamedGridLineForSide(const String& lineName, GridPo
sitionSide side) |
19 { | 26 { |
20 return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-sta
rt" : "-end"); | 27 return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-sta
rt" : "-end"); |
21 } | 28 } |
22 | 29 |
| 30 static GridPositionSide initialPositionSide(GridTrackSizingDirection direction) |
| 31 { |
| 32 return direction == ForColumns ? ColumnStartSide : RowStartSide; |
| 33 } |
| 34 |
| 35 static GridPositionSide finalPositionSide(GridTrackSizingDirection direction) |
| 36 { |
| 37 return direction == ForColumns ? ColumnEndSide : RowEndSide; |
| 38 } |
| 39 |
| 40 static size_t explicitGridSizeForSide(const ComputedStyle& gridContainerStyle, G
ridPositionSide side) |
| 41 { |
| 42 return isColumnSide(side) ? GridResolvedPosition::explicitGridColumnCount(gr
idContainerStyle) : GridResolvedPosition::explicitGridRowCount(gridContainerStyl
e); |
| 43 } |
| 44 |
| 45 bool GridUnresolvedSpan::requiresAutoPlacement() const |
| 46 { |
| 47 return m_initialPosition.shouldBeResolvedAgainstOppositePosition() && m_fina
lPosition.shouldBeResolvedAgainstOppositePosition(); |
| 48 } |
| 49 |
| 50 GridUnresolvedSpan& GridUnresolvedSpan::adjustGridPositionsFromStyle(const Compu
tedStyle& gridContainerStyle) |
| 51 { |
| 52 ASSERT(isColumnSide(m_initialPositionSide) == isColumnSide(m_finalPositionSi
de)); |
| 53 |
| 54 // We must handle the placement error handling code here instead of in the S
tyleAdjuster because we don't want to |
| 55 // overwrite the specified values. |
| 56 if (m_initialPosition.isSpan() && m_finalPosition.isSpan()) |
| 57 m_finalPosition.setAutoPosition(); |
| 58 |
| 59 // Try to early detect the case of non existing named grid lines. This way w
e could assume later that |
| 60 // GridResolvedPosition::resolveGrisPositionFromStyle() won't require the au
toplacement to run, i.e., it'll always return a |
| 61 // valid resolved position. |
| 62 if (m_initialPosition.isNamedGridArea() && !GridResolvedPosition::isValidNam
edLineOrArea(m_initialPosition.namedGridLine(), gridContainerStyle, m_initialPos
itionSide)) |
| 63 m_initialPosition.setAutoPosition(); |
| 64 |
| 65 if (m_finalPosition.isNamedGridArea() && !GridResolvedPosition::isValidNamed
LineOrArea(m_finalPosition.namedGridLine(), gridContainerStyle, m_finalPositionS
ide)) |
| 66 m_finalPosition.setAutoPosition(); |
| 67 |
| 68 // If the grid item has an automatic position and a grid span for a named li
ne in a given dimension, instead treat the grid span as one. |
| 69 if (m_initialPosition.isAuto() && m_finalPosition.isSpan() && !m_finalPositi
on.namedGridLine().isNull()) |
| 70 m_finalPosition.setSpanPosition(1, String()); |
| 71 if (m_finalPosition.isAuto() && m_initialPosition.isSpan() && !m_initialPosi
tion.namedGridLine().isNull()) |
| 72 m_initialPosition.setSpanPosition(1, String()); |
| 73 |
| 74 return *this; |
| 75 } |
| 76 |
| 77 static GridResolvedPosition adjustGridPositionForRowEndColumnEndSide(size_t reso
lvedPosition) |
| 78 { |
| 79 return resolvedPosition ? GridResolvedPosition(resolvedPosition - 1) : GridR
esolvedPosition(0); |
| 80 } |
| 81 |
| 82 static GridResolvedPosition adjustGridPositionForSide(size_t resolvedPosition, G
ridPositionSide side) |
| 83 { |
| 84 // An item finishing on the N-th line belongs to the N-1-th cell. |
| 85 if (side == ColumnEndSide || side == RowEndSide) |
| 86 return adjustGridPositionForRowEndColumnEndSide(resolvedPosition); |
| 87 |
| 88 return GridResolvedPosition(resolvedPosition); |
| 89 } |
| 90 |
| 91 GridResolvedPosition::GridResolvedPosition(const GridPosition& position, GridPos
itionSide side) |
| 92 { |
| 93 ASSERT(position.integerPosition()); |
| 94 size_t integerPosition = position.integerPosition() - 1; |
| 95 |
| 96 m_integerPosition = adjustGridPositionForSide(integerPosition, side).toInt()
; |
| 97 } |
| 98 |
23 bool GridResolvedPosition::isValidNamedLineOrArea(const String& lineName, const
ComputedStyle& style, GridPositionSide side) | 99 bool GridResolvedPosition::isValidNamedLineOrArea(const String& lineName, const
ComputedStyle& style, GridPositionSide side) |
24 { | 100 { |
25 const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side); | 101 const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side); |
26 | 102 |
27 return gridLineNames.contains(implicitNamedGridLineForSide(lineName, side))
|| gridLineNames.contains(lineName); | 103 return gridLineNames.contains(implicitNamedGridLineForSide(lineName, side))
|| gridLineNames.contains(lineName); |
28 } | 104 } |
29 | 105 |
30 GridPositionSide GridResolvedPosition::initialPositionSide(GridTrackSizingDirect
ion direction) | |
31 { | |
32 return (direction == ForColumns) ? ColumnStartSide : RowStartSide; | |
33 } | |
34 | |
35 GridPositionSide GridResolvedPosition::finalPositionSide(GridTrackSizingDirectio
n direction) | |
36 { | |
37 return (direction == ForColumns) ? ColumnEndSide : RowEndSide; | |
38 } | |
39 | |
40 void GridResolvedPosition::initialAndFinalPositionsFromStyle(const ComputedStyle
& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizingDirection direct
ion, GridPosition& initialPosition, GridPosition& finalPosition) | 106 void GridResolvedPosition::initialAndFinalPositionsFromStyle(const ComputedStyle
& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizingDirection direct
ion, GridPosition& initialPosition, GridPosition& finalPosition) |
41 { | 107 { |
42 initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnSt
art() : gridItem.style()->gridRowStart(); | 108 initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnSt
art() : gridItem.style()->gridRowStart(); |
43 finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd(
) : gridItem.style()->gridRowEnd(); | 109 finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd(
) : gridItem.style()->gridRowEnd(); |
44 | 110 |
45 // We must handle the placement error handling code here instead of in the S
tyleAdjuster because we don't want to | 111 // We must handle the placement error handling code here instead of in the S
tyleAdjuster because we don't want to |
46 // overwrite the specified values. | 112 // overwrite the specified values. |
47 if (initialPosition.isSpan() && finalPosition.isSpan()) | 113 if (initialPosition.isSpan() && finalPosition.isSpan()) |
48 finalPosition.setAutoPosition(); | 114 finalPosition.setAutoPosition(); |
49 | 115 |
50 // Try to early detect the case of non existing named grid lines. This way w
e could assume later that | 116 // Try to early detect the case of non existing named grid lines. This way w
e could assume later that |
51 // GridResolvedPosition::resolveGrisPositionFromStyle() always return a vali
d resolved position. | 117 // GridResolvedPosition::resolveGrisPositionFromStyle() always return a vali
d resolved position. |
52 if (initialPosition.isNamedGridArea() && !isValidNamedLineOrArea(initialPosi
tion.namedGridLine(), gridContainerStyle, initialPositionSide(direction))) | 118 if (initialPosition.isNamedGridArea() && !isValidNamedLineOrArea(initialPosi
tion.namedGridLine(), gridContainerStyle, initialPositionSide(direction))) |
53 initialPosition.setAutoPosition(); | 119 initialPosition.setAutoPosition(); |
54 | 120 |
55 if (finalPosition.isNamedGridArea() && !isValidNamedLineOrArea(finalPosition
.namedGridLine(), gridContainerStyle, finalPositionSide(direction))) | 121 if (finalPosition.isNamedGridArea() && !isValidNamedLineOrArea(finalPosition
.namedGridLine(), gridContainerStyle, finalPositionSide(direction))) |
56 finalPosition.setAutoPosition(); | 122 finalPosition.setAutoPosition(); |
57 | 123 |
58 // If the grid item has an automatic position and a grid span for a named li
ne in a given dimension, instead treat the grid span as one. | 124 // If the grid item has an automatic position and a grid span for a named li
ne in a given dimension, instead treat the grid span as one. |
59 if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.nam
edGridLine().isNull()) | 125 if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.nam
edGridLine().isNull()) |
60 finalPosition.setSpanPosition(1, String()); | 126 finalPosition.setSpanPosition(1, String()); |
61 if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.n
amedGridLine().isNull()) | 127 if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.n
amedGridLine().isNull()) |
62 initialPosition.setSpanPosition(1, String()); | 128 initialPosition.setSpanPosition(1, String()); |
63 } | 129 } |
64 | 130 |
| 131 static GridSpan resolveGridPositionAgainstOppositePosition(const ComputedStyle&
gridContainerStyle, const GridResolvedPosition& resolvedOppositePosition, const
GridPosition& position, GridPositionSide side) |
| 132 { |
| 133 if (position.isAuto()) |
| 134 return GridSpan(resolvedOppositePosition, resolvedOppositePosition); |
| 135 |
| 136 ASSERT(position.isSpan()); |
| 137 ASSERT(position.spanPosition() > 0); |
| 138 |
| 139 if (!position.namedGridLine().isNull()) { |
| 140 // span 2 'c' -> we need to find the appropriate grid line before / afte
r our opposite position. |
| 141 return resolveNamedGridLinePositionAgainstOppositePosition(gridContainer
Style, resolvedOppositePosition, position, side); |
| 142 } |
| 143 |
| 144 // 'span 1' is contained inside a single grid track regardless of the direct
ion. |
| 145 // That's why the CSS span value is one more than the offset we apply. |
| 146 size_t positionOffset = position.spanPosition() - 1; |
| 147 if (side == ColumnStartSide || side == RowStartSide) { |
| 148 size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePositi
on.toInt() - positionOffset); |
| 149 return GridSpan(initialResolvedPosition, resolvedOppositePosition); |
| 150 } |
| 151 |
| 152 return GridSpan(resolvedOppositePosition, resolvedOppositePosition.toInt() +
positionOffset); |
| 153 } |
| 154 |
65 GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(con
st ComputedStyle& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizing
Direction direction, const GridResolvedPosition& resolvedInitialPosition) | 155 GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(con
st ComputedStyle& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizing
Direction direction, const GridResolvedPosition& resolvedInitialPosition) |
66 { | 156 { |
67 GridPosition initialPosition, finalPosition; | 157 GridPosition initialPosition, finalPosition; |
68 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i
nitialPosition, finalPosition); | 158 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i
nitialPosition, finalPosition); |
69 | 159 |
70 GridPositionSide finalSide = finalPositionSide(direction); | 160 GridPositionSide finalSide = finalPositionSide(direction); |
71 | 161 |
72 // This method will only be used when both positions need to be resolved aga
inst the opposite one. | 162 // This method will only be used when both positions need to be resolved aga
inst the opposite one. |
73 ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPos
ition.shouldBeResolvedAgainstOppositePosition()); | 163 ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPos
ition.shouldBeResolvedAgainstOppositePosition()); |
74 | 164 |
75 GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition; | 165 GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition; |
76 | 166 |
77 if (initialPosition.isSpan()) | 167 if (initialPosition.isSpan()) |
78 return *resolveGridPositionAgainstOppositePosition(gridContainerStyle, r
esolvedInitialPosition, initialPosition, finalSide); | 168 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, re
solvedInitialPosition, initialPosition, finalSide); |
79 if (finalPosition.isSpan()) | 169 if (finalPosition.isSpan()) |
80 return *resolveGridPositionAgainstOppositePosition(gridContainerStyle, r
esolvedInitialPosition, finalPosition, finalSide); | 170 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, re
solvedInitialPosition, finalPosition, finalSide); |
81 | 171 |
82 return GridSpan(resolvedInitialPosition, resolvedFinalPosition); | 172 return GridSpan(resolvedInitialPosition, resolvedFinalPosition); |
83 } | 173 } |
84 | 174 |
85 PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const C
omputedStyle& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizingDire
ction direction) | 175 static GridResolvedPosition resolveNamedGridLinePositionFromStyle(const Computed
Style& gridContainerStyle, const GridPosition& position, GridPositionSide side) |
86 { | |
87 GridPosition initialPosition, finalPosition; | |
88 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i
nitialPosition, finalPosition); | |
89 | |
90 GridPositionSide initialSide = initialPositionSide(direction); | |
91 GridPositionSide finalSide = finalPositionSide(direction); | |
92 | |
93 if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPositi
on.shouldBeResolvedAgainstOppositePosition()) { | |
94 // We can't get our grid positions without running the auto placement al
gorithm. | |
95 return nullptr; | |
96 } | |
97 | |
98 if (initialPosition.shouldBeResolvedAgainstOppositePosition()) { | |
99 // Infer the position from the final position ('auto / 1' or 'span 2 / 3
' case). | |
100 GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyl
e(gridContainerStyle, finalPosition, finalSide); | |
101 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, fi
nalResolvedPosition, initialPosition, initialSide); | |
102 } | |
103 | |
104 if (finalPosition.shouldBeResolvedAgainstOppositePosition()) { | |
105 // Infer our position from the initial position ('1 / auto' or '3 / span
2' case). | |
106 GridResolvedPosition initialResolvedPosition = resolveGridPositionFromSt
yle(gridContainerStyle, initialPosition, initialSide); | |
107 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, in
itialResolvedPosition, finalPosition, finalSide); | |
108 } | |
109 | |
110 GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(
gridContainerStyle, initialPosition, initialSide); | |
111 GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gr
idContainerStyle, finalPosition, finalSide); | |
112 | |
113 // If 'grid-after' specifies a line at or before that specified by 'grid-bef
ore', it computes to 'span 1'. | |
114 if (resolvedFinalPosition < resolvedInitialPosition) | |
115 resolvedFinalPosition = resolvedInitialPosition; | |
116 | |
117 return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition)
); | |
118 } | |
119 | |
120 size_t GridResolvedPosition::explicitGridColumnCount(const ComputedStyle& gridCo
ntainerStyle) | |
121 { | |
122 return std::min(gridContainerStyle.gridTemplateColumns().size(), kGridMaxTra
cks); | |
123 } | |
124 | |
125 size_t GridResolvedPosition::explicitGridRowCount(const ComputedStyle& gridConta
inerStyle) | |
126 { | |
127 return std::min(gridContainerStyle.gridTemplateRows().size(), kGridMaxTracks
); | |
128 } | |
129 | |
130 size_t GridResolvedPosition::explicitGridSizeForSide(const ComputedStyle& gridCo
ntainerStyle, GridPositionSide side) | |
131 { | |
132 return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColu
mnCount(gridContainerStyle) : explicitGridRowCount(gridContainerStyle); | |
133 } | |
134 | |
135 GridResolvedPosition GridResolvedPosition::resolveNamedGridLinePositionFromStyle
(const ComputedStyle& gridContainerStyle, const GridPosition& position, GridPosi
tionSide side) | |
136 { | 176 { |
137 ASSERT(!position.namedGridLine().isNull()); | 177 ASSERT(!position.namedGridLine().isNull()); |
138 | 178 |
139 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl
e, side); | 179 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl
e, side); |
140 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri
dLine()); | 180 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri
dLine()); |
141 if (it == gridLinesNames.end()) { | 181 if (it == gridLinesNames.end()) { |
142 if (position.isPositive()) | 182 if (position.isPositive()) |
143 return GridResolvedPosition(0); | 183 return GridResolvedPosition(0); |
144 const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side
); | 184 const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side
); |
145 return adjustGridPositionForSide(lastLine, side); | 185 return adjustGridPositionForSide(lastLine, side); |
146 } | 186 } |
147 | 187 |
148 size_t namedGridLineIndex; | 188 size_t namedGridLineIndex; |
149 if (position.isPositive()) | 189 if (position.isPositive()) |
150 namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->va
lue.size()) - 1; | 190 namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->va
lue.size()) - 1; |
151 else | 191 else |
152 namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integ
erPosition()), 0); | 192 namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integ
erPosition()), 0); |
153 return adjustGridPositionForSide(it->value[namedGridLineIndex], side); | 193 return adjustGridPositionForSide(it->value[namedGridLineIndex], side); |
154 } | 194 } |
155 | 195 |
156 GridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const Co
mputedStyle& gridContainerStyle, const GridPosition& position, GridPositionSide
side) | 196 static GridResolvedPosition resolveGridPositionFromStyle(const ComputedStyle& gr
idContainerStyle, const GridPosition& position, GridPositionSide side) |
157 { | 197 { |
158 switch (position.type()) { | 198 switch (position.type()) { |
159 case ExplicitPosition: { | 199 case ExplicitPosition: { |
160 ASSERT(position.integerPosition()); | 200 ASSERT(position.integerPosition()); |
161 | 201 |
162 if (!position.namedGridLine().isNull()) | 202 if (!position.namedGridLine().isNull()) |
163 return resolveNamedGridLinePositionFromStyle(gridContainerStyle, pos
ition, side); | 203 return resolveNamedGridLinePositionFromStyle(gridContainerStyle, pos
ition, side); |
164 | 204 |
165 // Handle <integer> explicit position. | 205 // Handle <integer> explicit position. |
166 if (position.isPositive()) | 206 if (position.isPositive()) |
167 return adjustGridPositionForSide(position.integerPosition() - 1, sid
e); | 207 return adjustGridPositionForSide(position.integerPosition() - 1, sid
e); |
168 | 208 |
169 size_t resolvedPosition = abs(position.integerPosition()) - 1; | 209 size_t resolvedPosition = abs(position.integerPosition()) - 1; |
170 const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, si
de); | 210 const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, si
de); |
171 | 211 |
172 // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html,
we clamp negative value to the first line. | 212 // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html,
we clamp negative value to the first line. |
173 if (endOfTrack < resolvedPosition) | 213 if (endOfTrack < resolvedPosition) |
174 return GridResolvedPosition(0); | 214 return GridResolvedPosition(0); |
175 | 215 |
176 return adjustGridPositionForSide(endOfTrack - resolvedPosition, side); | 216 return adjustGridPositionForSide(endOfTrack - resolvedPosition, side); |
177 } | 217 } |
178 case NamedGridAreaPosition: | 218 case NamedGridAreaPosition: |
179 { | 219 { |
180 // First attempt to match the grid area's edge to a named grid area: if
there is a named line with the name | 220 // First attempt to match the grid area's edge to a named grid area: if
there is a named line with the name |
181 // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for
grid-*-end), contributes the first such | 221 // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for
grid-*-end), contributes the first such |
182 // line to the grid item's placement. | 222 // line to the grid item's placement. |
183 String namedGridLine = position.namedGridLine(); | 223 String namedGridLine = position.namedGridLine(); |
184 ASSERT(isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side)); | 224 ASSERT(GridResolvedPosition::isValidNamedLineOrArea(namedGridLine, gridC
ontainerStyle, side)); |
185 | 225 |
186 const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerS
tyle, side); | 226 const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerS
tyle, side); |
187 NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find(
implicitNamedGridLineForSide(namedGridLine, side)); | 227 NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find(
implicitNamedGridLineForSide(namedGridLine, side)); |
188 if (implicitLineIter != gridLineNames.end()) | 228 if (implicitLineIter != gridLineNames.end()) |
189 return adjustGridPositionForSide(implicitLineIter->value[0], side); | 229 return adjustGridPositionForSide(implicitLineIter->value[0], side); |
190 | 230 |
191 // Otherwise, if there is a named line with the specified name, contribu
tes the first such line to the grid | 231 // Otherwise, if there is a named line with the specified name, contribu
tes the first such line to the grid |
192 // item's placement. | 232 // item's placement. |
193 NamedGridLinesMap::const_iterator explicitLineIter = gridLineNames.find(
namedGridLine); | 233 NamedGridLinesMap::const_iterator explicitLineIter = gridLineNames.find(
namedGridLine); |
194 if (explicitLineIter != gridLineNames.end()) | 234 if (explicitLineIter != gridLineNames.end()) |
195 return adjustGridPositionForSide(explicitLineIter->value[0], side); | 235 return adjustGridPositionForSide(explicitLineIter->value[0], side); |
196 | 236 |
197 // If none of the above works specs mandate us to treat it as auto BUT w
e should have detected it before calling | 237 // If none of the above works specs mandate us to treat it as auto BUT w
e should have detected it before calling |
198 // this function in GridResolvedPosition::resolveGridPositionsFromStyle(
). We should be also covered by the | 238 // this function in GridResolvedPosition::resolveGridPositionsFromStyle(
). We should be also covered by the |
199 // ASSERT at the beginning of this block. | 239 // ASSERT at the beginning of this block. |
200 ASSERT_NOT_REACHED(); | 240 ASSERT_NOT_REACHED(); |
201 return GridResolvedPosition(0); | 241 return GridResolvedPosition(0); |
202 } | 242 } |
203 case AutoPosition: | 243 case AutoPosition: |
204 case SpanPosition: | 244 case SpanPosition: |
205 // 'auto' and span depend on the opposite position for resolution (e.g.
grid-row: auto / 1 or grid-column: span 3 / "myHeader"). | 245 // 'auto' and span depend on the opposite position for resolution (e.g.
grid-row: auto / 1 or grid-column: span 3 / "myHeader"). |
206 ASSERT_NOT_REACHED(); | 246 ASSERT_NOT_REACHED(); |
207 return GridResolvedPosition(0); | 247 return GridResolvedPosition(0); |
208 } | 248 } |
209 ASSERT_NOT_REACHED(); | 249 ASSERT_NOT_REACHED(); |
210 return GridResolvedPosition(0); | 250 return GridResolvedPosition(0); |
211 } | 251 } |
212 | 252 |
213 PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePos
ition(const ComputedStyle& gridContainerStyle, const GridResolvedPosition& resol
vedOppositePosition, const GridPosition& position, GridPositionSide side) | 253 GridSpan GridResolvedPosition::resolveGridPositionsFromStyle(const GridUnresolve
dSpan& unresolvedSpan, const ComputedStyle& gridContainerStyle) |
214 { | 254 { |
215 if (position.isAuto()) | 255 ASSERT(!unresolvedSpan.requiresAutoPlacement()); |
216 return GridSpan::create(resolvedOppositePosition, resolvedOppositePositi
on); | |
217 | 256 |
218 ASSERT(position.isSpan()); | 257 if (unresolvedSpan.initialPosition().shouldBeResolvedAgainstOppositePosition
()) { |
219 ASSERT(position.spanPosition() > 0); | 258 // Infer the position from the final position ('auto / 1' or 'span 2 / 3
' case). |
220 | 259 auto finalResolvedPosition = resolveGridPositionFromStyle(gridContainerS
tyle, unresolvedSpan.finalPosition(), unresolvedSpan.finalPositionSide()); |
221 if (!position.namedGridLine().isNull()) { | 260 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, fi
nalResolvedPosition, unresolvedSpan.initialPosition(), unresolvedSpan.initialPos
itionSide()); |
222 // span 2 'c' -> we need to find the appropriate grid line before / afte
r our opposite position. | |
223 return resolveNamedGridLinePositionAgainstOppositePosition(gridContainer
Style, resolvedOppositePosition, position, side); | |
224 } | 261 } |
225 | 262 |
226 return GridSpan::createWithSpanAgainstOpposite(resolvedOppositePosition, pos
ition, side); | 263 if (unresolvedSpan.finalPosition().shouldBeResolvedAgainstOppositePosition()
) { |
| 264 // Infer our position from the initial position ('1 / auto' or '3 / span
2' case). |
| 265 auto initialResolvedPosition = resolveGridPositionFromStyle(gridContaine
rStyle, unresolvedSpan.initialPosition(), unresolvedSpan.initialPositionSide()); |
| 266 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, in
itialResolvedPosition, unresolvedSpan.finalPosition(), unresolvedSpan.finalPosit
ionSide()); |
| 267 } |
| 268 |
| 269 auto resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerSty
le, unresolvedSpan.initialPosition(), unresolvedSpan.initialPositionSide()); |
| 270 auto resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle
, unresolvedSpan.finalPosition(), unresolvedSpan.finalPositionSide()); |
| 271 |
| 272 // If 'grid-row-end' specifies a line at or before that specified by 'grid-r
ow-start', it computes to 'span 1'. |
| 273 return GridSpan(resolvedInitialPosition, std::max(resolvedInitialPosition, r
esolvedFinalPosition)); |
227 } | 274 } |
228 | 275 |
229 PassOwnPtr<GridSpan> GridResolvedPosition::resolveNamedGridLinePositionAgainstOp
positePosition(const ComputedStyle& gridContainerStyle, const GridResolvedPositi
on& resolvedOppositePosition, const GridPosition& position, GridPositionSide sid
e) | 276 size_t GridResolvedPosition::explicitGridColumnCount(const ComputedStyle& gridCo
ntainerStyle) |
| 277 { |
| 278 return std::min(gridContainerStyle.gridTemplateColumns().size(), kGridMaxTra
cks); |
| 279 } |
| 280 |
| 281 size_t GridResolvedPosition::explicitGridRowCount(const ComputedStyle& gridConta
inerStyle) |
| 282 { |
| 283 return std::min(gridContainerStyle.gridTemplateRows().size(), kGridMaxTracks
); |
| 284 } |
| 285 |
| 286 static inline size_t firstNamedGridLineBeforePosition(size_t position, const Vec
tor<size_t>& gridLines) |
| 287 { |
| 288 // The grid line inequality needs to be strict (which doesn't match the afte
r / end case) because |position| is |
| 289 // already converted to an index in our grid representation (ie one was remo
ved from the grid line to account for |
| 290 // the side). |
| 291 size_t firstLineBeforePositionIndex = 0; |
| 292 auto firstLineBeforePosition = std::lower_bound(gridLines.begin(), gridLines
.end(), position); |
| 293 if (firstLineBeforePosition != gridLines.end()) { |
| 294 if (*firstLineBeforePosition > position && firstLineBeforePosition != gr
idLines.begin()) |
| 295 --firstLineBeforePosition; |
| 296 |
| 297 firstLineBeforePositionIndex = firstLineBeforePosition - gridLines.begin
(); |
| 298 } |
| 299 return firstLineBeforePositionIndex; |
| 300 } |
| 301 |
| 302 static GridSpan resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePo
sition(const GridResolvedPosition& resolvedOppositePosition, const GridPosition&
position, const Vector<size_t>& gridLines) |
| 303 { |
| 304 size_t gridLineIndex = std::max<int>(0, firstNamedGridLineBeforePosition(res
olvedOppositePosition.toInt(), gridLines) - position.spanPosition() + 1); |
| 305 GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition(gridLin
es[gridLineIndex]); |
| 306 return GridSpan(std::min(resolvedGridLinePosition, resolvedOppositePosition)
, resolvedOppositePosition); |
| 307 } |
| 308 |
| 309 static GridSpan resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePositi
on(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& pos
ition, const Vector<size_t>& gridLines) |
| 310 { |
| 311 ASSERT(gridLines.size()); |
| 312 size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1; |
| 313 const auto firstLineAfterOppositePosition = std::upper_bound(gridLines.begin
(), gridLines.end(), resolvedOppositePosition); |
| 314 if (firstLineAfterOppositePosition != gridLines.end()) |
| 315 firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - g
ridLines.begin(); |
| 316 |
| 317 size_t gridLineIndex = std::min<size_t>(gridLines.size() - 1, firstLineAfter
OppositePositionIndex + position.spanPosition() - 1); |
| 318 GridResolvedPosition resolvedGridLinePosition = adjustGridPositionForRowEndC
olumnEndSide(gridLines[gridLineIndex]); |
| 319 if (resolvedGridLinePosition < resolvedOppositePosition) |
| 320 resolvedGridLinePosition = resolvedOppositePosition; |
| 321 return GridSpan(resolvedOppositePosition, resolvedGridLinePosition); |
| 322 } |
| 323 |
| 324 static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const Comput
edStyle& gridContainerStyle, const GridResolvedPosition& resolvedOppositePositio
n, const GridPosition& position, GridPositionSide side) |
230 { | 325 { |
231 ASSERT(position.isSpan()); | 326 ASSERT(position.isSpan()); |
232 ASSERT(!position.namedGridLine().isNull()); | 327 ASSERT(!position.namedGridLine().isNull()); |
233 // Negative positions are not allowed per the specification and should have
been handled during parsing. | 328 // Negative positions are not allowed per the specification and should have
been handled during parsing. |
234 ASSERT(position.spanPosition() > 0); | 329 ASSERT(position.spanPosition() > 0); |
235 | 330 |
236 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl
e, side); | 331 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl
e, side); |
237 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri
dLine()); | 332 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri
dLine()); |
238 | 333 |
239 // 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). | 334 // 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). |
240 // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html. | 335 // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html. |
241 if (it == gridLinesNames.end()) | 336 if (it == gridLinesNames.end()) |
242 return GridSpan::create(resolvedOppositePosition, resolvedOppositePositi
on); | 337 return GridSpan(resolvedOppositePosition, resolvedOppositePosition); |
243 | 338 |
244 return GridSpan::createWithNamedSpanAgainstOpposite(resolvedOppositePosition
, position, side, it->value); | 339 if (side == RowStartSide || side == ColumnStartSide) |
| 340 return resolveRowStartColumnStartNamedGridLinePositionAgainstOppositePos
ition(resolvedOppositePosition, position, it->value); |
| 341 |
| 342 return resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition(re
solvedOppositePosition, position, it->value); |
| 343 } |
| 344 |
| 345 GridUnresolvedSpan GridResolvedPosition::unresolvedSpanFromStyle(const ComputedS
tyle& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizingDirection di
rection) |
| 346 { |
| 347 const ComputedStyle& itemStyle = gridItem.styleRef(); |
| 348 if (direction == ForColumns) { |
| 349 GridUnresolvedSpan unresolvedSpan(itemStyle.gridColumnStart(), ColumnSta
rtSide, itemStyle.gridColumnEnd(), ColumnEndSide); |
| 350 return unresolvedSpan.adjustGridPositionsFromStyle(gridContainerStyle); |
| 351 } |
| 352 |
| 353 GridUnresolvedSpan unresolvedSpan(itemStyle.gridRowStart(), RowStartSide, it
emStyle.gridRowEnd(), RowEndSide); |
| 354 return unresolvedSpan.adjustGridPositionsFromStyle(gridContainerStyle); |
245 } | 355 } |
246 | 356 |
247 } // namespace blink | 357 } // namespace blink |
OLD | NEW |