Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: third_party/WebKit/Source/core/style/GridResolvedPosition.cpp

Issue 1648903002: [css-grid] Rename GridResolvedPosition to GridPositionsResolver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/style/GridResolvedPosition.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "core/style/GridResolvedPosition.h"
6
7 #include "core/layout/LayoutBox.h"
8 #include "core/style/GridCoordinate.h"
9 #include <algorithm>
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 bool GridResolvedPosition::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 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 static void initialAndFinalPositionsFromStyle(const ComputedStyle& gridContainer Style, const LayoutBox& gridItem, GridTrackSizingDirection direction, GridPositi on& 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
45 // 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.
47 if (initialPosition.isSpan() && finalPosition.isSpan())
48 finalPosition.setAutoPosition();
49
50 if (gridItem.isOutOfFlowPositioned()) {
51 // Early detect the case of non existing named grid lines for positioned items.
52 if (initialPosition.isNamedGridArea() && !GridResolvedPosition::isValidN amedLineOrArea(initialPosition.namedGridLine(), gridContainerStyle, GridResolved Position::initialPositionSide(direction)))
53 initialPosition.setAutoPosition();
54
55 if (finalPosition.isNamedGridArea() && !GridResolvedPosition::isValidNam edLineOrArea(finalPosition.namedGridLine(), gridContainerStyle, GridResolvedPosi tion::finalPositionSide(direction)))
56 finalPosition.setAutoPosition();
57 }
58
59 // 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.
60 if (initialPosition.isAuto() && finalPosition.isSpan() && !finalPosition.nam edGridLine().isNull())
61 finalPosition.setSpanPosition(1, String());
62 if (finalPosition.isAuto() && initialPosition.isSpan() && !initialPosition.n amedGridLine().isNull())
63 initialPosition.setSpanPosition(1, String());
64 }
65
66 static size_t lookAheadForNamedGridLine(int start, size_t numberOfLines, const V ector<size_t>* namedGridLinesIndexes, size_t gridLastLine)
67 {
68 ASSERT(numberOfLines);
69
70 // Only implicit lines on the search direction are assumed to have the given name, so we can start to look from first line.
71 // See: https://drafts.csswg.org/css-grid/#grid-placement-span-int
72 size_t end = std::max(start, 0);
73
74 if (!namedGridLinesIndexes) {
75 end = std::max(end, gridLastLine + 1);
76 return end + numberOfLines - 1;
77 }
78
79 for (; numberOfLines; ++end) {
80 if (end > gridLastLine || namedGridLinesIndexes->contains(end))
81 numberOfLines--;
82 }
83
84 ASSERT(end);
85 return end - 1;
86 }
87
88 static int lookBackForNamedGridLine(int end, size_t numberOfLines, const Vector< size_t>* namedGridLinesIndexes, int gridLastLine)
89 {
90 ASSERT(numberOfLines);
91
92 // Only implicit lines on the search direction are assumed to have the given name, so we can start to look from last line.
93 // See: https://drafts.csswg.org/css-grid/#grid-placement-span-int
94 int start = std::min(end, gridLastLine);
95
96 if (!namedGridLinesIndexes) {
97 start = std::min(start, -1);
98 return start - numberOfLines + 1;
99 }
100
101 for (; numberOfLines; --start) {
102 if (start < 0 || namedGridLinesIndexes->contains(static_cast<size_t>(sta rt)))
103 numberOfLines--;
104 }
105
106 return start + 1;
107 }
108
109 static GridSpan definiteGridSpanWithNamedSpanAgainstOpposite(int resolvedOpposit ePosition, const GridPosition& position, GridPositionSide side, const Vector<siz e_t>* gridLines, int lastLine)
110 {
111 int start, end;
112
113 if (side == RowStartSide || side == ColumnStartSide) {
114 start = lookBackForNamedGridLine(resolvedOppositePosition - 1, position. spanPosition(), gridLines, lastLine);
115 end = resolvedOppositePosition;
116 } else {
117 start = resolvedOppositePosition;
118 end = lookAheadForNamedGridLine(resolvedOppositePosition + 1, position.s panPosition(), gridLines, lastLine);
119 }
120
121 return GridSpan::untranslatedDefiniteGridSpan(start, end);
122 }
123
124 size_t GridResolvedPosition::explicitGridColumnCount(const ComputedStyle& gridCo ntainerStyle)
125 {
126 return std::min<size_t>(gridContainerStyle.gridTemplateColumns().size(), kGr idMaxTracks);
127 }
128
129 size_t GridResolvedPosition::explicitGridRowCount(const ComputedStyle& gridConta inerStyle)
130 {
131 return std::min<size_t>(gridContainerStyle.gridTemplateRows().size(), kGridM axTracks);
132 }
133
134 static size_t explicitGridSizeForSide(const ComputedStyle& gridContainerStyle, G ridPositionSide side)
135 {
136 return (side == ColumnStartSide || side == ColumnEndSide) ? GridResolvedPosi tion::explicitGridColumnCount(gridContainerStyle) : GridResolvedPosition::explic itGridRowCount(gridContainerStyle);
137 }
138
139 static GridSpan resolveNamedGridLinePositionAgainstOppositePosition(const Comput edStyle& gridContainerStyle, int resolvedOppositePosition, const GridPosition& p osition, GridPositionSide side)
140 {
141 ASSERT(position.isSpan());
142 ASSERT(!position.namedGridLine().isNull());
143 // Negative positions are not allowed per the specification and should have been handled during parsing.
144 ASSERT(position.spanPosition() > 0);
145
146 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl e, side);
147 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri dLine());
148 const Vector<size_t>* gridLines = it == gridLinesNames.end() ? nullptr : &it ->value;
149 size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side);
150 return definiteGridSpanWithNamedSpanAgainstOpposite(resolvedOppositePosition , position, side, gridLines, lastLine);
151 }
152
153 static GridSpan definiteGridSpanWithSpanAgainstOpposite(size_t resolvedOppositeP osition, const GridPosition& position, GridPositionSide side)
154 {
155 size_t positionOffset = position.spanPosition();
156 if (side == ColumnStartSide || side == RowStartSide)
157 return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition - positionOffset, resolvedOppositePosition);
158
159 return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition, reso lvedOppositePosition + positionOffset);
160 }
161
162 static GridSpan resolveGridPositionAgainstOppositePosition(const ComputedStyle& gridContainerStyle, int resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
163 {
164 if (position.isAuto()) {
165 if (side == ColumnStartSide || side == RowStartSide)
166 return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePositi on - 1, resolvedOppositePosition);
167 return GridSpan::untranslatedDefiniteGridSpan(resolvedOppositePosition, resolvedOppositePosition + 1);
168 }
169
170 ASSERT(position.isSpan());
171 ASSERT(position.spanPosition() > 0);
172
173 if (!position.namedGridLine().isNull()) {
174 // span 2 'c' -> we need to find the appropriate grid line before / afte r our opposite position.
175 return resolveNamedGridLinePositionAgainstOppositePosition(gridContainer Style, resolvedOppositePosition, position, side);
176 }
177
178 return definiteGridSpanWithSpanAgainstOpposite(resolvedOppositePosition, pos ition, side);
179 }
180
181 size_t GridResolvedPosition::spanSizeForAutoPlacedItem(const ComputedStyle& grid ContainerStyle, const LayoutBox& gridItem, GridTrackSizingDirection direction)
182 {
183 GridPosition initialPosition, finalPosition;
184 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i nitialPosition, finalPosition);
185
186 // This method will only be used when both positions need to be resolved aga inst the opposite one.
187 ASSERT(initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPos ition.shouldBeResolvedAgainstOppositePosition());
188
189 if (initialPosition.isAuto() && finalPosition.isAuto())
190 return 1;
191
192 GridPosition position = initialPosition.isSpan() ? initialPosition : finalPo sition;
193 ASSERT(position.isSpan());
194 ASSERT(position.spanPosition());
195 return position.spanPosition();
196 }
197
198 static int resolveNamedGridLinePositionFromStyle(const ComputedStyle& gridContai nerStyle, const GridPosition& position, GridPositionSide side)
199 {
200 ASSERT(!position.namedGridLine().isNull());
201
202 const NamedGridLinesMap& gridLinesNames = gridLinesForSide(gridContainerStyl e, side);
203 NamedGridLinesMap::const_iterator it = gridLinesNames.find(position.namedGri dLine());
204 const Vector<size_t>* gridLines = it == gridLinesNames.end() ? nullptr : &it ->value;
205 size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side);
206 if (position.isPositive())
207 return lookAheadForNamedGridLine(0, abs(position.integerPosition()), gri dLines, lastLine);
208 else
209 return lookBackForNamedGridLine(lastLine, abs(position.integerPosition() ), gridLines, lastLine);
210 }
211
212 static int resolveGridPositionFromStyle(const ComputedStyle& gridContainerStyle, const GridPosition& position, GridPositionSide side)
213 {
214 switch (position.type()) {
215 case ExplicitPosition: {
216 ASSERT(position.integerPosition());
217
218 if (!position.namedGridLine().isNull())
219 return resolveNamedGridLinePositionFromStyle(gridContainerStyle, pos ition, side);
220
221 // Handle <integer> explicit position.
222 if (position.isPositive())
223 return position.integerPosition() - 1;
224
225 size_t resolvedPosition = abs(position.integerPosition()) - 1;
226 size_t endOfTrack = explicitGridSizeForSide(gridContainerStyle, side);
227
228 return endOfTrack - resolvedPosition;
229 }
230 case NamedGridAreaPosition:
231 {
232 // First attempt to match the grid area's edge to a named grid area: if there is a named line with the name
233 // ''<custom-ident>-start (for grid-*-start) / <custom-ident>-end'' (for grid-*-end), contributes the first such
234 // line to the grid item's placement.
235 String namedGridLine = position.namedGridLine();
236 ASSERT(!position.namedGridLine().isNull());
237
238 const NamedGridLinesMap& gridLineNames = gridLinesForSide(gridContainerS tyle, side);
239 NamedGridLinesMap::const_iterator implicitLineIter = gridLineNames.find( implicitNamedGridLineForSide(namedGridLine, side));
240 if (implicitLineIter != gridLineNames.end())
241 return implicitLineIter->value[0];
242
243 // Otherwise, if there is a named line with the specified name, contribu tes the first such line to the grid
244 // item's placement.
245 NamedGridLinesMap::const_iterator explicitLineIter = gridLineNames.find( namedGridLine);
246 if (explicitLineIter != gridLineNames.end())
247 return explicitLineIter->value[0];
248
249 ASSERT(!GridResolvedPosition::isValidNamedLineOrArea(namedGridLine, grid ContainerStyle, side));
250 // If none of the above works specs mandate to assume that all the lines in the implicit grid have this name.
251 size_t lastLine = explicitGridSizeForSide(gridContainerStyle, side);
252 return lastLine + 1;
253 }
254 case AutoPosition:
255 case SpanPosition:
256 // 'auto' and span depend on the opposite position for resolution (e.g. grid-row: auto / 1 or grid-column: span 3 / "myHeader").
257 ASSERT_NOT_REACHED();
258 return 0;
259 }
260 ASSERT_NOT_REACHED();
261 return 0;
262 }
263
264 GridSpan GridResolvedPosition::resolveGridPositionsFromStyle(const ComputedStyle & gridContainerStyle, const LayoutBox& gridItem, GridTrackSizingDirection direct ion)
265 {
266 GridPosition initialPosition, finalPosition;
267 initialAndFinalPositionsFromStyle(gridContainerStyle, gridItem, direction, i nitialPosition, finalPosition);
268
269 GridPositionSide initialSide = initialPositionSide(direction);
270 GridPositionSide finalSide = finalPositionSide(direction);
271
272 if (initialPosition.shouldBeResolvedAgainstOppositePosition() && finalPositi on.shouldBeResolvedAgainstOppositePosition()) {
273 // We can't get our grid positions without running the auto placement al gorithm.
274 return GridSpan::indefiniteGridSpan();
275 }
276
277 if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
278 // Infer the position from the final position ('auto / 1' or 'span 2 / 3 ' case).
279 int finalResolvedPosition = resolveGridPositionFromStyle(gridContainerSt yle, finalPosition, finalSide);
280 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, fi nalResolvedPosition, initialPosition, initialSide);
281 }
282
283 if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
284 // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
285 int initialResolvedPosition = resolveGridPositionFromStyle(gridContainer Style, initialPosition, initialSide);
286 return resolveGridPositionAgainstOppositePosition(gridContainerStyle, in itialResolvedPosition, finalPosition, finalSide);
287 }
288
289 int resolvedInitialPosition = resolveGridPositionFromStyle(gridContainerStyl e, initialPosition, initialSide);
290 int resolvedFinalPosition = resolveGridPositionFromStyle(gridContainerStyle, finalPosition, finalSide);
291
292 if (resolvedFinalPosition < resolvedInitialPosition)
293 std::swap(resolvedFinalPosition, resolvedInitialPosition);
294 else if (resolvedFinalPosition == resolvedInitialPosition)
295 resolvedFinalPosition = resolvedInitialPosition + 1;
296
297 return GridSpan::untranslatedDefiniteGridSpan(resolvedInitialPosition, resol vedFinalPosition);
298 }
299
300 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/style/GridResolvedPosition.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698