OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "core/layout/style/GridResolvedPosition.h" | |
7 | |
8 #include "core/layout/LayoutBox.h" | |
9 #include "core/layout/style/GridCoordinate.h" | |
10 | |
11 namespace blink { | |
12 | |
13 static const NamedGridLinesMap& gridLinesForSide(const ComputedStyle& style, Gri
dPositionSide side) | |
14 { | |
15 return (side == ColumnStartSide || side == ColumnEndSide) ? style.namedGridC
olumnLines() : style.namedGridRowLines(); | |
16 } | |
17 | |
18 static inline String implicitNamedGridLineForSide(const String& lineName, GridPo
sitionSide side) | |
19 { | |
20 return lineName + ((side == ColumnStartSide || side == RowStartSide) ? "-sta
rt" : "-end"); | |
21 } | |
22 | |
23 static bool isValidNamedLineOrArea(const String& lineName, const ComputedStyle&
style, GridPositionSide side) | |
24 { | |
25 const NamedGridLinesMap& gridLineNames = gridLinesForSide(style, side); | |
26 | |
27 return gridLineNames.contains(implicitNamedGridLineForSide(lineName, side))
|| gridLineNames.contains(lineName); | |
28 } | |
29 | |
30 static GridPositionSide calculateInitialPositionSide(GridTrackSizingDirection di
rection) | |
31 { | |
32 return (direction == ForColumns) ? ColumnStartSide : RowStartSide; | |
33 } | |
34 | |
35 static GridPositionSide calculateFinalPositionSide(GridTrackSizingDirection dire
ction) | |
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) | |
41 { | |
42 initialPosition = (direction == ForColumns) ? gridItem.style()->gridColumnSt
art() : gridItem.style()->gridRowStart(); | |
43 finalPosition = (direction == ForColumns) ? gridItem.style()->gridColumnEnd(
) : gridItem.style()->gridRowEnd(); | |
44 GridPositionSide initialPositionSide = calculateInitialPositionSide(directio
n); | |
45 GridPositionSide finalPositionSide = calculateFinalPositionSide(direction); | |
46 | |
47 // We must handle the placement error handling code here instead of in the S
tyleAdjuster because we don't want to | |
48 // overwrite the specified values. | |
49 if (initialPosition.isSpan() && finalPosition.isSpan()) | |
50 finalPosition.setAutoPosition(); | |
51 | |
52 // Try to early detect the case of non existing named grid lines. This way w
e could assume later that | |
53 // GridResolvedPosition::resolveGrisPositionFromStyle() always return a vali
d resolved position. | |
54 if (initialPosition.isNamedGridArea() && !isValidNamedLineOrArea(initialPosi
tion.namedGridLine(), gridContainerStyle, initialPositionSide)) | |
55 initialPosition.setAutoPosition(); | |
56 | |
57 if (finalPosition.isNamedGridArea() && !isValidNamedLineOrArea(finalPosition
.namedGridLine(), gridContainerStyle, finalPositionSide)) | |
58 finalPosition.setAutoPosition(); | |
59 | |
60 // 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. | |
61 if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.nam
edGridLine().isNull()) | |
62 finalPosition.setSpanPosition(1, String()); | |
63 if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.n
amedGridLine().isNull()) | |
64 initialPosition.setSpanPosition(1, String()); | |
65 } | |
66 | |
67 GridSpan GridResolvedPosition::resolveGridPositionsFromAutoPlacementPosition(con
st ComputedStyle& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizing
Direction direction, const GridResolvedPosition& resolvedInitialPosition) | |
68 { | |
69 GridPosition initialPosition, finalPosition; | |
70 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i
nitialPosition, finalPosition); | |
71 | |
72 GridPositionSide finalPositionSide = calculateFinalPositionSide(direction); | |
73 | |
74 // This method will only be used when both positions need to be resolved aga
inst the opposite one. | |
75 ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPos
ition.shouldBeResolvedAgainstOppositePosition()); | |
76 | |
77 GridResolvedPosition resolvedFinalPosition = resolvedInitialPosition; | |
78 | |
79 if (initialPosition.isSpan()) | |
80 return *resolveGridPositionAgainstOppositePosition(gridContainerStyle, r
esolvedInitialPosition, initialPosition, finalPositionSide); | |
81 if (finalPosition.isSpan()) | |
82 return *resolveGridPositionAgainstOppositePosition(gridContainerStyle, r
esolvedInitialPosition, finalPosition, finalPositionSide); | |
83 | |
84 return GridSpan(resolvedInitialPosition, resolvedFinalPosition); | |
85 } | |
86 | |
87 PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionsFromStyle(const C
omputedStyle& gridContainerStyle, const LayoutBox& gridItem, GridTrackSizingDire
ction direction) | |
88 { | |
89 GridPosition initialPosition, finalPosition; | |
90 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i
nitialPosition, finalPosition); | |
91 | |
92 GridPositionSide initialPositionSide = calculateInitialPositionSide(directio
n); | |
93 GridPositionSide finalPositionSide = calculateFinalPositionSide(direction); | |
94 | |
95 if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPositi
on.shouldBeResolvedAgainstOppositePosition()) { | |
96 // We can't get our grid positions without running the auto placement al
gorithm. | |
97 return nullptr; | |
98 } | |
99 | |
100 if (initialPosition.shouldBeResolvedAgainstOppositePosition()) { | |
101 // Infer the position from the final position ('auto / 1' or 'span 2 / 3
' case). | |
102 GridResolvedPosition finalResolvedPosition = resolveGridPositionFromStyl
e(gridContainerStyle, finalPosition, finalPositionSide); | |
103 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, fi
nalResolvedPosition, initialPosition, initialPositionSide); | |
104 } | |
105 | |
106 if (finalPosition.shouldBeResolvedAgainstOppositePosition()) { | |
107 // Infer our position from the initial position ('1 / auto' or '3 / span
2' case). | |
108 GridResolvedPosition initialResolvedPosition = resolveGridPositionFromSt
yle(gridContainerStyle, initialPosition, initialPositionSide); | |
109 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, in
itialResolvedPosition, finalPosition, finalPositionSide); | |
110 } | |
111 | |
112 GridResolvedPosition resolvedInitialPosition = resolveGridPositionFromStyle(
gridContainerStyle, initialPosition, initialPositionSide); | |
113 GridResolvedPosition resolvedFinalPosition = resolveGridPositionFromStyle(gr
idContainerStyle, finalPosition, finalPositionSide); | |
114 | |
115 // If 'grid-after' specifies a line at or before that specified by 'grid-bef
ore', it computes to 'span 1'. | |
116 if (resolvedFinalPosition < resolvedInitialPosition) | |
117 resolvedFinalPosition = resolvedInitialPosition; | |
118 | |
119 return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition)
); | |
120 } | |
121 | |
122 size_t GridResolvedPosition::explicitGridColumnCount(const ComputedStyle& gridCo
ntainerStyle) | |
123 { | |
124 return std::min(gridContainerStyle.gridTemplateColumns().size(), kGridMaxTra
cks); | |
125 } | |
126 | |
127 size_t GridResolvedPosition::explicitGridRowCount(const ComputedStyle& gridConta
inerStyle) | |
128 { | |
129 return std::min(gridContainerStyle.gridTemplateRows().size(), kGridMaxTracks
); | |
130 } | |
131 | |
132 size_t GridResolvedPosition::explicitGridSizeForSide(const ComputedStyle& gridCo
ntainerStyle, GridPositionSide side) | |
133 { | |
134 return (side == ColumnStartSide || side == ColumnEndSide) ? explicitGridColu
mnCount(gridContainerStyle) : explicitGridRowCount(gridContainerStyle); | |
135 } | |
136 | |
137 GridResolvedPosition GridResolvedPosition::resolveNamedGridLinePositionFromStyle
(const ComputedStyle& gridContainerStyle, const GridPosition& position, GridPosi
tionSide side) | |
138 { | |
139 ASSERT(!position.namedGridLine().isNull()); | |
140 | |
141 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl
e, side); | |
142 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri
dLine()); | |
143 if (it == gridLinesNames.end()) { | |
144 if (position.isPositive()) | |
145 return GridResolvedPosition(0); | |
146 const size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side
); | |
147 return adjustGridPositionForSide(lastLine, side); | |
148 } | |
149 | |
150 size_t namedGridLineIndex; | |
151 if (position.isPositive()) | |
152 namedGridLineIndex = std::min<size_t>(position.integerPosition(), it->va
lue.size()) - 1; | |
153 else | |
154 namedGridLineIndex = std::max<int>(it->value.size() - abs(position.integ
erPosition()), 0); | |
155 return adjustGridPositionForSide(it->value[namedGridLineIndex], side); | |
156 } | |
157 | |
158 GridResolvedPosition GridResolvedPosition::resolveGridPositionFromStyle(const Co
mputedStyle& gridContainerStyle, const GridPosition& position, GridPositionSide
side) | |
159 { | |
160 switch (position.type()) { | |
161 case ExplicitPosition: { | |
162 ASSERT(position.integerPosition()); | |
163 | |
164 if (!position.namedGridLine().isNull()) | |
165 return resolveNamedGridLinePositionFromStyle(gridContainerStyle, pos
ition, side); | |
166 | |
167 // Handle <integer> explicit position. | |
168 if (position.isPositive()) | |
169 return adjustGridPositionForSide(position.integerPosition() - 1, sid
e); | |
170 | |
171 size_t resolvedPosition = abs(position.integerPosition()) - 1; | |
172 const size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, si
de); | |
173 | |
174 // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html,
we clamp negative value to the first line. | |
175 if (endOfTrack < resolvedPosition) | |
176 return GridResolvedPosition(0); | |
177 | |
178 return adjustGridPositionForSide(endOfTrack - resolvedPosition, side); | |
179 } | |
180 case NamedGridAreaPosition: | |
181 { | |
182 // First attempt to match the grid area's edge to a named grid area: if
there is a named line with the name | |
183 // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for
grid-*-end), contributes the first such | |
184 // line to the grid item's placement. | |
185 String namedGridLine = position.namedGridLine(); | |
186 ASSERT(isValidNamedLineOrArea(namedGridLine, gridContainerStyle, side)); | |
187 | |
188 const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerS
tyle, side); | |
189 NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find(
implicitNamedGridLineForSide(namedGridLine, side)); | |
190 if (implicitLineIter != gridLineNames.end()) | |
191 return adjustGridPositionForSide(implicitLineIter->value[0], side); | |
192 | |
193 // Otherwise, if there is a named line with the specified name, contribu
tes the first such line to the grid | |
194 // item's placement. | |
195 NamedGridLinesMap::const_iterator explicitLineIter = gridLineNames.find(
namedGridLine); | |
196 if (explicitLineIter != gridLineNames.end()) | |
197 return adjustGridPositionForSide(explicitLineIter->value[0], side); | |
198 | |
199 // If none of the above works specs mandate us to treat it as auto BUT w
e should have detected it before calling | |
200 // this function in GridResolvedPosition::resolveGridPositionsFromStyle(
). We should be also covered by the | |
201 // ASSERT at the beginning of this block. | |
202 ASSERT_NOT_REACHED(); | |
203 return GridResolvedPosition(0); | |
204 } | |
205 case AutoPosition: | |
206 case SpanPosition: | |
207 // 'auto' and span depend on the opposite position for resolution (e.g.
grid-row: auto / 1 or grid-column: span 3 / "myHeader"). | |
208 ASSERT_NOT_REACHED(); | |
209 return GridResolvedPosition(0); | |
210 } | |
211 ASSERT_NOT_REACHED(); | |
212 return GridResolvedPosition(0); | |
213 } | |
214 | |
215 PassOwnPtr<GridSpan> GridResolvedPosition::resolveGridPositionAgainstOppositePos
ition(const ComputedStyle& gridContainerStyle, const GridResolvedPosition& resol
vedOppositePosition, const GridPosition& position, GridPositionSide side) | |
216 { | |
217 if (position.isAuto()) | |
218 return GridSpan::create(resolvedOppositePosition, resolvedOppositePositi
on); | |
219 | |
220 ASSERT(position.isSpan()); | |
221 ASSERT(position.spanPosition() > 0); | |
222 | |
223 if (!position.namedGridLine().isNull()) { | |
224 // span 2 'c' -> we need to find the appropriate grid line before / afte
r our opposite position. | |
225 return resolveNamedGridLinePositionAgainstOppositePosition(gridContainer
Style, resolvedOppositePosition, position, side); | |
226 } | |
227 | |
228 return GridSpan::createWithSpanAgainstOpposite(resolvedOppositePosition, pos
ition, side); | |
229 } | |
230 | |
231 PassOwnPtr<GridSpan> GridResolvedPosition::resolveNamedGridLinePositionAgainstOp
positePosition(const ComputedStyle& gridContainerStyle, const GridResolvedPositi
on& resolvedOppositePosition, const GridPosition& position, GridPositionSide sid
e) | |
232 { | |
233 ASSERT(position.isSpan()); | |
234 ASSERT(!position.namedGridLine().isNull()); | |
235 // Negative positions are not allowed per the specification and should have
been handled during parsing. | |
236 ASSERT(position.spanPosition() > 0); | |
237 | |
238 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl
e, side); | |
239 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri
dLine()); | |
240 | |
241 // 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). | |
242 // See http://lists.w3.org/Archives/Public/www-style/2013Jun/0394.html. | |
243 if (it == gridLinesNames.end()) | |
244 return GridSpan::create(resolvedOppositePosition, resolvedOppositePositi
on); | |
245 | |
246 return GridSpan::createWithNamedSpanAgainstOpposite(resolvedOppositePosition
, position, side, it->value); | |
247 } | |
248 | |
249 } // namespace blink | |
OLD | NEW |