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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutGrid.cpp

Issue 2654533003: [css-grid] Move the track sizing algorithm to its own class (Closed)
Patch Set: Created 3 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 21 matching lines...) Expand all
32 #include "core/paint/PaintLayer.h" 32 #include "core/paint/PaintLayer.h"
33 #include "core/style/ComputedStyle.h" 33 #include "core/style/ComputedStyle.h"
34 #include "core/style/GridArea.h" 34 #include "core/style/GridArea.h"
35 #include "platform/LengthFunctions.h" 35 #include "platform/LengthFunctions.h"
36 #include "wtf/PtrUtil.h" 36 #include "wtf/PtrUtil.h"
37 #include <algorithm> 37 #include <algorithm>
38 #include <memory> 38 #include <memory>
39 39
40 namespace blink { 40 namespace blink {
41 41
42 static const int infinity = -1;
43
44 class GridItemWithSpan;
45
46 size_t LayoutGrid::Grid::numTracks(GridTrackSizingDirection direction) const {
47 if (direction == ForRows)
48 return m_grid.size();
49 return m_grid.size() ? m_grid[0].size() : 0;
50 }
51
52 void LayoutGrid::Grid::ensureGridSize(size_t maximumRowSize,
53 size_t maximumColumnSize) {
54 DCHECK(maximumRowSize <= kGridMaxTracks * 2);
55 DCHECK(maximumColumnSize <= kGridMaxTracks * 2);
56 const size_t oldRowSize = numTracks(ForRows);
57 if (maximumRowSize > oldRowSize) {
58 m_grid.grow(maximumRowSize);
59 for (size_t row = oldRowSize; row < numTracks(ForRows); ++row)
60 m_grid[row].grow(numTracks(ForColumns));
61 }
62
63 if (maximumColumnSize > numTracks(ForColumns)) {
64 for (size_t row = 0; row < numTracks(ForRows); ++row)
65 m_grid[row].grow(maximumColumnSize);
66 }
67 }
68
69 void LayoutGrid::Grid::insert(LayoutBox& child, const GridArea& area) {
70 DCHECK(area.rows.isTranslatedDefinite() &&
71 area.columns.isTranslatedDefinite());
72 ensureGridSize(area.rows.endLine(), area.columns.endLine());
73
74 for (const auto& row : area.rows) {
75 for (const auto& column : area.columns)
76 m_grid[row][column].push_back(&child);
77 }
78
79 setGridItemArea(child, area);
80 }
81
82 void LayoutGrid::Grid::setSmallestTracksStart(int rowStart, int columnStart) {
83 m_smallestRowStart = rowStart;
84 m_smallestColumnStart = columnStart;
85 }
86
87 int LayoutGrid::Grid::smallestTrackStart(
88 GridTrackSizingDirection direction) const {
89 return direction == ForRows ? m_smallestRowStart : m_smallestColumnStart;
90 }
91
92 GridArea LayoutGrid::Grid::gridItemArea(const LayoutBox& item) const {
93 DCHECK(m_gridItemArea.contains(&item));
94 return m_gridItemArea.get(&item);
95 }
96
97 void LayoutGrid::Grid::setGridItemArea(const LayoutBox& item, GridArea area) {
98 m_gridItemArea.set(&item, area);
99 }
100
101 size_t LayoutGrid::Grid::gridItemPaintOrder(const LayoutBox& item) const {
102 return m_gridItemsIndexesMap.get(&item);
103 }
104
105 void LayoutGrid::Grid::setGridItemPaintOrder(const LayoutBox& item,
106 size_t order) {
107 m_gridItemsIndexesMap.set(&item, order);
108 }
109
110 #if DCHECK_IS_ON()
111 bool LayoutGrid::Grid::hasAnyGridItemPaintOrder() const {
112 return !m_gridItemsIndexesMap.isEmpty();
113 }
114 #endif
115
116 void LayoutGrid::Grid::setAutoRepeatTracks(size_t autoRepeatRows,
117 size_t autoRepeatColumns) {
118 m_autoRepeatRows = autoRepeatRows;
119 m_autoRepeatColumns = autoRepeatColumns;
120 }
121
122 size_t LayoutGrid::Grid::autoRepeatTracks(
123 GridTrackSizingDirection direction) const {
124 return direction == ForRows ? m_autoRepeatRows : m_autoRepeatColumns;
125 }
126
127 void LayoutGrid::Grid::setAutoRepeatEmptyColumns(
128 std::unique_ptr<OrderedTrackIndexSet> autoRepeatEmptyColumns) {
129 m_autoRepeatEmptyColumns = std::move(autoRepeatEmptyColumns);
130 }
131
132 void LayoutGrid::Grid::setAutoRepeatEmptyRows(
133 std::unique_ptr<OrderedTrackIndexSet> autoRepeatEmptyRows) {
134 m_autoRepeatEmptyRows = std::move(autoRepeatEmptyRows);
135 }
136
137 bool LayoutGrid::Grid::hasAutoRepeatEmptyTracks(
138 GridTrackSizingDirection direction) const {
139 return direction == ForColumns ? !!m_autoRepeatEmptyColumns
140 : !!m_autoRepeatEmptyRows;
141 }
142
143 bool LayoutGrid::Grid::isEmptyAutoRepeatTrack(
144 GridTrackSizingDirection direction,
145 size_t line) const {
146 DCHECK(hasAutoRepeatEmptyTracks(direction));
147 return autoRepeatEmptyTracks(direction)->contains(line);
148 }
149
150 LayoutGrid::OrderedTrackIndexSet* LayoutGrid::Grid::autoRepeatEmptyTracks(
151 GridTrackSizingDirection direction) const {
152 DCHECK(hasAutoRepeatEmptyTracks(direction));
153 return direction == ForColumns ? m_autoRepeatEmptyColumns.get()
154 : m_autoRepeatEmptyRows.get();
155 }
156
157 GridSpan LayoutGrid::Grid::gridItemSpan(
158 const LayoutBox& gridItem,
159 GridTrackSizingDirection direction) const {
160 GridArea area = gridItemArea(gridItem);
161 return direction == ForColumns ? area.columns : area.rows;
162 }
163
164 void LayoutGrid::Grid::setHasAnyOrthogonalGridItem(
165 bool hasAnyOrthogonalGridItem) {
166 m_hasAnyOrthogonalGridItem = hasAnyOrthogonalGridItem;
167 }
168
169 void LayoutGrid::Grid::setNeedsItemsPlacement(bool needsItemsPlacement) {
170 m_needsItemsPlacement = needsItemsPlacement;
171
172 if (!needsItemsPlacement) {
173 m_grid.shrinkToFit();
174 return;
175 }
176
177 m_grid.resize(0);
178 m_gridItemArea.clear();
179 m_gridItemsIndexesMap.clear();
180 m_hasAnyOrthogonalGridItem = false;
181 m_smallestRowStart = 0;
182 m_smallestColumnStart = 0;
183 m_autoRepeatColumns = 0;
184 m_autoRepeatRows = 0;
185 m_autoRepeatEmptyColumns = nullptr;
186 m_autoRepeatEmptyRows = nullptr;
187 }
188
189 class GridTrack {
190 public:
191 GridTrack() : m_infinitelyGrowable(false) {}
192
193 LayoutUnit baseSize() const {
194 DCHECK(isGrowthLimitBiggerThanBaseSize());
195 return m_baseSize;
196 }
197
198 LayoutUnit growthLimit() const {
199 DCHECK(isGrowthLimitBiggerThanBaseSize());
200 DCHECK(!m_growthLimitCap || m_growthLimitCap.value() >= m_growthLimit ||
201 m_baseSize >= m_growthLimitCap.value());
202 return m_growthLimit;
203 }
204
205 void setBaseSize(LayoutUnit baseSize) {
206 m_baseSize = baseSize;
207 ensureGrowthLimitIsBiggerThanBaseSize();
208 }
209
210 void setGrowthLimit(LayoutUnit growthLimit) {
211 m_growthLimit =
212 growthLimit == infinity
213 ? growthLimit
214 : std::min(growthLimit, m_growthLimitCap.value_or(growthLimit));
215 ensureGrowthLimitIsBiggerThanBaseSize();
216 }
217
218 bool infiniteGrowthPotential() const {
219 return growthLimitIsInfinite() || m_infinitelyGrowable;
220 }
221
222 LayoutUnit plannedSize() const { return m_plannedSize; }
223
224 void setPlannedSize(const LayoutUnit& plannedSize) {
225 ASSERT(plannedSize >= 0 || plannedSize == infinity);
226 m_plannedSize = plannedSize;
227 }
228
229 LayoutUnit sizeDuringDistribution() const { return m_sizeDuringDistribution; }
230
231 void setSizeDuringDistribution(const LayoutUnit& sizeDuringDistribution) {
232 DCHECK_GE(sizeDuringDistribution, 0);
233 DCHECK(growthLimitIsInfinite() || growthLimit() >= sizeDuringDistribution);
234 m_sizeDuringDistribution = sizeDuringDistribution;
235 }
236
237 void growSizeDuringDistribution(const LayoutUnit& sizeDuringDistribution) {
238 DCHECK_GE(sizeDuringDistribution, 0);
239 m_sizeDuringDistribution += sizeDuringDistribution;
240 }
241
242 bool infinitelyGrowable() const { return m_infinitelyGrowable; }
243 void setInfinitelyGrowable(bool infinitelyGrowable) {
244 m_infinitelyGrowable = infinitelyGrowable;
245 }
246
247 void setGrowthLimitCap(Optional<LayoutUnit> growthLimitCap) {
248 DCHECK(!growthLimitCap || *growthLimitCap >= 0);
249 m_growthLimitCap = growthLimitCap;
250 }
251
252 Optional<LayoutUnit> growthLimitCap() const { return m_growthLimitCap; }
253
254 private:
255 bool growthLimitIsInfinite() const { return m_growthLimit == infinity; }
256 bool isGrowthLimitBiggerThanBaseSize() const {
257 return growthLimitIsInfinite() || m_growthLimit >= m_baseSize;
258 }
259
260 void ensureGrowthLimitIsBiggerThanBaseSize() {
261 if (m_growthLimit != infinity && m_growthLimit < m_baseSize)
262 m_growthLimit = m_baseSize;
263 }
264
265 LayoutUnit m_baseSize;
266 LayoutUnit m_growthLimit;
267 LayoutUnit m_plannedSize;
268 LayoutUnit m_sizeDuringDistribution;
269 Optional<LayoutUnit> m_growthLimitCap;
270 bool m_infinitelyGrowable;
271 };
272
273 struct ContentAlignmentData { 42 struct ContentAlignmentData {
274 STACK_ALLOCATED(); 43 STACK_ALLOCATED();
275 44
276 public: 45 public:
277 ContentAlignmentData(){}; 46 ContentAlignmentData(){};
278 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) 47 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution)
279 : positionOffset(position), distributionOffset(distribution) {} 48 : positionOffset(position), distributionOffset(distribution) {}
280 49
281 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } 50 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; }
282 51
283 LayoutUnit positionOffset = LayoutUnit(-1); 52 LayoutUnit positionOffset = LayoutUnit(-1);
284 LayoutUnit distributionOffset = LayoutUnit(-1); 53 LayoutUnit distributionOffset = LayoutUnit(-1);
285 }; 54 };
286 55
287 enum TrackSizeRestriction { 56 enum TrackSizeRestriction {
288 AllowInfinity, 57 AllowInfinity,
289 ForbidInfinity, 58 ForbidInfinity,
290 }; 59 };
291 60
292 class LayoutGrid::GridIterator { 61 LayoutGrid::LayoutGrid(Element* element)
293 WTF_MAKE_NONCOPYABLE(GridIterator); 62 : LayoutBlock(element), m_grid(this), m_trackSizingAlgorithm(this, m_grid) {
294
295 public:
296 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
297 // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd
298 // column.
299 GridIterator(const Grid& grid,
300 GridTrackSizingDirection direction,
301 size_t fixedTrackIndex,
302 size_t varyingTrackIndex = 0)
303 : m_grid(grid.m_grid),
304 m_direction(direction),
305 m_rowIndex((direction == ForColumns) ? varyingTrackIndex
306 : fixedTrackIndex),
307 m_columnIndex((direction == ForColumns) ? fixedTrackIndex
308 : varyingTrackIndex),
309 m_childIndex(0) {
310 DCHECK(!m_grid.isEmpty());
311 DCHECK(!m_grid[0].isEmpty());
312 DCHECK(m_rowIndex < m_grid.size());
313 DCHECK(m_columnIndex < m_grid[0].size());
314 }
315
316 LayoutBox* nextGridItem() {
317 DCHECK(!m_grid.isEmpty());
318 DCHECK(!m_grid[0].isEmpty());
319
320 size_t& varyingTrackIndex =
321 (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
322 const size_t endOfVaryingTrackIndex =
323 (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
324 for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
325 const GridCell& children = m_grid[m_rowIndex][m_columnIndex];
326 if (m_childIndex < children.size())
327 return children[m_childIndex++];
328
329 m_childIndex = 0;
330 }
331 return nullptr;
332 }
333
334 bool checkEmptyCells(size_t rowSpan, size_t columnSpan) const {
335 DCHECK(!m_grid.isEmpty());
336 DCHECK(!m_grid[0].isEmpty());
337
338 // Ignore cells outside current grid as we will grow it later if needed.
339 size_t maxRows = std::min(m_rowIndex + rowSpan, m_grid.size());
340 size_t maxColumns = std::min(m_columnIndex + columnSpan, m_grid[0].size());
341
342 // This adds a O(N^2) behavior that shouldn't be a big deal as we expect
343 // spanning areas to be small.
344 for (size_t row = m_rowIndex; row < maxRows; ++row) {
345 for (size_t column = m_columnIndex; column < maxColumns; ++column) {
346 const GridCell& children = m_grid[row][column];
347 if (!children.isEmpty())
348 return false;
349 }
350 }
351
352 return true;
353 }
354
355 std::unique_ptr<GridArea> nextEmptyGridArea(size_t fixedTrackSpan,
356 size_t varyingTrackSpan) {
357 DCHECK(!m_grid.isEmpty());
358 DCHECK(!m_grid[0].isEmpty());
359 ASSERT(fixedTrackSpan >= 1 && varyingTrackSpan >= 1);
360
361 size_t rowSpan =
362 (m_direction == ForColumns) ? varyingTrackSpan : fixedTrackSpan;
363 size_t columnSpan =
364 (m_direction == ForColumns) ? fixedTrackSpan : varyingTrackSpan;
365
366 size_t& varyingTrackIndex =
367 (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
368 const size_t endOfVaryingTrackIndex =
369 (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
370 for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
371 if (checkEmptyCells(rowSpan, columnSpan)) {
372 std::unique_ptr<GridArea> result = WTF::wrapUnique(
373 new GridArea(GridSpan::translatedDefiniteGridSpan(
374 m_rowIndex, m_rowIndex + rowSpan),
375 GridSpan::translatedDefiniteGridSpan(
376 m_columnIndex, m_columnIndex + columnSpan)));
377 // Advance the iterator to avoid an infinite loop where we would return
378 // the same grid area over and over.
379 ++varyingTrackIndex;
380 return result;
381 }
382 }
383 return nullptr;
384 }
385
386 private:
387 const GridAsMatrix& m_grid;
388 GridTrackSizingDirection m_direction;
389 size_t m_rowIndex;
390 size_t m_columnIndex;
391 size_t m_childIndex;
392 };
393
394 struct LayoutGrid::GridSizingData {
395 WTF_MAKE_NONCOPYABLE(GridSizingData);
396 STACK_ALLOCATED();
397
398 public:
399 GridSizingData(size_t gridColumnCount, size_t gridRowCount, Grid& grid)
400 : columnTracks(gridColumnCount), rowTracks(gridRowCount), m_grid(grid) {}
401
402 Vector<GridTrack> columnTracks;
403 Vector<GridTrack> rowTracks;
404 Vector<size_t> contentSizedTracksIndex;
405
406 // Performance optimization: hold onto these Vectors until the end of Layout
407 // to avoid repeated malloc / free.
408 Vector<GridTrack*> filteredTracks;
409 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan;
410 Vector<GridTrack*> growBeyondGrowthLimitsTracks;
411
412 LayoutUnit& freeSpace(GridTrackSizingDirection direction) {
413 return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows;
414 }
415
416 LayoutUnit availableSpace() const { return m_availableSpace; }
417 void setAvailableSpace(LayoutUnit availableSpace) {
418 m_availableSpace = availableSpace;
419 }
420
421 SizingOperation sizingOperation{TrackSizing};
422 enum SizingState {
423 ColumnSizingFirstIteration,
424 RowSizingFirstIteration,
425 ColumnSizingSecondIteration,
426 RowSizingSecondIteration
427 };
428 SizingState sizingState{ColumnSizingFirstIteration};
429 void nextState() {
430 switch (sizingState) {
431 case ColumnSizingFirstIteration:
432 sizingState = RowSizingFirstIteration;
433 return;
434 case RowSizingFirstIteration:
435 sizingState = ColumnSizingSecondIteration;
436 return;
437 case ColumnSizingSecondIteration:
438 sizingState = RowSizingSecondIteration;
439 return;
440 case RowSizingSecondIteration:
441 sizingState = ColumnSizingFirstIteration;
442 return;
443 }
444 NOTREACHED();
445 sizingState = ColumnSizingFirstIteration;
446 }
447 bool isValidTransition(GridTrackSizingDirection direction) const {
448 switch (sizingState) {
449 case ColumnSizingFirstIteration:
450 case ColumnSizingSecondIteration:
451 return direction == ForColumns;
452 case RowSizingFirstIteration:
453 case RowSizingSecondIteration:
454 return direction == ForRows;
455 }
456 NOTREACHED();
457 return false;
458 }
459
460 Grid& grid() const { return m_grid; }
461
462 private:
463 LayoutUnit freeSpaceForColumns{};
464 LayoutUnit freeSpaceForRows{};
465 // No need to store one per direction as it will be only used for computations
466 // during each axis track sizing. It's cached here because we need it to
467 // compute relative sizes.
468 LayoutUnit m_availableSpace;
469
470 Grid& m_grid;
471 };
472
473 struct GridItemsSpanGroupRange {
474 Vector<GridItemWithSpan>::iterator rangeStart;
475 Vector<GridItemWithSpan>::iterator rangeEnd;
476 };
477
478 LayoutGrid::LayoutGrid(Element* element) : LayoutBlock(element), m_grid(this) {
479 ASSERT(!childrenInline()); 63 ASSERT(!childrenInline());
480 if (!isAnonymous()) 64 if (!isAnonymous())
481 UseCounter::count(document(), UseCounter::CSSGridLayout); 65 UseCounter::count(document(), UseCounter::CSSGridLayout);
482 } 66 }
483 67
484 LayoutGrid::~LayoutGrid() {} 68 LayoutGrid::~LayoutGrid() {}
485 69
486 LayoutGrid* LayoutGrid::createAnonymous(Document* document) { 70 LayoutGrid* LayoutGrid::createAnonymous(Document* document) {
487 LayoutGrid* layoutGrid = new LayoutGrid(nullptr); 71 LayoutGrid* layoutGrid = new LayoutGrid(nullptr);
488 layoutGrid->setDocumentForAnonymous(document); 72 layoutGrid->setDocumentForAnonymous(document);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 oldStyle.gridAutoRepeatRows().size() != 124 oldStyle.gridAutoRepeatRows().size() !=
541 styleRef().gridAutoRepeatRows().size(); 125 styleRef().gridAutoRepeatRows().size();
542 } 126 }
543 127
544 bool LayoutGrid::namedGridLinesDefinitionDidChange( 128 bool LayoutGrid::namedGridLinesDefinitionDidChange(
545 const ComputedStyle& oldStyle) const { 129 const ComputedStyle& oldStyle) const {
546 return oldStyle.namedGridRowLines() != styleRef().namedGridRowLines() || 130 return oldStyle.namedGridRowLines() != styleRef().namedGridRowLines() ||
547 oldStyle.namedGridColumnLines() != styleRef().namedGridColumnLines(); 131 oldStyle.namedGridColumnLines() != styleRef().namedGridColumnLines();
548 } 132 }
549 133
550 LayoutUnit LayoutGrid::computeTrackBasedLogicalHeight( 134 LayoutUnit LayoutGrid::computeTrackBasedLogicalHeight() const {
551 const GridSizingData& sizingData) const {
552 LayoutUnit logicalHeight; 135 LayoutUnit logicalHeight;
553 136
554 for (const auto& row : sizingData.rowTracks) 137 const Vector<GridTrack>& allRows = m_trackSizingAlgorithm.tracks(ForRows);
138 for (const auto& row : allRows)
555 logicalHeight += row.baseSize(); 139 logicalHeight += row.baseSize();
556 140
557 logicalHeight += 141 logicalHeight += guttersSize(m_grid, ForRows, 0, allRows.size(), TrackSizing);
558 guttersSize(sizingData.grid(), ForRows, 0, sizingData.rowTracks.size(),
559 sizingData.sizingOperation);
560 142
561 return logicalHeight; 143 return logicalHeight;
562 } 144 }
563 145
564 void LayoutGrid::computeTrackSizesForDefiniteSize( 146 void LayoutGrid::computeTrackSizesForDefiniteSize(
565 GridTrackSizingDirection direction, 147 GridTrackSizingDirection direction,
566 GridSizingData& sizingData, 148 LayoutUnit availableSpace) {
567 LayoutUnit availableSpace) const { 149 // DCHECK(sizingData.isValidTransition(direction));
568 DCHECK(sizingData.isValidTransition(direction));
569 sizingData.setAvailableSpace(availableSpace);
570 sizingData.freeSpace(direction) =
571 availableSpace - guttersSize(sizingData.grid(), direction, 0,
572 sizingData.grid().numTracks(direction),
573 sizingData.sizingOperation);
574 sizingData.sizingOperation = TrackSizing;
575 150
576 LayoutUnit baseSizes, growthLimits; 151 LayoutUnit freeSpace =
577 computeUsedBreadthOfGridTracks(direction, sizingData, baseSizes, 152 availableSpace - guttersSize(m_grid, direction, 0,
578 growthLimits); 153 m_grid.numTracks(direction), TrackSizing);
579 ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData)); 154 m_trackSizingAlgorithm.setup(direction, numTracks(direction, m_grid),
580 sizingData.nextState(); 155 TrackSizing, availableSpace, freeSpace);
156 m_trackSizingAlgorithm.run();
157
158 DCHECK(m_trackSizingAlgorithm.tracksAreWiderThanMinTrackBreadth());
159 // sizingData.nextState();
Manuel Rego 2017/01/30 11:00:46 Mmmm, what's this?
svillar 2017/01/30 11:28:29 Oh I forgot to remove those. The states are now ha
581 } 160 }
582 161
583 void LayoutGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, 162 void LayoutGrid::repeatTracksSizingIfNeeded(LayoutUnit availableSpaceForColumns,
584 LayoutUnit availableSpaceForColumns,
585 LayoutUnit availableSpaceForRows) { 163 LayoutUnit availableSpaceForRows) {
586 DCHECK(sizingData.sizingState > GridSizingData::RowSizingFirstIteration); 164 // DCHECK(sizingData.sizingState > GridSizingData::RowSizingFirstIteration);
Manuel Rego 2017/01/30 11:00:46 And this?
svillar 2017/01/30 11:28:29 Yeah good catch. I forgot to remove them.
587 165
588 // In orthogonal flow cases column track's size is determined by using the 166 // In orthogonal flow cases column track's size is determined by using the
589 // computed row track's size, which it was estimated during the first cycle of 167 // computed row track's size, which it was estimated during the first cycle of
590 // the sizing algorithm. 168 // the sizing algorithm.
591 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns 169 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns
592 // and rows, to determine the final values. 170 // and rows, to determine the final values.
593 // TODO (lajava): orthogonal flows is just one of the cases which may require 171 // TODO (lajava): orthogonal flows is just one of the cases which may require
594 // a new cycle of the sizing algorithm; there may be more. In addition, not 172 // a new cycle of the sizing algorithm; there may be more. In addition, not
595 // all the cases with orthogonal flows require this extra cycle; we need a 173 // all the cases with orthogonal flows require this extra cycle; we need a
596 // more specific condition to detect whether child's min-content contribution 174 // more specific condition to detect whether child's min-content contribution
597 // has changed or not. 175 // has changed or not.
598 if (sizingData.grid().hasAnyOrthogonalGridItem()) { 176 if (m_grid.hasAnyOrthogonalGridItem()) {
599 computeTrackSizesForDefiniteSize(ForColumns, sizingData, 177 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
600 availableSpaceForColumns); 178 computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows);
601 computeTrackSizesForDefiniteSize(ForRows, sizingData,
602 availableSpaceForRows);
603 } 179 }
604 } 180 }
605 181
606 void LayoutGrid::layoutBlock(bool relayoutChildren) { 182 void LayoutGrid::layoutBlock(bool relayoutChildren) {
607 ASSERT(needsLayout()); 183 ASSERT(needsLayout());
608 184
609 // We cannot perform a simplifiedLayout() on a dirty grid that 185 // We cannot perform a simplifiedLayout() on a dirty grid that
610 // has positioned items to be laid out. 186 // has positioned items to be laid out.
611 if (!relayoutChildren && 187 if (!relayoutChildren &&
612 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && 188 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) &&
(...skipping 24 matching lines...) Expand all
637 } 213 }
638 } 214 }
639 215
640 updateLogicalWidth(); 216 updateLogicalWidth();
641 m_hasDefiniteLogicalHeight = hasDefiniteLogicalHeight(); 217 m_hasDefiniteLogicalHeight = hasDefiniteLogicalHeight();
642 218
643 TextAutosizer::LayoutScope textAutosizerLayoutScope(this, &layoutScope); 219 TextAutosizer::LayoutScope textAutosizerLayoutScope(this, &layoutScope);
644 220
645 placeItemsOnGrid(m_grid, TrackSizing); 221 placeItemsOnGrid(m_grid, TrackSizing);
646 222
647 GridSizingData sizingData(numTracks(ForColumns, m_grid),
648 numTracks(ForRows, m_grid), m_grid);
649
650 // 1- First, the track sizing algorithm is used to resolve the sizes of the 223 // 1- First, the track sizing algorithm is used to resolve the sizes of the
651 // grid columns. 224 // grid columns.
652 // At this point the logical width is always definite as the above call to 225 // At this point the logical width is always definite as the above call to
653 // updateLogicalWidth() properly resolves intrinsic sizes. We cannot do the 226 // updateLogicalWidth() properly resolves intrinsic sizes. We cannot do the
654 // same for heights though because many code paths inside 227 // same for heights though because many code paths inside
655 // updateLogicalHeight() require a previous call to setLogicalHeight() to 228 // updateLogicalHeight() require a previous call to setLogicalHeight() to
656 // resolve heights properly (like for positioned items for example). 229 // resolve heights properly (like for positioned items for example).
657 LayoutUnit availableSpaceForColumns = availableLogicalWidth(); 230 LayoutUnit availableSpaceForColumns = availableLogicalWidth();
658 computeTrackSizesForDefiniteSize(ForColumns, sizingData, 231 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
659 availableSpaceForColumns);
660 232
661 // 2- Next, the track sizing algorithm resolves the sizes of the grid rows, 233 // 2- Next, the track sizing algorithm resolves the sizes of the grid rows,
662 // using the grid column sizes calculated in the previous step. 234 // using the grid column sizes calculated in the previous step.
663 if (cachedHasDefiniteLogicalHeight()) { 235 if (cachedHasDefiniteLogicalHeight()) {
664 computeTrackSizesForDefiniteSize( 236 computeTrackSizesForDefiniteSize(
665 ForRows, sizingData, 237 ForRows, availableLogicalHeight(ExcludeMarginBorderPadding));
666 availableLogicalHeight(ExcludeMarginBorderPadding));
667 } else { 238 } else {
668 computeTrackSizesForIndefiniteSize( 239 computeTrackSizesForIndefiniteSize(m_trackSizingAlgorithm, ForRows,
669 ForRows, sizingData, m_minContentHeight, m_maxContentHeight); 240 m_grid, m_minContentHeight,
670 sizingData.nextState(); 241 m_maxContentHeight);
671 sizingData.sizingOperation = TrackSizing;
672 } 242 }
673 LayoutUnit trackBasedLogicalHeight = 243 LayoutUnit trackBasedLogicalHeight = computeTrackBasedLogicalHeight() +
674 computeTrackBasedLogicalHeight(sizingData) + 244 borderAndPaddingLogicalHeight() +
675 borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(); 245 scrollbarLogicalHeight();
676 setLogicalHeight(trackBasedLogicalHeight); 246 setLogicalHeight(trackBasedLogicalHeight);
677 247
678 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); 248 LayoutUnit oldClientAfterEdge = clientLogicalBottom();
679 updateLogicalHeight(); 249 updateLogicalHeight();
680 250
681 // Once grid's indefinite height is resolved, we can compute the 251 // Once grid's indefinite height is resolved, we can compute the
682 // available free space for Content Alignment. 252 // available free space for Content Alignment.
683 if (!cachedHasDefiniteLogicalHeight()) 253 if (!cachedHasDefiniteLogicalHeight()) {
684 sizingData.freeSpace(ForRows) = logicalHeight() - trackBasedLogicalHeight; 254 m_trackSizingAlgorithm.freeSpace(ForRows) =
255 logicalHeight() - trackBasedLogicalHeight;
256 }
685 257
686 // 3- If the min-content contribution of any grid items have changed based 258 // 3- If the min-content contribution of any grid items have changed based
687 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with 259 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with
688 // the new min-content contribution (once only). 260 // the new min-content contribution (once only).
689 repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, 261 repeatTracksSizingIfNeeded(availableSpaceForColumns,
690 contentLogicalHeight()); 262 contentLogicalHeight());
691 263
692 // Grid container should have the minimum height of a line if it's editable. 264 // Grid container should have the minimum height of a line if it's editable.
693 // That doesn't affect track sizing though. 265 // That doesn't affect track sizing though.
694 if (hasLineIfEmpty()) 266 if (hasLineIfEmpty())
695 setLogicalHeight( 267 setLogicalHeight(
696 std::max(logicalHeight(), minimumLogicalHeightForEmptyLine())); 268 std::max(logicalHeight(), minimumLogicalHeightForEmptyLine()));
697 269
698 applyStretchAlignmentToTracksIfNeeded(ForColumns, sizingData); 270 applyStretchAlignmentToTracksIfNeeded(ForColumns);
699 applyStretchAlignmentToTracksIfNeeded(ForRows, sizingData); 271 applyStretchAlignmentToTracksIfNeeded(ForRows);
700 272
701 layoutGridItems(sizingData); 273 layoutGridItems();
274 m_trackSizingAlgorithm.reset();
702 275
703 if (size() != previousSize) 276 if (size() != previousSize)
704 relayoutChildren = true; 277 relayoutChildren = true;
705 278
706 layoutPositionedObjects(relayoutChildren || isDocumentElement()); 279 layoutPositionedObjects(relayoutChildren || isDocumentElement());
707 280
708 computeOverflow(oldClientAfterEdge); 281 computeOverflow(oldClientAfterEdge);
709 } 282 }
710 283
711 updateLayerTransformAfterLayout(); 284 updateLayerTransformAfterLayout();
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 371
799 return gapAccumulator; 372 return gapAccumulator;
800 } 373 }
801 374
802 void LayoutGrid::computeIntrinsicLogicalWidths( 375 void LayoutGrid::computeIntrinsicLogicalWidths(
803 LayoutUnit& minLogicalWidth, 376 LayoutUnit& minLogicalWidth,
804 LayoutUnit& maxLogicalWidth) const { 377 LayoutUnit& maxLogicalWidth) const {
805 Grid grid(this); 378 Grid grid(this);
806 placeItemsOnGrid(grid, IntrinsicSizeComputation); 379 placeItemsOnGrid(grid, IntrinsicSizeComputation);
807 380
808 GridSizingData sizingData(numTracks(ForColumns, grid), 381 GridTrackSizingAlgorithm algorithm(this, grid);
809 numTracks(ForRows, grid), grid); 382 computeTrackSizesForIndefiniteSize(algorithm, ForColumns, grid,
810 383 minLogicalWidth, maxLogicalWidth);
811 computeTrackSizesForIndefiniteSize(ForColumns, sizingData, minLogicalWidth,
812 maxLogicalWidth);
813 384
814 LayoutUnit scrollbarWidth = LayoutUnit(scrollbarLogicalWidth()); 385 LayoutUnit scrollbarWidth = LayoutUnit(scrollbarLogicalWidth());
815 minLogicalWidth += scrollbarWidth; 386 minLogicalWidth += scrollbarWidth;
816 maxLogicalWidth += scrollbarWidth; 387 maxLogicalWidth += scrollbarWidth;
817 } 388 }
818 389
819 void LayoutGrid::computeTrackSizesForIndefiniteSize( 390 void LayoutGrid::computeTrackSizesForIndefiniteSize(
391 GridTrackSizingAlgorithm& algo,
820 GridTrackSizingDirection direction, 392 GridTrackSizingDirection direction,
821 GridSizingData& sizingData, 393 Grid& grid,
822 LayoutUnit& minIntrinsicSize, 394 LayoutUnit& minIntrinsicSize,
823 LayoutUnit& maxIntrinsicSize) const { 395 LayoutUnit& maxIntrinsicSize) const {
824 DCHECK(sizingData.isValidTransition(direction)); 396 algo.setup(direction, numTracks(direction, grid), IntrinsicSizeComputation,
825 sizingData.setAvailableSpace(LayoutUnit()); 397 LayoutUnit(), LayoutUnit());
826 sizingData.freeSpace(direction) = LayoutUnit(); 398 algo.run();
827 sizingData.sizingOperation = IntrinsicSizeComputation;
828 399
829 computeUsedBreadthOfGridTracks(direction, sizingData, minIntrinsicSize, 400 minIntrinsicSize = algo.minContentSize();
830 maxIntrinsicSize); 401 maxIntrinsicSize = algo.maxContentSize();
831 402
832 size_t numberOfTracks = direction == ForColumns 403 size_t numberOfTracks = algo.tracks(direction).size();
833 ? sizingData.columnTracks.size()
834 : sizingData.rowTracks.size();
835 LayoutUnit totalGuttersSize = 404 LayoutUnit totalGuttersSize =
836 guttersSize(sizingData.grid(), direction, 0, numberOfTracks, 405 guttersSize(grid, direction, 0, numberOfTracks, IntrinsicSizeComputation);
837 sizingData.sizingOperation);
838 minIntrinsicSize += totalGuttersSize; 406 minIntrinsicSize += totalGuttersSize;
839 maxIntrinsicSize += totalGuttersSize; 407 maxIntrinsicSize += totalGuttersSize;
840 408
841 #if DCHECK_IS_ON() 409 #if DCHECK_IS_ON()
842 DCHECK(tracksAreWiderThanMinTrackBreadth(direction, sizingData)); 410 DCHECK(algo.tracksAreWiderThanMinTrackBreadth());
843 #endif 411 #endif
844 } 412 }
845 413
846 LayoutUnit LayoutGrid::computeIntrinsicLogicalContentHeightUsing( 414 LayoutUnit LayoutGrid::computeIntrinsicLogicalContentHeightUsing(
847 const Length& logicalHeightLength, 415 const Length& logicalHeightLength,
848 LayoutUnit intrinsicContentHeight, 416 LayoutUnit intrinsicContentHeight,
849 LayoutUnit borderAndPadding) const { 417 LayoutUnit borderAndPadding) const {
850 if (logicalHeightLength.isMinContent()) 418 if (logicalHeightLength.isMinContent())
851 return m_minContentHeight; 419 return m_minContentHeight;
852 420
(...skipping 10 matching lines...) Expand all
863 } 431 }
864 432
865 if (logicalHeightLength.isFillAvailable()) 433 if (logicalHeightLength.isFillAvailable())
866 return containingBlock()->availableLogicalHeight( 434 return containingBlock()->availableLogicalHeight(
867 ExcludeMarginBorderPadding) - 435 ExcludeMarginBorderPadding) -
868 borderAndPadding; 436 borderAndPadding;
869 ASSERT_NOT_REACHED(); 437 ASSERT_NOT_REACHED();
870 return LayoutUnit(); 438 return LayoutUnit();
871 } 439 }
872 440
873 static inline double normalizedFlexFraction(const GridTrack& track,
874 double flexFactor) {
875 return track.baseSize() / std::max<double>(1, flexFactor);
876 }
877
878 void LayoutGrid::computeUsedBreadthOfGridTracks(
879 GridTrackSizingDirection direction,
880 GridSizingData& sizingData,
881 LayoutUnit& baseSizesWithoutMaximization,
882 LayoutUnit& growthLimitsWithoutMaximization) const {
883 LayoutUnit& freeSpace = sizingData.freeSpace(direction);
884 const LayoutUnit initialFreeSpace = freeSpace;
885 Vector<GridTrack>& tracks = (direction == ForColumns)
886 ? sizingData.columnTracks
887 : sizingData.rowTracks;
888 Vector<size_t> flexibleSizedTracksIndex;
889 sizingData.contentSizedTracksIndex.shrink(0);
890
891 // Grid gutters were removed from freeSpace by the caller, but we must use
892 // them to compute relative (i.e. percentages) sizes.
893 LayoutUnit maxSize = sizingData.availableSpace().clampNegativeToZero();
894 bool hasDefiniteFreeSpace = sizingData.sizingOperation == TrackSizing;
895
896 // 1. Initialize per Grid track variables.
897 for (size_t i = 0; i < tracks.size(); ++i) {
898 GridTrack& track = tracks[i];
899 GridTrackSize trackSize = gridTrackSize(direction, i, sizingData);
900
901 track.setBaseSize(computeUsedBreadthOfMinLength(trackSize, maxSize));
902 track.setGrowthLimit(
903 computeUsedBreadthOfMaxLength(trackSize, track.baseSize(), maxSize));
904 track.setInfinitelyGrowable(false);
905
906 if (trackSize.isFitContent()) {
907 GridLength gridLength = trackSize.fitContentTrackBreadth();
908 if (!gridLength.hasPercentage() || hasDefiniteFreeSpace)
909 track.setGrowthLimitCap(valueForLength(gridLength.length(), maxSize));
910 }
911
912 if (trackSize.isContentSized())
913 sizingData.contentSizedTracksIndex.push_back(i);
914 if (trackSize.maxTrackBreadth().isFlex())
915 flexibleSizedTracksIndex.push_back(i);
916 }
917
918 // 2. Resolve content-based TrackSizingFunctions.
919 if (!sizingData.contentSizedTracksIndex.isEmpty())
920 resolveContentBasedTrackSizingFunctions(direction, sizingData);
921
922 baseSizesWithoutMaximization = growthLimitsWithoutMaximization = LayoutUnit();
923
924 for (auto& track : tracks) {
925 ASSERT(!track.infiniteGrowthPotential());
926 baseSizesWithoutMaximization += track.baseSize();
927 growthLimitsWithoutMaximization += track.growthLimit();
928 // The growth limit caps must be cleared now in order to properly sort
929 // tracks by growth potential on an eventual "Maximize Tracks".
930 track.setGrowthLimitCap(WTF::nullopt);
931 }
932 freeSpace = initialFreeSpace - baseSizesWithoutMaximization;
933
934 if (hasDefiniteFreeSpace && freeSpace <= 0)
935 return;
936
937 // 3. Grow all Grid tracks in GridTracks from their baseSize up to their
938 // growthLimit value until freeSpace is exhausted.
939 const size_t tracksSize = tracks.size();
940 if (hasDefiniteFreeSpace) {
941 Vector<GridTrack*> tracksForDistribution(tracksSize);
942 for (size_t i = 0; i < tracksSize; ++i) {
943 tracksForDistribution[i] = tracks.data() + i;
944 tracksForDistribution[i]->setPlannedSize(
945 tracksForDistribution[i]->baseSize());
946 }
947
948 distributeSpaceToTracks<MaximizeTracks>(tracksForDistribution, nullptr,
949 sizingData, freeSpace);
950
951 for (auto* track : tracksForDistribution)
952 track->setBaseSize(track->plannedSize());
953 } else {
954 for (auto& track : tracks)
955 track.setBaseSize(track.growthLimit());
956 }
957
958 if (flexibleSizedTracksIndex.isEmpty())
959 return;
960
961 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
962 double flexFraction = 0;
963 if (hasDefiniteFreeSpace) {
964 flexFraction = findFlexFactorUnitSize(
965 tracks, GridSpan::translatedDefiniteGridSpan(0, tracks.size()),
966 direction, initialFreeSpace, sizingData);
967 } else {
968 for (const auto& trackIndex : flexibleSizedTracksIndex) {
969 flexFraction = std::max(
970 flexFraction, normalizedFlexFraction(
971 tracks[trackIndex],
972 gridTrackSize(direction, trackIndex, sizingData)
973 .maxTrackBreadth()
974 .flex()));
975 }
976
977 const Grid& grid = sizingData.grid();
978 if (grid.hasGridItems()) {
979 for (size_t i = 0; i < flexibleSizedTracksIndex.size(); ++i) {
980 GridIterator iterator(grid, direction, flexibleSizedTracksIndex[i]);
981 while (LayoutBox* gridItem = iterator.nextGridItem()) {
982 const GridSpan& span = grid.gridItemSpan(*gridItem, direction);
983
984 // Do not include already processed items.
985 if (i > 0 && span.startLine() <= flexibleSizedTracksIndex[i - 1])
986 continue;
987
988 flexFraction =
989 std::max(flexFraction,
990 findFlexFactorUnitSize(
991 tracks, span, direction,
992 maxContentForChild(*gridItem, direction, sizingData),
993 sizingData));
994 }
995 }
996 }
997 }
998
999 LayoutUnit totalGrowth;
1000 Vector<LayoutUnit> increments;
1001 increments.grow(flexibleSizedTracksIndex.size());
1002 computeFlexSizedTracksGrowth(direction, tracks, flexibleSizedTracksIndex,
1003 flexFraction, increments, totalGrowth,
1004 sizingData);
1005
1006 // We only need to redo the flex fraction computation for indefinite heights
1007 // (definite sizes are already constrained by min/max sizes). Regarding
1008 // widths, they are always definite at layout time so we shouldn't ever have
1009 // to do this.
1010 if (!hasDefiniteFreeSpace && direction == ForRows) {
1011 auto minSize = computeContentLogicalHeight(
1012 MinSize, styleRef().logicalMinHeight(), LayoutUnit(-1));
1013 auto maxSize = computeContentLogicalHeight(
1014 MaxSize, styleRef().logicalMaxHeight(), LayoutUnit(-1));
1015
1016 // Redo the flex fraction computation using min|max-height as definite
1017 // available space in case the total height is smaller than min-height or
1018 // larger than max-height.
1019 LayoutUnit rowsSize =
1020 totalGrowth + computeTrackBasedLogicalHeight(sizingData);
1021 bool checkMinSize = minSize && rowsSize < minSize;
1022 bool checkMaxSize = maxSize != -1 && rowsSize > maxSize;
1023 if (checkMinSize || checkMaxSize) {
1024 LayoutUnit freeSpace = checkMaxSize ? maxSize : LayoutUnit(-1);
1025 freeSpace = std::max(freeSpace, minSize) -
1026 guttersSize(sizingData.grid(), ForRows, 0,
1027 sizingData.grid().numTracks(ForRows),
1028 sizingData.sizingOperation);
1029
1030 flexFraction = findFlexFactorUnitSize(
1031 tracks, GridSpan::translatedDefiniteGridSpan(0, tracks.size()),
1032 ForRows, freeSpace, sizingData);
1033
1034 totalGrowth = LayoutUnit(0);
1035 computeFlexSizedTracksGrowth(ForRows, tracks, flexibleSizedTracksIndex,
1036 flexFraction, increments, totalGrowth,
1037 sizingData);
1038 }
1039 }
1040
1041 size_t i = 0;
1042 for (auto trackIndex : flexibleSizedTracksIndex) {
1043 auto& track = tracks[trackIndex];
1044 if (LayoutUnit increment = increments[i++])
1045 track.setBaseSize(track.baseSize() + increment);
1046 }
1047 freeSpace -= totalGrowth;
1048 growthLimitsWithoutMaximization += totalGrowth;
1049 }
1050
1051 void LayoutGrid::computeFlexSizedTracksGrowth(
1052 GridTrackSizingDirection direction,
1053 Vector<GridTrack>& tracks,
1054 const Vector<size_t>& flexibleSizedTracksIndex,
1055 double flexFraction,
1056 Vector<LayoutUnit>& increments,
1057 LayoutUnit& totalGrowth,
1058 const GridSizingData& sizingData) const {
1059 size_t numFlexTracks = flexibleSizedTracksIndex.size();
1060 DCHECK_EQ(increments.size(), numFlexTracks);
1061 for (size_t i = 0; i < numFlexTracks; ++i) {
1062 size_t trackIndex = flexibleSizedTracksIndex[i];
1063 auto trackSize = gridTrackSize(direction, trackIndex, sizingData);
1064 DCHECK(trackSize.maxTrackBreadth().isFlex());
1065 LayoutUnit oldBaseSize = tracks[trackIndex].baseSize();
1066 LayoutUnit newBaseSize =
1067 std::max(oldBaseSize,
1068 LayoutUnit(flexFraction * trackSize.maxTrackBreadth().flex()));
1069 increments[i] = newBaseSize - oldBaseSize;
1070 totalGrowth += increments[i];
1071 }
1072 }
1073
1074 LayoutUnit LayoutGrid::computeUsedBreadthOfMinLength(
1075 const GridTrackSize& trackSize,
1076 LayoutUnit maxSize) const {
1077 const GridLength& gridLength = trackSize.minTrackBreadth();
1078 if (gridLength.isFlex())
1079 return LayoutUnit();
1080
1081 const Length& trackLength = gridLength.length();
1082 if (trackLength.isSpecified())
1083 return valueForLength(trackLength, maxSize);
1084
1085 ASSERT(trackLength.isMinContent() || trackLength.isAuto() ||
1086 trackLength.isMaxContent());
1087 return LayoutUnit();
1088 }
1089
1090 LayoutUnit LayoutGrid::computeUsedBreadthOfMaxLength(
1091 const GridTrackSize& trackSize,
1092 LayoutUnit usedBreadth,
1093 LayoutUnit maxSize) const {
1094 const GridLength& gridLength = trackSize.maxTrackBreadth();
1095 if (gridLength.isFlex())
1096 return usedBreadth;
1097
1098 const Length& trackLength = gridLength.length();
1099 if (trackLength.isSpecified())
1100 return valueForLength(trackLength, maxSize);
1101
1102 ASSERT(trackLength.isMinContent() || trackLength.isAuto() ||
1103 trackLength.isMaxContent());
1104 return LayoutUnit(infinity);
1105 }
1106
1107 double LayoutGrid::computeFlexFactorUnitSize(
1108 const Vector<GridTrack>& tracks,
1109 GridTrackSizingDirection direction,
1110 double flexFactorSum,
1111 LayoutUnit& leftOverSpace,
1112 const Vector<size_t, 8>& flexibleTracksIndexes,
1113 const GridSizingData& sizingData,
1114 std::unique_ptr<TrackIndexSet> tracksToTreatAsInflexible) const {
1115 // We want to avoid the effect of flex factors sum below 1 making the factor
1116 // unit size to grow exponentially.
1117 double hypotheticalFactorUnitSize =
1118 leftOverSpace / std::max<double>(1, flexFactorSum);
1119
1120 // product of the hypothetical "flex factor unit" and any flexible track's
1121 // "flex factor" must be grater than such track's "base size".
1122 std::unique_ptr<TrackIndexSet> additionalTracksToTreatAsInflexible =
1123 std::move(tracksToTreatAsInflexible);
1124 bool validFlexFactorUnit = true;
1125 for (auto index : flexibleTracksIndexes) {
1126 if (additionalTracksToTreatAsInflexible &&
1127 additionalTracksToTreatAsInflexible->contains(index))
1128 continue;
1129 LayoutUnit baseSize = tracks[index].baseSize();
1130 double flexFactor =
1131 gridTrackSize(direction, index, sizingData).maxTrackBreadth().flex();
1132 // treating all such tracks as inflexible.
1133 if (baseSize > hypotheticalFactorUnitSize * flexFactor) {
1134 leftOverSpace -= baseSize;
1135 flexFactorSum -= flexFactor;
1136 if (!additionalTracksToTreatAsInflexible)
1137 additionalTracksToTreatAsInflexible = WTF::makeUnique<TrackIndexSet>();
1138 additionalTracksToTreatAsInflexible->add(index);
1139 validFlexFactorUnit = false;
1140 }
1141 }
1142 if (!validFlexFactorUnit) {
1143 return computeFlexFactorUnitSize(
1144 tracks, direction, flexFactorSum, leftOverSpace, flexibleTracksIndexes,
1145 sizingData, std::move(additionalTracksToTreatAsInflexible));
1146 }
1147 return hypotheticalFactorUnitSize;
1148 }
1149
1150 double LayoutGrid::findFlexFactorUnitSize(
1151 const Vector<GridTrack>& tracks,
1152 const GridSpan& tracksSpan,
1153 GridTrackSizingDirection direction,
1154 LayoutUnit leftOverSpace,
1155 const GridSizingData& sizingData) const {
1156 if (leftOverSpace <= 0)
1157 return 0;
1158
1159 double flexFactorSum = 0;
1160 Vector<size_t, 8> flexibleTracksIndexes;
1161 for (const auto& trackIndex : tracksSpan) {
1162 GridTrackSize trackSize = gridTrackSize(direction, trackIndex, sizingData);
1163 if (!trackSize.maxTrackBreadth().isFlex()) {
1164 leftOverSpace -= tracks[trackIndex].baseSize();
1165 } else {
1166 flexibleTracksIndexes.push_back(trackIndex);
1167 flexFactorSum += trackSize.maxTrackBreadth().flex();
1168 }
1169 }
1170
1171 // The function is not called if we don't have <flex> grid tracks
1172 ASSERT(!flexibleTracksIndexes.isEmpty());
1173
1174 return computeFlexFactorUnitSize(tracks, direction, flexFactorSum,
1175 leftOverSpace, flexibleTracksIndexes,
1176 sizingData);
1177 }
1178
1179 static bool hasOverrideContainingBlockContentSizeForChild(
1180 const LayoutBox& child,
1181 GridTrackSizingDirection direction) {
1182 return direction == ForColumns
1183 ? child.hasOverrideContainingBlockLogicalWidth()
1184 : child.hasOverrideContainingBlockLogicalHeight();
1185 }
1186
1187 static LayoutUnit overrideContainingBlockContentSizeForChild( 441 static LayoutUnit overrideContainingBlockContentSizeForChild(
1188 const LayoutBox& child, 442 const LayoutBox& child,
1189 GridTrackSizingDirection direction) { 443 GridTrackSizingDirection direction) {
1190 return direction == ForColumns 444 return direction == ForColumns
1191 ? child.overrideContainingBlockContentLogicalWidth() 445 ? child.overrideContainingBlockContentLogicalWidth()
1192 : child.overrideContainingBlockContentLogicalHeight(); 446 : child.overrideContainingBlockContentLogicalHeight();
1193 } 447 }
1194 448
1195 static void setOverrideContainingBlockContentSizeForChild(
1196 LayoutBox& child,
1197 GridTrackSizingDirection direction,
1198 LayoutUnit size) {
1199 if (direction == ForColumns)
1200 child.setOverrideContainingBlockContentLogicalWidth(size);
1201 else
1202 child.setOverrideContainingBlockContentLogicalHeight(size);
1203 }
1204
1205 static bool shouldClearOverrideContainingBlockContentSizeForChild(
1206 const LayoutBox& child,
1207 GridTrackSizingDirection direction) {
1208 if (direction == ForColumns)
1209 return child.hasRelativeLogicalWidth() ||
1210 child.styleRef().logicalWidth().isIntrinsicOrAuto();
1211 return child.hasRelativeLogicalHeight() ||
1212 child.styleRef().logicalHeight().isIntrinsicOrAuto();
1213 }
1214
1215 const GridTrackSize& LayoutGrid::rawGridTrackSize(
1216 GridTrackSizingDirection direction,
1217 size_t translatedIndex,
1218 const GridSizingData& sizingData) const {
1219 bool isRowAxis = direction == ForColumns;
1220 const Vector<GridTrackSize>& trackStyles =
1221 isRowAxis ? styleRef().gridTemplateColumns()
1222 : styleRef().gridTemplateRows();
1223 const Vector<GridTrackSize>& autoRepeatTrackStyles =
1224 isRowAxis ? styleRef().gridAutoRepeatColumns()
1225 : styleRef().gridAutoRepeatRows();
1226 const Vector<GridTrackSize>& autoTrackStyles =
1227 isRowAxis ? styleRef().gridAutoColumns() : styleRef().gridAutoRows();
1228 size_t insertionPoint = isRowAxis
1229 ? styleRef().gridAutoRepeatColumnsInsertionPoint()
1230 : styleRef().gridAutoRepeatRowsInsertionPoint();
1231 size_t autoRepeatTracksCount = sizingData.grid().autoRepeatTracks(direction);
1232
1233 // We should not use GridPositionsResolver::explicitGridXXXCount() for this
1234 // because the explicit grid might be larger than the number of tracks in
1235 // grid-template-rows|columns (if grid-template-areas is specified for
1236 // example).
1237 size_t explicitTracksCount = trackStyles.size() + autoRepeatTracksCount;
1238
1239 int untranslatedIndexAsInt =
1240 translatedIndex + sizingData.grid().smallestTrackStart(direction);
1241 size_t autoTrackStylesSize = autoTrackStyles.size();
1242 if (untranslatedIndexAsInt < 0) {
1243 int index = untranslatedIndexAsInt % static_cast<int>(autoTrackStylesSize);
1244 // We need to traspose the index because the first negative implicit line
1245 // will get the last defined auto track and so on.
1246 index += index ? autoTrackStylesSize : 0;
1247 return autoTrackStyles[index];
1248 }
1249
1250 size_t untranslatedIndex = static_cast<size_t>(untranslatedIndexAsInt);
1251 if (untranslatedIndex >= explicitTracksCount)
1252 return autoTrackStyles[(untranslatedIndex - explicitTracksCount) %
1253 autoTrackStylesSize];
1254
1255 if (LIKELY(!autoRepeatTracksCount) || untranslatedIndex < insertionPoint)
1256 return trackStyles[untranslatedIndex];
1257
1258 if (untranslatedIndex < (insertionPoint + autoRepeatTracksCount)) {
1259 size_t autoRepeatLocalIndex = untranslatedIndexAsInt - insertionPoint;
1260 return autoRepeatTrackStyles[autoRepeatLocalIndex %
1261 autoRepeatTrackStyles.size()];
1262 }
1263
1264 return trackStyles[untranslatedIndex - autoRepeatTracksCount];
1265 }
1266
1267 GridTrackSize LayoutGrid::gridTrackSize(
1268 GridTrackSizingDirection direction,
1269 size_t translatedIndex,
1270 const GridSizingData& sizingData) const {
1271 // Collapse empty auto repeat tracks if auto-fit.
1272 if (sizingData.grid().hasAutoRepeatEmptyTracks(direction) &&
1273 sizingData.grid().isEmptyAutoRepeatTrack(direction, translatedIndex))
1274 return {Length(Fixed), LengthTrackSizing};
1275
1276 const GridTrackSize& trackSize =
1277 rawGridTrackSize(direction, translatedIndex, sizingData);
1278 if (trackSize.isFitContent())
1279 return trackSize;
1280
1281 GridLength minTrackBreadth = trackSize.minTrackBreadth();
1282 GridLength maxTrackBreadth = trackSize.maxTrackBreadth();
1283 // If the logical width/height of the grid container is indefinite, percentage
1284 // values are treated as <auto>.
1285 if (minTrackBreadth.hasPercentage() || maxTrackBreadth.hasPercentage()) {
1286 // For the inline axis this only happens when we're computing the intrinsic
1287 // sizes (AvailableSpaceIndefinite).
1288 if ((sizingData.sizingOperation == IntrinsicSizeComputation) ||
1289 (direction == ForRows && !cachedHasDefiniteLogicalHeight())) {
1290 if (minTrackBreadth.hasPercentage())
1291 minTrackBreadth = Length(Auto);
1292 if (maxTrackBreadth.hasPercentage())
1293 maxTrackBreadth = Length(Auto);
1294 }
1295 }
1296
1297 // Flex sizes are invalid as a min sizing function. However we still can have
1298 // a flexible |minTrackBreadth| if the track had a flex size directly (e.g.
1299 // "1fr"), the spec says that in this case it implies an automatic minimum.
1300 if (minTrackBreadth.isFlex())
1301 minTrackBreadth = Length(Auto);
1302
1303 return GridTrackSize(minTrackBreadth, maxTrackBreadth);
1304 }
1305
1306 bool LayoutGrid::isOrthogonalChild(const LayoutBox& child) const { 449 bool LayoutGrid::isOrthogonalChild(const LayoutBox& child) const {
1307 return child.isHorizontalWritingMode() != isHorizontalWritingMode(); 450 return child.isHorizontalWritingMode() != isHorizontalWritingMode();
1308 } 451 }
1309 452
1310 LayoutUnit LayoutGrid::logicalHeightForChild(LayoutBox& child,
1311 GridSizingData& sizingData) const {
1312 GridTrackSizingDirection childBlockDirection =
1313 flowAwareDirectionForChild(child, ForRows);
1314 // If |child| has a relative logical height, we shouldn't let it override its
1315 // intrinsic height, which is what we are interested in here. Thus we need to
1316 // set the block-axis override size to -1 (no possible resolution).
1317 if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForRows)) {
1318 setOverrideContainingBlockContentSizeForChild(child, childBlockDirection,
1319 LayoutUnit(-1));
1320 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1321 }
1322
1323 // We need to clear the stretched height to properly compute logical height
1324 // during layout.
1325 if (child.needsLayout())
1326 child.clearOverrideLogicalContentHeight();
1327
1328 child.layoutIfNeeded();
1329 return child.logicalHeight() + child.marginLogicalHeight();
1330 }
1331
1332 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild(
1333 const LayoutBox& child,
1334 GridTrackSizingDirection direction) const {
1335 return !isOrthogonalChild(child)
1336 ? direction
1337 : (direction == ForColumns ? ForRows : ForColumns);
1338 }
1339
1340 LayoutUnit LayoutGrid::minSizeForChild(LayoutBox& child,
1341 GridTrackSizingDirection direction,
1342 GridSizingData& sizingData) const {
1343 GridTrackSizingDirection childInlineDirection =
1344 flowAwareDirectionForChild(child, ForColumns);
1345 bool isRowAxis = direction == childInlineDirection;
1346 const Length& childSize = isRowAxis ? child.styleRef().logicalWidth()
1347 : child.styleRef().logicalHeight();
1348 const Length& childMinSize = isRowAxis ? child.styleRef().logicalMinWidth()
1349 : child.styleRef().logicalMinHeight();
1350 bool overflowIsVisible =
1351 isRowAxis
1352 ? child.styleRef().overflowInlineDirection() == EOverflow::Visible
1353 : child.styleRef().overflowBlockDirection() == EOverflow::Visible;
1354 if (!childSize.isAuto() || (childMinSize.isAuto() && overflowIsVisible))
1355 return minContentForChild(child, direction, sizingData);
1356
1357 bool overrideSizeHasChanged =
1358 updateOverrideContainingBlockContentSizeForChild(
1359 child, childInlineDirection, sizingData);
1360 if (isRowAxis) {
1361 LayoutUnit marginLogicalWidth =
1362 sizingData.sizingOperation == TrackSizing
1363 ? computeMarginLogicalSizeForChild(InlineDirection, child)
1364 : marginIntrinsicLogicalWidthForChild(child);
1365 return child.computeLogicalWidthUsing(
1366 MinSize, childMinSize,
1367 overrideContainingBlockContentSizeForChild(child,
1368 childInlineDirection),
1369 this) +
1370 marginLogicalWidth;
1371 }
1372
1373 if (overrideSizeHasChanged &&
1374 (direction != ForColumns ||
1375 sizingData.sizingOperation != IntrinsicSizeComputation))
1376 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1377 child.layoutIfNeeded();
1378 return child.computeLogicalHeightUsing(MinSize, childMinSize,
1379 child.intrinsicLogicalHeight()) +
1380 child.marginLogicalHeight() + child.scrollbarLogicalHeight();
1381 }
1382
1383 bool LayoutGrid::updateOverrideContainingBlockContentSizeForChild(
1384 LayoutBox& child,
1385 GridTrackSizingDirection direction,
1386 GridSizingData& sizingData) const {
1387 LayoutUnit overrideSize =
1388 gridAreaBreadthForChild(child, direction, sizingData);
1389 if (hasOverrideContainingBlockContentSizeForChild(child, direction) &&
1390 overrideContainingBlockContentSizeForChild(child, direction) ==
1391 overrideSize)
1392 return false;
1393
1394 setOverrideContainingBlockContentSizeForChild(child, direction, overrideSize);
1395 return true;
1396 }
1397
1398 DISABLE_CFI_PERF
1399 LayoutUnit LayoutGrid::minContentForChild(LayoutBox& child,
1400 GridTrackSizingDirection direction,
1401 GridSizingData& sizingData) const {
1402 GridTrackSizingDirection childInlineDirection =
1403 flowAwareDirectionForChild(child, ForColumns);
1404 if (direction == childInlineDirection) {
1405 // If |child| has a relative logical width, we shouldn't let it override its
1406 // intrinsic width, which is what we are interested in here. Thus we need to
1407 // set the inline-axis override size to -1 (no possible resolution).
1408 if (shouldClearOverrideContainingBlockContentSizeForChild(child,
1409 ForColumns))
1410 setOverrideContainingBlockContentSizeForChild(child, childInlineDirection,
1411 LayoutUnit(-1));
1412
1413 // FIXME: It's unclear if we should return the intrinsic width or the
1414 // preferred width.
1415 // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
1416 LayoutUnit marginLogicalWidth =
1417 child.needsLayout()
1418 ? computeMarginLogicalSizeForChild(InlineDirection, child)
1419 : child.marginLogicalWidth();
1420 return child.minPreferredLogicalWidth() + marginLogicalWidth;
1421 }
1422
1423 // All orthogonal flow boxes were already laid out during an early layout
1424 // phase performed in FrameView::performLayout.
1425 // It's true that grid track sizing was not completed at that time and it may
1426 // afffect the final height of a grid item, but since it's forbidden to
1427 // perform a layout during intrinsic width computation, we have to use that
1428 // computed height for now.
1429 if (direction == ForColumns &&
1430 sizingData.sizingOperation == IntrinsicSizeComputation) {
1431 DCHECK(isOrthogonalChild(child));
1432 return child.logicalHeight() + child.marginLogicalHeight();
1433 }
1434
1435 if (updateOverrideContainingBlockContentSizeForChild(
1436 child, childInlineDirection, sizingData))
1437 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1438 return logicalHeightForChild(child, sizingData);
1439 }
1440
1441 DISABLE_CFI_PERF
1442 LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child,
1443 GridTrackSizingDirection direction,
1444 GridSizingData& sizingData) const {
1445 GridTrackSizingDirection childInlineDirection =
1446 flowAwareDirectionForChild(child, ForColumns);
1447 if (direction == childInlineDirection) {
1448 // If |child| has a relative logical width, we shouldn't let it override its
1449 // intrinsic width, which is what we are interested in here. Thus we need to
1450 // set the inline-axis override size to -1 (no possible resolution).
1451 if (shouldClearOverrideContainingBlockContentSizeForChild(child,
1452 ForColumns))
1453 setOverrideContainingBlockContentSizeForChild(child, childInlineDirection,
1454 LayoutUnit(-1));
1455
1456 // FIXME: It's unclear if we should return the intrinsic width or the
1457 // preferred width.
1458 // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
1459 LayoutUnit marginLogicalWidth =
1460 child.needsLayout()
1461 ? computeMarginLogicalSizeForChild(InlineDirection, child)
1462 : child.marginLogicalWidth();
1463 return child.maxPreferredLogicalWidth() + marginLogicalWidth;
1464 }
1465
1466 // All orthogonal flow boxes were already laid out during an early layout
1467 // phase performed in FrameView::performLayout.
1468 // It's true that grid track sizing was not completed at that time and it may
1469 // afffect the final height of a grid item, but since it's forbidden to
1470 // perform a layout during intrinsic width computation, we have to use that
1471 // computed height for now.
1472 if (direction == ForColumns &&
1473 sizingData.sizingOperation == IntrinsicSizeComputation) {
1474 DCHECK(isOrthogonalChild(child));
1475 return child.logicalHeight() + child.marginLogicalHeight();
1476 }
1477
1478 if (updateOverrideContainingBlockContentSizeForChild(
1479 child, childInlineDirection, sizingData))
1480 child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
1481 return logicalHeightForChild(child, sizingData);
1482 }
1483
1484 // We're basically using a class instead of a std::pair because of accessing
1485 // gridItem() or getGridSpan() is much more self-explanatory that using .first
1486 // or .second members in the pair. Having a std::pair<LayoutBox*, size_t>
1487 // does not work either because we still need the GridSpan so we'd have to add
1488 // an extra hash lookup for each item at the beginning of
1489 // LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems().
1490 class GridItemWithSpan {
1491 public:
1492 GridItemWithSpan(LayoutBox& gridItem, const GridSpan& gridSpan)
1493 : m_gridItem(&gridItem), m_gridSpan(gridSpan) {}
1494
1495 LayoutBox& gridItem() const { return *m_gridItem; }
1496 GridSpan getGridSpan() const { return m_gridSpan; }
1497
1498 bool operator<(const GridItemWithSpan other) const {
1499 return m_gridSpan.integerSpan() < other.m_gridSpan.integerSpan();
1500 }
1501
1502 private:
1503 LayoutBox* m_gridItem;
1504 GridSpan m_gridSpan;
1505 };
1506
1507 bool LayoutGrid::spanningItemCrossesFlexibleSizedTracks(
1508 const GridSpan& span,
1509 GridTrackSizingDirection direction,
1510 const GridSizingData& sizingData) const {
1511 for (const auto& trackPosition : span) {
1512 const GridTrackSize& trackSize =
1513 gridTrackSize(direction, trackPosition, sizingData);
1514 if (trackSize.minTrackBreadth().isFlex() ||
1515 trackSize.maxTrackBreadth().isFlex())
1516 return true;
1517 }
1518
1519 return false;
1520 }
1521
1522 void LayoutGrid::resolveContentBasedTrackSizingFunctions(
1523 GridTrackSizingDirection direction,
1524 GridSizingData& sizingData) const {
1525 sizingData.itemsSortedByIncreasingSpan.shrink(0);
1526 const Grid& grid = sizingData.grid();
1527 if (grid.hasGridItems()) {
1528 HashSet<LayoutBox*> itemsSet;
1529 for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
1530 GridIterator iterator(grid, direction, trackIndex);
1531 GridTrack& track = (direction == ForColumns)
1532 ? sizingData.columnTracks[trackIndex]
1533 : sizingData.rowTracks[trackIndex];
1534 while (LayoutBox* gridItem = iterator.nextGridItem()) {
1535 if (itemsSet.add(gridItem).isNewEntry) {
1536 const GridSpan& span = grid.gridItemSpan(*gridItem, direction);
1537 if (span.integerSpan() == 1) {
1538 resolveContentBasedTrackSizingFunctionsForNonSpanningItems(
1539 direction, span, *gridItem, track, sizingData);
1540 } else if (!spanningItemCrossesFlexibleSizedTracks(span, direction,
1541 sizingData)) {
1542 sizingData.itemsSortedByIncreasingSpan.push_back(
1543 GridItemWithSpan(*gridItem, span));
1544 }
1545 }
1546 }
1547 }
1548 std::sort(sizingData.itemsSortedByIncreasingSpan.begin(),
1549 sizingData.itemsSortedByIncreasingSpan.end());
1550 }
1551
1552 auto it = sizingData.itemsSortedByIncreasingSpan.begin();
1553 auto end = sizingData.itemsSortedByIncreasingSpan.end();
1554 while (it != end) {
1555 GridItemsSpanGroupRange spanGroupRange = {it,
1556 std::upper_bound(it, end, *it)};
1557 resolveContentBasedTrackSizingFunctionsForItems<ResolveIntrinsicMinimums>(
1558 direction, sizingData, spanGroupRange);
1559 resolveContentBasedTrackSizingFunctionsForItems<
1560 ResolveContentBasedMinimums>(direction, sizingData, spanGroupRange);
1561 resolveContentBasedTrackSizingFunctionsForItems<ResolveMaxContentMinimums>(
1562 direction, sizingData, spanGroupRange);
1563 resolveContentBasedTrackSizingFunctionsForItems<ResolveIntrinsicMaximums>(
1564 direction, sizingData, spanGroupRange);
1565 resolveContentBasedTrackSizingFunctionsForItems<ResolveMaxContentMaximums>(
1566 direction, sizingData, spanGroupRange);
1567 it = spanGroupRange.rangeEnd;
1568 }
1569
1570 for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
1571 GridTrack& track = (direction == ForColumns)
1572 ? sizingData.columnTracks[trackIndex]
1573 : sizingData.rowTracks[trackIndex];
1574 if (track.growthLimit() == infinity)
1575 track.setGrowthLimit(track.baseSize());
1576 }
1577 }
1578
1579 void LayoutGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems(
1580 GridTrackSizingDirection direction,
1581 const GridSpan& span,
1582 LayoutBox& gridItem,
1583 GridTrack& track,
1584 GridSizingData& sizingData) const {
1585 const size_t trackPosition = span.startLine();
1586 GridTrackSize trackSize = gridTrackSize(direction, trackPosition, sizingData);
1587
1588 if (trackSize.hasMinContentMinTrackBreadth())
1589 track.setBaseSize(std::max(
1590 track.baseSize(), minContentForChild(gridItem, direction, sizingData)));
1591 else if (trackSize.hasMaxContentMinTrackBreadth())
1592 track.setBaseSize(std::max(
1593 track.baseSize(), maxContentForChild(gridItem, direction, sizingData)));
1594 else if (trackSize.hasAutoMinTrackBreadth())
1595 track.setBaseSize(std::max(
1596 track.baseSize(), minSizeForChild(gridItem, direction, sizingData)));
1597
1598 if (trackSize.hasMinContentMaxTrackBreadth()) {
1599 track.setGrowthLimit(
1600 std::max(track.growthLimit(),
1601 minContentForChild(gridItem, direction, sizingData)));
1602 } else if (trackSize.hasMaxContentOrAutoMaxTrackBreadth()) {
1603 LayoutUnit growthLimit =
1604 maxContentForChild(gridItem, direction, sizingData);
1605 if (trackSize.isFitContent())
1606 growthLimit =
1607 std::min(growthLimit,
1608 valueForLength(trackSize.fitContentTrackBreadth().length(),
1609 sizingData.availableSpace()));
1610 track.setGrowthLimit(std::max(track.growthLimit(), growthLimit));
1611 }
1612 }
1613
1614 static LayoutUnit trackSizeForTrackSizeComputationPhase(
1615 TrackSizeComputationPhase phase,
1616 const GridTrack& track,
1617 TrackSizeRestriction restriction) {
1618 switch (phase) {
1619 case ResolveIntrinsicMinimums:
1620 case ResolveContentBasedMinimums:
1621 case ResolveMaxContentMinimums:
1622 case MaximizeTracks:
1623 return track.baseSize();
1624 case ResolveIntrinsicMaximums:
1625 case ResolveMaxContentMaximums:
1626 const LayoutUnit& growthLimit = track.growthLimit();
1627 if (restriction == AllowInfinity)
1628 return growthLimit;
1629 return growthLimit == infinity ? track.baseSize() : growthLimit;
1630 }
1631
1632 ASSERT_NOT_REACHED();
1633 return track.baseSize();
1634 }
1635
1636 static bool shouldProcessTrackForTrackSizeComputationPhase(
1637 TrackSizeComputationPhase phase,
1638 const GridTrackSize& trackSize) {
1639 switch (phase) {
1640 case ResolveIntrinsicMinimums:
1641 return trackSize.hasIntrinsicMinTrackBreadth();
1642 case ResolveContentBasedMinimums:
1643 return trackSize.hasMinOrMaxContentMinTrackBreadth();
1644 case ResolveMaxContentMinimums:
1645 return trackSize.hasMaxContentMinTrackBreadth();
1646 case ResolveIntrinsicMaximums:
1647 return trackSize.hasIntrinsicMaxTrackBreadth();
1648 case ResolveMaxContentMaximums:
1649 return trackSize.hasMaxContentOrAutoMaxTrackBreadth();
1650 case MaximizeTracks:
1651 ASSERT_NOT_REACHED();
1652 return false;
1653 }
1654
1655 ASSERT_NOT_REACHED();
1656 return false;
1657 }
1658
1659 static bool trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(
1660 TrackSizeComputationPhase phase,
1661 const GridTrackSize& trackSize) {
1662 switch (phase) {
1663 case ResolveIntrinsicMinimums:
1664 case ResolveContentBasedMinimums:
1665 return trackSize
1666 .hasAutoOrMinContentMinTrackBreadthAndIntrinsicMaxTrackBreadth();
1667 case ResolveMaxContentMinimums:
1668 return trackSize
1669 .hasMaxContentMinTrackBreadthAndMaxContentMaxTrackBreadth();
1670 case ResolveIntrinsicMaximums:
1671 case ResolveMaxContentMaximums:
1672 return true;
1673 case MaximizeTracks:
1674 ASSERT_NOT_REACHED();
1675 return false;
1676 }
1677
1678 ASSERT_NOT_REACHED();
1679 return false;
1680 }
1681
1682 static void markAsInfinitelyGrowableForTrackSizeComputationPhase(
1683 TrackSizeComputationPhase phase,
1684 GridTrack& track) {
1685 switch (phase) {
1686 case ResolveIntrinsicMinimums:
1687 case ResolveContentBasedMinimums:
1688 case ResolveMaxContentMinimums:
1689 return;
1690 case ResolveIntrinsicMaximums:
1691 if (trackSizeForTrackSizeComputationPhase(phase, track, AllowInfinity) ==
1692 infinity &&
1693 track.plannedSize() != infinity)
1694 track.setInfinitelyGrowable(true);
1695 return;
1696 case ResolveMaxContentMaximums:
1697 if (track.infinitelyGrowable())
1698 track.setInfinitelyGrowable(false);
1699 return;
1700 case MaximizeTracks:
1701 ASSERT_NOT_REACHED();
1702 return;
1703 }
1704
1705 ASSERT_NOT_REACHED();
1706 }
1707
1708 static void updateTrackSizeForTrackSizeComputationPhase(
1709 TrackSizeComputationPhase phase,
1710 GridTrack& track) {
1711 switch (phase) {
1712 case ResolveIntrinsicMinimums:
1713 case ResolveContentBasedMinimums:
1714 case ResolveMaxContentMinimums:
1715 track.setBaseSize(track.plannedSize());
1716 return;
1717 case ResolveIntrinsicMaximums:
1718 case ResolveMaxContentMaximums:
1719 track.setGrowthLimit(track.plannedSize());
1720 return;
1721 case MaximizeTracks:
1722 ASSERT_NOT_REACHED();
1723 return;
1724 }
1725
1726 ASSERT_NOT_REACHED();
1727 }
1728
1729 LayoutUnit LayoutGrid::currentItemSizeForTrackSizeComputationPhase(
1730 TrackSizeComputationPhase phase,
1731 LayoutBox& gridItem,
1732 GridTrackSizingDirection direction,
1733 GridSizingData& sizingData) const {
1734 switch (phase) {
1735 case ResolveIntrinsicMinimums:
1736 case ResolveIntrinsicMaximums:
1737 return minSizeForChild(gridItem, direction, sizingData);
1738 case ResolveContentBasedMinimums:
1739 return minContentForChild(gridItem, direction, sizingData);
1740 case ResolveMaxContentMinimums:
1741 case ResolveMaxContentMaximums:
1742 return maxContentForChild(gridItem, direction, sizingData);
1743 case MaximizeTracks:
1744 ASSERT_NOT_REACHED();
1745 return LayoutUnit();
1746 }
1747
1748 ASSERT_NOT_REACHED();
1749 return LayoutUnit();
1750 }
1751
1752 template <TrackSizeComputationPhase phase>
1753 void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(
1754 GridTrackSizingDirection direction,
1755 GridSizingData& sizingData,
1756 const GridItemsSpanGroupRange& gridItemsWithSpan) const {
1757 Vector<GridTrack>& tracks = (direction == ForColumns)
1758 ? sizingData.columnTracks
1759 : sizingData.rowTracks;
1760 for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
1761 GridTrack& track = tracks[trackIndex];
1762 track.setPlannedSize(
1763 trackSizeForTrackSizeComputationPhase(phase, track, AllowInfinity));
1764 }
1765
1766 for (auto it = gridItemsWithSpan.rangeStart; it != gridItemsWithSpan.rangeEnd;
1767 ++it) {
1768 GridItemWithSpan& gridItemWithSpan = *it;
1769 ASSERT(gridItemWithSpan.getGridSpan().integerSpan() > 1);
1770 const GridSpan& itemSpan = gridItemWithSpan.getGridSpan();
1771
1772 sizingData.growBeyondGrowthLimitsTracks.shrink(0);
1773 sizingData.filteredTracks.shrink(0);
1774 LayoutUnit spanningTracksSize;
1775 for (const auto& trackPosition : itemSpan) {
1776 GridTrackSize trackSize =
1777 gridTrackSize(direction, trackPosition, sizingData);
1778 GridTrack& track = (direction == ForColumns)
1779 ? sizingData.columnTracks[trackPosition]
1780 : sizingData.rowTracks[trackPosition];
1781 spanningTracksSize +=
1782 trackSizeForTrackSizeComputationPhase(phase, track, ForbidInfinity);
1783 if (!shouldProcessTrackForTrackSizeComputationPhase(phase, trackSize))
1784 continue;
1785
1786 sizingData.filteredTracks.push_back(&track);
1787
1788 if (trackShouldGrowBeyondGrowthLimitsForTrackSizeComputationPhase(
1789 phase, trackSize))
1790 sizingData.growBeyondGrowthLimitsTracks.push_back(&track);
1791 }
1792
1793 if (sizingData.filteredTracks.isEmpty())
1794 continue;
1795
1796 spanningTracksSize +=
1797 guttersSize(sizingData.grid(), direction, itemSpan.startLine(),
1798 itemSpan.integerSpan(), sizingData.sizingOperation);
1799
1800 LayoutUnit extraSpace =
1801 currentItemSizeForTrackSizeComputationPhase(
1802 phase, gridItemWithSpan.gridItem(), direction, sizingData) -
1803 spanningTracksSize;
1804 extraSpace = extraSpace.clampNegativeToZero();
1805 auto& tracksToGrowBeyondGrowthLimits =
1806 sizingData.growBeyondGrowthLimitsTracks.isEmpty()
1807 ? sizingData.filteredTracks
1808 : sizingData.growBeyondGrowthLimitsTracks;
1809 distributeSpaceToTracks<phase>(sizingData.filteredTracks,
1810 &tracksToGrowBeyondGrowthLimits, sizingData,
1811 extraSpace);
1812 }
1813
1814 for (const auto& trackIndex : sizingData.contentSizedTracksIndex) {
1815 GridTrack& track = tracks[trackIndex];
1816 markAsInfinitelyGrowableForTrackSizeComputationPhase(phase, track);
1817 updateTrackSizeForTrackSizeComputationPhase(phase, track);
1818 }
1819 }
1820
1821 static bool sortByGridTrackGrowthPotential(const GridTrack* track1,
1822 const GridTrack* track2) {
1823 // This check ensures that we respect the irreflexivity property of the strict
1824 // weak ordering required by std::sort(forall x: NOT x < x).
1825 bool track1HasInfiniteGrowthPotentialWithoutCap =
1826 track1->infiniteGrowthPotential() && !track1->growthLimitCap();
1827 bool track2HasInfiniteGrowthPotentialWithoutCap =
1828 track2->infiniteGrowthPotential() && !track2->growthLimitCap();
1829
1830 if (track1HasInfiniteGrowthPotentialWithoutCap &&
1831 track2HasInfiniteGrowthPotentialWithoutCap)
1832 return false;
1833
1834 if (track1HasInfiniteGrowthPotentialWithoutCap ||
1835 track2HasInfiniteGrowthPotentialWithoutCap)
1836 return track2HasInfiniteGrowthPotentialWithoutCap;
1837
1838 LayoutUnit track1Limit =
1839 track1->growthLimitCap().value_or(track1->growthLimit());
1840 LayoutUnit track2Limit =
1841 track2->growthLimitCap().value_or(track2->growthLimit());
1842 return (track1Limit - track1->baseSize()) <
1843 (track2Limit - track2->baseSize());
1844 }
1845
1846 static void clampGrowthShareIfNeeded(TrackSizeComputationPhase phase,
1847 const GridTrack& track,
1848 LayoutUnit& growthShare) {
1849 if (phase != ResolveMaxContentMaximums || !track.growthLimitCap())
1850 return;
1851
1852 LayoutUnit distanceToCap =
1853 track.growthLimitCap().value() - track.sizeDuringDistribution();
1854 if (distanceToCap <= 0)
1855 return;
1856
1857 growthShare = std::min(growthShare, distanceToCap);
1858 }
1859
1860 template <TrackSizeComputationPhase phase>
1861 void LayoutGrid::distributeSpaceToTracks(
1862 Vector<GridTrack*>& tracks,
1863 Vector<GridTrack*>* growBeyondGrowthLimitsTracks,
1864 GridSizingData& sizingData,
1865 LayoutUnit& availableLogicalSpace) const {
1866 ASSERT(availableLogicalSpace >= 0);
1867
1868 for (auto* track : tracks)
1869 track->setSizeDuringDistribution(
1870 trackSizeForTrackSizeComputationPhase(phase, *track, ForbidInfinity));
1871
1872 if (availableLogicalSpace > 0) {
1873 std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
1874
1875 size_t tracksSize = tracks.size();
1876 for (size_t i = 0; i < tracksSize; ++i) {
1877 GridTrack& track = *tracks[i];
1878 LayoutUnit availableLogicalSpaceShare =
1879 availableLogicalSpace / (tracksSize - i);
1880 const LayoutUnit& trackBreadth =
1881 trackSizeForTrackSizeComputationPhase(phase, track, ForbidInfinity);
1882 LayoutUnit growthShare =
1883 track.infiniteGrowthPotential()
1884 ? availableLogicalSpaceShare
1885 : std::min(availableLogicalSpaceShare,
1886 track.growthLimit() - trackBreadth);
1887 clampGrowthShareIfNeeded(phase, track, growthShare);
1888 DCHECK_GE(growthShare, 0) << "We must never shrink any grid track or "
1889 "else we can't guarantee we abide by our "
1890 "min-sizing function.";
1891 track.growSizeDuringDistribution(growthShare);
1892 availableLogicalSpace -= growthShare;
1893 }
1894 }
1895
1896 if (availableLogicalSpace > 0 && growBeyondGrowthLimitsTracks) {
1897 // We need to sort them because there might be tracks with growth limit caps
1898 // (like the ones with fit-content()) which cannot indefinitely grow over
1899 // the limits.
1900 if (phase == ResolveMaxContentMaximums)
1901 std::sort(growBeyondGrowthLimitsTracks->begin(),
1902 growBeyondGrowthLimitsTracks->end(),
1903 sortByGridTrackGrowthPotential);
1904
1905 size_t tracksGrowingAboveMaxBreadthSize =
1906 growBeyondGrowthLimitsTracks->size();
1907 for (size_t i = 0; i < tracksGrowingAboveMaxBreadthSize; ++i) {
1908 GridTrack* track = growBeyondGrowthLimitsTracks->at(i);
1909 LayoutUnit growthShare =
1910 availableLogicalSpace / (tracksGrowingAboveMaxBreadthSize - i);
1911 clampGrowthShareIfNeeded(phase, *track, growthShare);
1912 DCHECK_GE(growthShare, 0) << "We must never shrink any grid track or "
1913 "else we can't guarantee we abide by our "
1914 "min-sizing function.";
1915 track->growSizeDuringDistribution(growthShare);
1916 availableLogicalSpace -= growthShare;
1917 }
1918 }
1919
1920 for (auto* track : tracks)
1921 track->setPlannedSize(
1922 track->plannedSize() == infinity
1923 ? track->sizeDuringDistribution()
1924 : std::max(track->plannedSize(), track->sizeDuringDistribution()));
1925 }
1926
1927 #if DCHECK_IS_ON()
1928 bool LayoutGrid::tracksAreWiderThanMinTrackBreadth(
1929 GridTrackSizingDirection direction,
1930 GridSizingData& sizingData) const {
1931 const Vector<GridTrack>& tracks = (direction == ForColumns)
1932 ? sizingData.columnTracks
1933 : sizingData.rowTracks;
1934 LayoutUnit maxSize = sizingData.availableSpace().clampNegativeToZero();
1935 for (size_t i = 0; i < tracks.size(); ++i) {
1936 GridTrackSize trackSize = gridTrackSize(direction, i, sizingData);
1937 if (computeUsedBreadthOfMinLength(trackSize, maxSize) >
1938 tracks[i].baseSize())
1939 return false;
1940 }
1941 return true;
1942 }
1943 #endif
1944
1945 size_t LayoutGrid::computeAutoRepeatTracksCount( 453 size_t LayoutGrid::computeAutoRepeatTracksCount(
1946 GridTrackSizingDirection direction, 454 GridTrackSizingDirection direction,
1947 SizingOperation sizingOperation) const { 455 SizingOperation sizingOperation) const {
1948 bool isRowAxis = direction == ForColumns; 456 bool isRowAxis = direction == ForColumns;
1949 const auto& autoRepeatTracks = isRowAxis ? styleRef().gridAutoRepeatColumns() 457 const auto& autoRepeatTracks = isRowAxis ? styleRef().gridAutoRepeatColumns()
1950 : styleRef().gridAutoRepeatRows(); 458 : styleRef().gridAutoRepeatRows();
1951 size_t autoRepeatTrackListLength = autoRepeatTracks.size(); 459 size_t autoRepeatTrackListLength = autoRepeatTracks.size();
1952 460
1953 if (!autoRepeatTrackListLength) 461 if (!autoRepeatTrackListLength)
1954 return 0; 462 return 0;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
2038 // Provided the grid container does not have a definite size or max-size in 546 // Provided the grid container does not have a definite size or max-size in
2039 // the relevant axis, if the min size is definite then the number of 547 // the relevant axis, if the min size is definite then the number of
2040 // repetitions is the largest possible positive integer that fulfills that 548 // repetitions is the largest possible positive integer that fulfills that
2041 // minimum requirement. 549 // minimum requirement.
2042 if (needsToFulfillMinimumSize) 550 if (needsToFulfillMinimumSize)
2043 ++repetitions; 551 ++repetitions;
2044 552
2045 return repetitions * autoRepeatTrackListLength; 553 return repetitions * autoRepeatTrackListLength;
2046 } 554 }
2047 555
2048 std::unique_ptr<LayoutGrid::OrderedTrackIndexSet> 556 std::unique_ptr<OrderedTrackIndexSet>
2049 LayoutGrid::computeEmptyTracksForAutoRepeat( 557 LayoutGrid::computeEmptyTracksForAutoRepeat(
2050 Grid& grid, 558 Grid& grid,
2051 GridTrackSizingDirection direction) const { 559 GridTrackSizingDirection direction) const {
2052 bool isRowAxis = direction == ForColumns; 560 bool isRowAxis = direction == ForColumns;
2053 if ((isRowAxis && styleRef().gridAutoRepeatColumnsType() != AutoFit) || 561 if ((isRowAxis && styleRef().gridAutoRepeatColumnsType() != AutoFit) ||
2054 (!isRowAxis && styleRef().gridAutoRepeatRowsType() != AutoFit)) 562 (!isRowAxis && styleRef().gridAutoRepeatRowsType() != AutoFit))
2055 return nullptr; 563 return nullptr;
2056 564
2057 std::unique_ptr<OrderedTrackIndexSet> emptyTrackIndexes; 565 std::unique_ptr<OrderedTrackIndexSet> emptyTrackIndexes;
2058 size_t insertionPoint = isRowAxis 566 size_t insertionPoint = isRowAxis
(...skipping 16 matching lines...) Expand all
2075 if (!iterator.nextGridItem()) { 583 if (!iterator.nextGridItem()) {
2076 if (!emptyTrackIndexes) 584 if (!emptyTrackIndexes)
2077 emptyTrackIndexes = WTF::wrapUnique(new OrderedTrackIndexSet); 585 emptyTrackIndexes = WTF::wrapUnique(new OrderedTrackIndexSet);
2078 emptyTrackIndexes->add(trackIndex); 586 emptyTrackIndexes->add(trackIndex);
2079 } 587 }
2080 } 588 }
2081 } 589 }
2082 return emptyTrackIndexes; 590 return emptyTrackIndexes;
2083 } 591 }
2084 592
2085 void LayoutGrid::placeItemsOnGrid(LayoutGrid::Grid& grid, 593 void LayoutGrid::placeItemsOnGrid(Grid& grid,
2086 SizingOperation sizingOperation) const { 594 SizingOperation sizingOperation) const {
2087 size_t autoRepeatRows = 595 size_t autoRepeatRows =
2088 computeAutoRepeatTracksCount(ForRows, sizingOperation); 596 computeAutoRepeatTracksCount(ForRows, sizingOperation);
2089 size_t autoRepeatColumns = 597 size_t autoRepeatColumns =
2090 computeAutoRepeatTracksCount(ForColumns, sizingOperation); 598 computeAutoRepeatTracksCount(ForColumns, sizingOperation);
2091 if (autoRepeatRows != grid.autoRepeatTracks(ForRows) || 599 if (autoRepeatRows != grid.autoRepeatTracks(ForRows) ||
2092 autoRepeatColumns != grid.autoRepeatTracks(ForColumns)) { 600 autoRepeatColumns != grid.autoRepeatTracks(ForColumns)) {
2093 grid.setNeedsItemsPlacement(true); 601 grid.setNeedsItemsPlacement(true);
2094 grid.setAutoRepeatTracks(autoRepeatRows, autoRepeatColumns); 602 grid.setAutoRepeatTracks(autoRepeatRows, autoRepeatColumns);
2095 } 603 }
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
2465 return tracks; 973 return tracks;
2466 } 974 }
2467 975
2468 static const StyleContentAlignmentData& contentAlignmentNormalBehavior() { 976 static const StyleContentAlignmentData& contentAlignmentNormalBehavior() {
2469 static const StyleContentAlignmentData normalBehavior = { 977 static const StyleContentAlignmentData normalBehavior = {
2470 ContentPositionNormal, ContentDistributionStretch}; 978 ContentPositionNormal, ContentDistributionStretch};
2471 return normalBehavior; 979 return normalBehavior;
2472 } 980 }
2473 981
2474 void LayoutGrid::applyStretchAlignmentToTracksIfNeeded( 982 void LayoutGrid::applyStretchAlignmentToTracksIfNeeded(
2475 GridTrackSizingDirection direction, 983 GridTrackSizingDirection direction) {
2476 GridSizingData& sizingData) { 984 LayoutUnit& availableSpace = m_trackSizingAlgorithm.freeSpace(direction);
2477 LayoutUnit& availableSpace = sizingData.freeSpace(direction);
2478 if (availableSpace <= 0 || 985 if (availableSpace <= 0 ||
2479 (direction == ForColumns && 986 (direction == ForColumns &&
2480 styleRef().resolvedJustifyContentDistribution( 987 styleRef().resolvedJustifyContentDistribution(
2481 contentAlignmentNormalBehavior()) != ContentDistributionStretch) || 988 contentAlignmentNormalBehavior()) != ContentDistributionStretch) ||
2482 (direction == ForRows && 989 (direction == ForRows &&
2483 styleRef().resolvedAlignContentDistribution( 990 styleRef().resolvedAlignContentDistribution(
2484 contentAlignmentNormalBehavior()) != ContentDistributionStretch)) 991 contentAlignmentNormalBehavior()) != ContentDistributionStretch))
2485 return; 992 return;
2486 993
2487 // Spec defines auto-sized tracks as the ones with an 'auto' max-sizing 994 // Spec defines auto-sized tracks as the ones with an 'auto' max-sizing
2488 // function. 995 // function.
2489 Vector<GridTrack>& tracks = (direction == ForColumns) 996 Vector<GridTrack>& allTracks = m_trackSizingAlgorithm.tracks(direction);
2490 ? sizingData.columnTracks
2491 : sizingData.rowTracks;
2492 Vector<unsigned> autoSizedTracksIndex; 997 Vector<unsigned> autoSizedTracksIndex;
2493 for (unsigned i = 0; i < tracks.size(); ++i) { 998 for (unsigned i = 0; i < allTracks.size(); ++i) {
2494 const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData); 999 const GridTrackSize& trackSize =
1000 m_trackSizingAlgorithm.gridTrackSize(direction, i, TrackSizing);
2495 if (trackSize.hasAutoMaxTrackBreadth()) 1001 if (trackSize.hasAutoMaxTrackBreadth())
2496 autoSizedTracksIndex.push_back(i); 1002 autoSizedTracksIndex.push_back(i);
2497 } 1003 }
2498 1004
2499 unsigned numberOfAutoSizedTracks = autoSizedTracksIndex.size(); 1005 unsigned numberOfAutoSizedTracks = autoSizedTracksIndex.size();
2500 if (numberOfAutoSizedTracks < 1) 1006 if (numberOfAutoSizedTracks < 1)
2501 return; 1007 return;
2502 1008
2503 LayoutUnit sizeToIncrease = availableSpace / numberOfAutoSizedTracks; 1009 LayoutUnit sizeToIncrease = availableSpace / numberOfAutoSizedTracks;
2504 for (const auto& trackIndex : autoSizedTracksIndex) { 1010 for (const auto& trackIndex : autoSizedTracksIndex) {
2505 GridTrack* track = tracks.data() + trackIndex; 1011 GridTrack* track = allTracks.data() + trackIndex;
2506 LayoutUnit baseSize = track->baseSize() + sizeToIncrease; 1012 LayoutUnit baseSize = track->baseSize() + sizeToIncrease;
2507 track->setBaseSize(baseSize); 1013 track->setBaseSize(baseSize);
2508 } 1014 }
1015
2509 availableSpace = LayoutUnit(); 1016 availableSpace = LayoutUnit();
2510 } 1017 }
2511 1018
2512 void LayoutGrid::layoutGridItems(GridSizingData& sizingData) { 1019 void LayoutGrid::layoutGridItems() {
2513 DCHECK_EQ(sizingData.sizingOperation, TrackSizing); 1020 populateGridPositionsForDirection(ForColumns);
2514 populateGridPositionsForDirection(sizingData, ForColumns); 1021 populateGridPositionsForDirection(ForRows);
2515 populateGridPositionsForDirection(sizingData, ForRows);
2516 m_gridItemsOverflowingGridArea.resize(0); 1022 m_gridItemsOverflowingGridArea.resize(0);
2517 1023
2518 for (LayoutBox* child = firstChildBox(); child; 1024 for (LayoutBox* child = firstChildBox(); child;
2519 child = child->nextSiblingBox()) { 1025 child = child->nextSiblingBox()) {
2520 if (child->isOutOfFlowPositioned()) { 1026 if (child->isOutOfFlowPositioned()) {
2521 prepareChildForPositionedLayout(*child); 1027 prepareChildForPositionedLayout(*child);
2522 continue; 1028 continue;
2523 } 1029 }
2524 1030
2525 // Because the grid area cannot be styled, we don't need to adjust 1031 // Because the grid area cannot be styled, we don't need to adjust
2526 // the grid breadth to account for 'box-sizing'. 1032 // the grid breadth to account for 'box-sizing'.
2527 LayoutUnit oldOverrideContainingBlockContentLogicalWidth = 1033 LayoutUnit oldOverrideContainingBlockContentLogicalWidth =
2528 child->hasOverrideContainingBlockLogicalWidth() 1034 child->hasOverrideContainingBlockLogicalWidth()
2529 ? child->overrideContainingBlockContentLogicalWidth() 1035 ? child->overrideContainingBlockContentLogicalWidth()
2530 : LayoutUnit(); 1036 : LayoutUnit();
2531 LayoutUnit oldOverrideContainingBlockContentLogicalHeight = 1037 LayoutUnit oldOverrideContainingBlockContentLogicalHeight =
2532 child->hasOverrideContainingBlockLogicalHeight() 1038 child->hasOverrideContainingBlockLogicalHeight()
2533 ? child->overrideContainingBlockContentLogicalHeight() 1039 ? child->overrideContainingBlockContentLogicalHeight()
2534 : LayoutUnit(); 1040 : LayoutUnit();
2535 1041
2536 LayoutUnit overrideContainingBlockContentLogicalWidth = 1042 LayoutUnit overrideContainingBlockContentLogicalWidth =
2537 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForColumns, 1043 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForColumns);
2538 sizingData);
2539 LayoutUnit overrideContainingBlockContentLogicalHeight = 1044 LayoutUnit overrideContainingBlockContentLogicalHeight =
2540 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows, 1045 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows);
2541 sizingData);
2542 1046
2543 if (oldOverrideContainingBlockContentLogicalWidth != 1047 if (oldOverrideContainingBlockContentLogicalWidth !=
2544 overrideContainingBlockContentLogicalWidth || 1048 overrideContainingBlockContentLogicalWidth ||
2545 (oldOverrideContainingBlockContentLogicalHeight != 1049 (oldOverrideContainingBlockContentLogicalHeight !=
2546 overrideContainingBlockContentLogicalHeight && 1050 overrideContainingBlockContentLogicalHeight &&
2547 child->hasRelativeLogicalHeight())) 1051 child->hasRelativeLogicalHeight()))
2548 child->setNeedsLayout(LayoutInvalidationReason::GridChanged); 1052 child->setNeedsLayout(LayoutInvalidationReason::GridChanged);
2549 1053
2550 child->setOverrideContainingBlockContentLogicalWidth( 1054 child->setOverrideContainingBlockContentLogicalWidth(
2551 overrideContainingBlockContentLogicalWidth); 1055 overrideContainingBlockContentLogicalWidth);
2552 child->setOverrideContainingBlockContentLogicalHeight( 1056 child->setOverrideContainingBlockContentLogicalHeight(
2553 overrideContainingBlockContentLogicalHeight); 1057 overrideContainingBlockContentLogicalHeight);
2554 1058
2555 // Stretching logic might force a child layout, so we need to run it before 1059 // Stretching logic might force a child layout, so we need to run it before
2556 // the layoutIfNeeded call to avoid unnecessary relayouts. This might imply 1060 // the layoutIfNeeded call to avoid unnecessary relayouts. This might imply
2557 // that child margins, needed to correctly determine the available space 1061 // that child margins, needed to correctly determine the available space
2558 // before stretching, are not set yet. 1062 // before stretching, are not set yet.
2559 applyStretchAlignmentToChildIfNeeded(*child); 1063 applyStretchAlignmentToChildIfNeeded(*child);
2560 1064
2561 child->layoutIfNeeded(); 1065 child->layoutIfNeeded();
2562 1066
2563 // We need pending layouts to be done in order to compute auto-margins 1067 // We need pending layouts to be done in order to compute auto-margins
2564 // properly. 1068 // properly.
2565 updateAutoMarginsInColumnAxisIfNeeded(*child); 1069 updateAutoMarginsInColumnAxisIfNeeded(*child);
2566 updateAutoMarginsInRowAxisIfNeeded(*child); 1070 updateAutoMarginsInRowAxisIfNeeded(*child);
2567 1071
2568 const GridArea& area = sizingData.grid().gridItemArea(*child); 1072 const GridArea& area = m_grid.gridItemArea(*child);
2569 #if DCHECK_IS_ON() 1073 #if DCHECK_IS_ON()
2570 ASSERT(area.columns.startLine() < sizingData.columnTracks.size()); 1074 DCHECK(area.columns.startLine() <
2571 ASSERT(area.rows.startLine() < sizingData.rowTracks.size()); 1075 m_trackSizingAlgorithm.tracks(ForColumns).size());
1076 DCHECK(area.rows.startLine() <
1077 m_trackSizingAlgorithm.tracks(ForRows).size());
2572 #endif 1078 #endif
2573 child->setLogicalLocation(findChildLogicalPosition(*child, sizingData)); 1079 child->setLogicalLocation(findChildLogicalPosition(*child));
2574 1080
2575 // Keep track of children overflowing their grid area as we might need to 1081 // Keep track of children overflowing their grid area as we might need to
2576 // paint them even if the grid-area is not visible. Using physical 1082 // paint them even if the grid-area is not visible. Using physical
2577 // dimensions for simplicity, so we can forget about orthogonalty. 1083 // dimensions for simplicity, so we can forget about orthogonalty.
2578 LayoutUnit childGridAreaHeight = 1084 LayoutUnit childGridAreaHeight =
2579 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalHeight 1085 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalHeight
2580 : overrideContainingBlockContentLogicalWidth; 1086 : overrideContainingBlockContentLogicalWidth;
2581 LayoutUnit childGridAreaWidth = 1087 LayoutUnit childGridAreaWidth =
2582 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalWidth 1088 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalWidth
2583 : overrideContainingBlockContentLogicalHeight; 1089 : overrideContainingBlockContentLogicalHeight;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2730 1236
2731 if (endLine > 0 && endLine < lastLine) { 1237 if (endLine > 0 && endLine < lastLine) {
2732 DCHECK(!m_grid.needsItemsPlacement()); 1238 DCHECK(!m_grid.needsItemsPlacement());
2733 offset += guttersSize(m_grid, direction, endLine - 1, 2, TrackSizing); 1239 offset += guttersSize(m_grid, direction, endLine - 1, 2, TrackSizing);
2734 offset += isForColumns ? m_offsetBetweenColumns : m_offsetBetweenRows; 1240 offset += isForColumns ? m_offsetBetweenColumns : m_offsetBetweenRows;
2735 } 1241 }
2736 } 1242 }
2737 } 1243 }
2738 } 1244 }
2739 1245
2740 LayoutUnit LayoutGrid::assumedRowsSizeForOrthogonalChild(
2741 const LayoutBox& child,
2742 const GridSizingData& sizingData) const {
2743 DCHECK(isOrthogonalChild(child));
2744 const Grid& grid = sizingData.grid();
2745 const GridSpan& span = grid.gridItemSpan(child, ForRows);
2746 LayoutUnit gridAreaSize;
2747 bool gridAreaIsIndefinite = false;
2748 LayoutUnit containingBlockAvailableSize =
2749 containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
2750 for (auto trackPosition : span) {
2751 GridLength maxTrackSize =
2752 gridTrackSize(ForRows, trackPosition, sizingData).maxTrackBreadth();
2753 if (maxTrackSize.isContentSized() || maxTrackSize.isFlex())
2754 gridAreaIsIndefinite = true;
2755 else
2756 gridAreaSize +=
2757 valueForLength(maxTrackSize.length(), containingBlockAvailableSize);
2758 }
2759
2760 gridAreaSize += guttersSize(grid, ForRows, span.startLine(),
2761 span.integerSpan(), sizingData.sizingOperation);
2762
2763 return gridAreaIsIndefinite
2764 ? std::max(child.maxPreferredLogicalWidth(), gridAreaSize)
2765 : gridAreaSize;
2766 }
2767
2768 LayoutUnit LayoutGrid::gridAreaBreadthForChild(
2769 const LayoutBox& child,
2770 GridTrackSizingDirection direction,
2771 const GridSizingData& sizingData) const {
2772 // To determine the column track's size based on an orthogonal grid item we
2773 // need it's logical height, which may depend on the row track's size. It's
2774 // possible that the row tracks sizing logic has not been performed yet, so we
2775 // will need to do an estimation.
2776 if (direction == ForRows &&
2777 sizingData.sizingState == GridSizingData::ColumnSizingFirstIteration)
2778 return assumedRowsSizeForOrthogonalChild(child, sizingData);
2779
2780 const Vector<GridTrack>& tracks =
2781 direction == ForColumns ? sizingData.columnTracks : sizingData.rowTracks;
2782 const GridSpan& span = sizingData.grid().gridItemSpan(child, direction);
2783 LayoutUnit gridAreaBreadth;
2784 for (const auto& trackPosition : span)
2785 gridAreaBreadth += tracks[trackPosition].baseSize();
2786
2787 gridAreaBreadth +=
2788 guttersSize(sizingData.grid(), direction, span.startLine(),
2789 span.integerSpan(), sizingData.sizingOperation);
2790
2791 return gridAreaBreadth;
2792 }
2793
2794 LayoutUnit LayoutGrid::gridAreaBreadthForChildIncludingAlignmentOffsets( 1246 LayoutUnit LayoutGrid::gridAreaBreadthForChildIncludingAlignmentOffsets(
2795 const LayoutBox& child, 1247 const LayoutBox& child,
2796 GridTrackSizingDirection direction, 1248 GridTrackSizingDirection direction) const {
2797 const GridSizingData& sizingData) const {
2798 // We need the cached value when available because Content Distribution 1249 // We need the cached value when available because Content Distribution
2799 // alignment properties may have some influence in the final grid area 1250 // alignment properties may have some influence in the final grid area
2800 // breadth. 1251 // breadth.
2801 const Vector<GridTrack>& tracks = (direction == ForColumns) 1252 const Vector<GridTrack>& tracks = m_trackSizingAlgorithm.tracks(direction);
2802 ? sizingData.columnTracks 1253 const GridSpan& span =
2803 : sizingData.rowTracks; 1254 m_trackSizingAlgorithm.grid().gridItemSpan(child, direction);
2804 const GridSpan& span = sizingData.grid().gridItemSpan(child, direction);
2805 const Vector<LayoutUnit>& linePositions = 1255 const Vector<LayoutUnit>& linePositions =
2806 (direction == ForColumns) ? m_columnPositions : m_rowPositions; 1256 (direction == ForColumns) ? m_columnPositions : m_rowPositions;
2807 LayoutUnit initialTrackPosition = linePositions[span.startLine()]; 1257 LayoutUnit initialTrackPosition = linePositions[span.startLine()];
2808 LayoutUnit finalTrackPosition = linePositions[span.endLine() - 1]; 1258 LayoutUnit finalTrackPosition = linePositions[span.endLine() - 1];
2809 // Track Positions vector stores the 'start' grid line of each track, so we 1259 // Track Positions vector stores the 'start' grid line of each track, so we
2810 // have to add last track's baseSize. 1260 // have to add last track's baseSize.
2811 return finalTrackPosition - initialTrackPosition + 1261 return finalTrackPosition - initialTrackPosition +
2812 tracks[span.endLine() - 1].baseSize(); 1262 tracks[span.endLine() - 1].baseSize();
2813 } 1263 }
2814 1264
2815 void LayoutGrid::populateGridPositionsForDirection( 1265 void LayoutGrid::populateGridPositionsForDirection(
2816 GridSizingData& sizingData,
2817 GridTrackSizingDirection direction) { 1266 GridTrackSizingDirection direction) {
2818 // Since we add alignment offsets and track gutters, grid lines are not always 1267 // Since we add alignment offsets and track gutters, grid lines are not always
2819 // adjacent. Hence we will have to assume from now on that we just store 1268 // adjacent. Hence we will have to assume from now on that we just store
2820 // positions of the initial grid lines of each track, except the last one, 1269 // positions of the initial grid lines of each track, except the last one,
2821 // which is the only one considered as a final grid line of a track. 1270 // which is the only one considered as a final grid line of a track.
2822 1271
2823 // The grid container's frame elements (border, padding and <content-position> 1272 // The grid container's frame elements (border, padding and <content-position>
2824 // offset) are sensible to the inline-axis flow direction. However, column 1273 // offset) are sensible to the inline-axis flow direction. However, column
2825 // lines positions are 'direction' unaware. This simplification allows us to 1274 // lines positions are 'direction' unaware. This simplification allows us to
2826 // use the same indexes to identify the columns independently on the 1275 // use the same indexes to identify the columns independently on the
2827 // inline-axis direction. 1276 // inline-axis direction.
2828 bool isRowAxis = direction == ForColumns; 1277 bool isRowAxis = direction == ForColumns;
2829 auto& tracks = isRowAxis ? sizingData.columnTracks : sizingData.rowTracks; 1278 auto& tracks = m_trackSizingAlgorithm.tracks(direction);
2830 size_t numberOfTracks = tracks.size(); 1279 size_t numberOfTracks = tracks.size();
2831 size_t numberOfLines = numberOfTracks + 1; 1280 size_t numberOfLines = numberOfTracks + 1;
2832 size_t lastLine = numberOfLines - 1; 1281 size_t lastLine = numberOfLines - 1;
2833 ContentAlignmentData offset = computeContentPositionAndDistributionOffset( 1282 ContentAlignmentData offset = computeContentPositionAndDistributionOffset(
2834 direction, sizingData.freeSpace(direction), numberOfTracks); 1283 direction, m_trackSizingAlgorithm.freeSpace(direction), numberOfTracks);
2835 auto& positions = isRowAxis ? m_columnPositions : m_rowPositions; 1284 auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
2836 positions.resize(numberOfLines); 1285 positions.resize(numberOfLines);
2837 auto borderAndPadding = 1286 auto borderAndPadding =
2838 isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore(); 1287 isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore();
2839 positions[0] = borderAndPadding + offset.positionOffset; 1288 positions[0] = borderAndPadding + offset.positionOffset;
2840 const Grid& grid = sizingData.grid(); 1289 const Grid& grid = m_trackSizingAlgorithm.grid();
2841 if (numberOfLines > 1) { 1290 if (numberOfLines > 1) {
2842 // If we have collapsed tracks we just ignore gaps here and add them later 1291 // If we have collapsed tracks we just ignore gaps here and add them later
2843 // as we might not compute the gap between two consecutive tracks without 1292 // as we might not compute the gap between two consecutive tracks without
2844 // examining the surrounding ones. 1293 // examining the surrounding ones.
2845 bool hasCollapsedTracks = grid.hasAutoRepeatEmptyTracks(direction); 1294 bool hasCollapsedTracks = grid.hasAutoRepeatEmptyTracks(direction);
2846 LayoutUnit gap = 1295 LayoutUnit gap = !hasCollapsedTracks
2847 !hasCollapsedTracks 1296 ? gridGapForDirection(direction, TrackSizing)
2848 ? gridGapForDirection(direction, sizingData.sizingOperation) 1297 : LayoutUnit();
2849 : LayoutUnit();
2850 size_t nextToLastLine = numberOfLines - 2; 1298 size_t nextToLastLine = numberOfLines - 2;
2851 for (size_t i = 0; i < nextToLastLine; ++i) 1299 for (size_t i = 0; i < nextToLastLine; ++i)
2852 positions[i + 1] = 1300 positions[i + 1] =
2853 positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap; 1301 positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap;
2854 positions[lastLine] = 1302 positions[lastLine] =
2855 positions[nextToLastLine] + tracks[nextToLastLine].baseSize(); 1303 positions[nextToLastLine] + tracks[nextToLastLine].baseSize();
2856 1304
2857 // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to 1305 // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to
2858 // collapse (they coincide exactly) except on the edges of the grid where 1306 // collapse (they coincide exactly) except on the edges of the grid where
2859 // they become 0. 1307 // they become 0.
2860 if (hasCollapsedTracks) { 1308 if (hasCollapsedTracks) {
2861 gap = gridGapForDirection(direction, sizingData.sizingOperation); 1309 gap = gridGapForDirection(direction, TrackSizing);
2862 size_t remainingEmptyTracks = 1310 size_t remainingEmptyTracks =
2863 grid.autoRepeatEmptyTracks(direction)->size(); 1311 grid.autoRepeatEmptyTracks(direction)->size();
2864 LayoutUnit gapAccumulator; 1312 LayoutUnit gapAccumulator;
2865 for (size_t i = 1; i < lastLine; ++i) { 1313 for (size_t i = 1; i < lastLine; ++i) {
2866 if (grid.isEmptyAutoRepeatTrack(direction, i - 1)) { 1314 if (grid.isEmptyAutoRepeatTrack(direction, i - 1)) {
2867 --remainingEmptyTracks; 1315 --remainingEmptyTracks;
2868 } else { 1316 } else {
2869 // Add gap between consecutive non empty tracks. Add it also just once 1317 // Add gap between consecutive non empty tracks. Add it also just once
2870 // for an arbitrary number of empty tracks between two non empty ones. 1318 // for an arbitrary number of empty tracks between two non empty ones.
2871 bool allRemainingTracksAreEmpty = 1319 bool allRemainingTracksAreEmpty =
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2963 const LayoutBox& child) const { 1411 const LayoutBox& child) const {
2964 if (!child.isAnonymous()) 1412 if (!child.isAnonymous())
2965 return child.styleRef().resolvedJustifySelf(ItemPositionStretch); 1413 return child.styleRef().resolvedJustifySelf(ItemPositionStretch);
2966 // All the 'auto' values has been solved by the StyleAdjuster, but it's 1414 // All the 'auto' values has been solved by the StyleAdjuster, but it's
2967 // possible that some grid items generate Anonymous boxes, which need to be 1415 // possible that some grid items generate Anonymous boxes, which need to be
2968 // solved during layout. 1416 // solved during layout.
2969 return child.styleRef().resolvedJustifySelf(selfAlignmentNormalBehavior(), 1417 return child.styleRef().resolvedJustifySelf(selfAlignmentNormalBehavior(),
2970 style()); 1418 style());
2971 } 1419 }
2972 1420
1421 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild(
1422 const LayoutBox& child,
1423 GridTrackSizingDirection direction) const {
1424 return !isOrthogonalChild(child)
1425 ? direction
1426 : (direction == ForColumns ? ForRows : ForColumns);
1427 }
1428
2973 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to 1429 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to
2974 // LayoutBox. 1430 // LayoutBox.
2975 void LayoutGrid::applyStretchAlignmentToChildIfNeeded(LayoutBox& child) { 1431 void LayoutGrid::applyStretchAlignmentToChildIfNeeded(LayoutBox& child) {
2976 // We clear height override values because we will decide now whether it's 1432 // We clear height override values because we will decide now whether it's
2977 // allowed or not, evaluating the conditions which might have changed since 1433 // allowed or not, evaluating the conditions which might have changed since
2978 // the old values were set. 1434 // the old values were set.
2979 child.clearOverrideLogicalContentHeight(); 1435 child.clearOverrideLogicalContentHeight();
2980 1436
2981 GridTrackSizingDirection childBlockDirection = 1437 GridTrackSizingDirection childBlockDirection =
2982 flowAwareDirectionForChild(child, ForRows); 1438 flowAwareDirectionForChild(child, ForRows);
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
3328 return GridAxisStart; 1784 return GridAxisStart;
3329 case ItemPositionAuto: 1785 case ItemPositionAuto:
3330 case ItemPositionNormal: 1786 case ItemPositionNormal:
3331 break; 1787 break;
3332 } 1788 }
3333 1789
3334 ASSERT_NOT_REACHED(); 1790 ASSERT_NOT_REACHED();
3335 return GridAxisStart; 1791 return GridAxisStart;
3336 } 1792 }
3337 1793
3338 LayoutUnit LayoutGrid::columnAxisOffsetForChild( 1794 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const {
3339 const LayoutBox& child, 1795 const GridSpan& rowsSpan =
3340 GridSizingData& sizingData) const { 1796 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForRows);
3341 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows);
3342 size_t childStartLine = rowsSpan.startLine(); 1797 size_t childStartLine = rowsSpan.startLine();
3343 LayoutUnit startOfRow = m_rowPositions[childStartLine]; 1798 LayoutUnit startOfRow = m_rowPositions[childStartLine];
3344 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); 1799 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
3345 if (hasAutoMarginsInColumnAxis(child)) 1800 if (hasAutoMarginsInColumnAxis(child))
3346 return startPosition; 1801 return startPosition;
3347 GridAxisPosition axisPosition = columnAxisPositionForChild(child); 1802 GridAxisPosition axisPosition = columnAxisPositionForChild(child);
3348 switch (axisPosition) { 1803 switch (axisPosition) {
3349 case GridAxisStart: 1804 case GridAxisStart:
3350 return startPosition; 1805 return startPosition;
3351 case GridAxisEnd: 1806 case GridAxisEnd:
3352 case GridAxisCenter: { 1807 case GridAxisCenter: {
3353 size_t childEndLine = rowsSpan.endLine(); 1808 size_t childEndLine = rowsSpan.endLine();
3354 LayoutUnit endOfRow = m_rowPositions[childEndLine]; 1809 LayoutUnit endOfRow = m_rowPositions[childEndLine];
3355 // m_rowPositions include distribution offset (because of content 1810 // m_rowPositions include distribution offset (because of content
3356 // alignment) and gutters so we need to subtract them to get the actual 1811 // alignment) and gutters so we need to subtract them to get the actual
3357 // end position for a given row (this does not have to be done for the 1812 // end position for a given row (this does not have to be done for the
3358 // last track as there are no more m_columnPositions after it). 1813 // last track as there are no more m_columnPositions after it).
3359 LayoutUnit trackGap = 1814 LayoutUnit trackGap = gridGapForDirection(ForRows, TrackSizing);
3360 gridGapForDirection(ForRows, sizingData.sizingOperation);
3361 if (childEndLine < m_rowPositions.size() - 1) { 1815 if (childEndLine < m_rowPositions.size() - 1) {
3362 endOfRow -= trackGap; 1816 endOfRow -= trackGap;
3363 endOfRow -= m_offsetBetweenRows; 1817 endOfRow -= m_offsetBetweenRows;
3364 } 1818 }
3365 LayoutUnit columnAxisChildSize = 1819 LayoutUnit columnAxisChildSize =
3366 isOrthogonalChild(child) 1820 isOrthogonalChild(child)
3367 ? child.logicalWidth() + child.marginLogicalWidth() 1821 ? child.logicalWidth() + child.marginLogicalWidth()
3368 : child.logicalHeight() + child.marginLogicalHeight(); 1822 : child.logicalHeight() + child.marginLogicalHeight();
3369 OverflowAlignment overflow = alignSelfForChild(child).overflow(); 1823 OverflowAlignment overflow = alignSelfForChild(child).overflow();
3370 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset( 1824 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(
3371 overflow, endOfRow - startOfRow, columnAxisChildSize); 1825 overflow, endOfRow - startOfRow, columnAxisChildSize);
3372 return startPosition + (axisPosition == GridAxisEnd 1826 return startPosition + (axisPosition == GridAxisEnd
3373 ? offsetFromStartPosition 1827 ? offsetFromStartPosition
3374 : offsetFromStartPosition / 2); 1828 : offsetFromStartPosition / 2);
3375 } 1829 }
3376 } 1830 }
3377 1831
3378 ASSERT_NOT_REACHED(); 1832 ASSERT_NOT_REACHED();
3379 return LayoutUnit(); 1833 return LayoutUnit();
3380 } 1834 }
3381 1835
3382 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child, 1836 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child) const {
3383 GridSizingData& sizingData) const {
3384 const GridSpan& columnsSpan = 1837 const GridSpan& columnsSpan =
3385 sizingData.grid().gridItemSpan(child, ForColumns); 1838 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForColumns);
3386 size_t childStartLine = columnsSpan.startLine(); 1839 size_t childStartLine = columnsSpan.startLine();
3387 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; 1840 LayoutUnit startOfColumn = m_columnPositions[childStartLine];
3388 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); 1841 LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
3389 if (hasAutoMarginsInRowAxis(child)) 1842 if (hasAutoMarginsInRowAxis(child))
3390 return startPosition; 1843 return startPosition;
3391 GridAxisPosition axisPosition = rowAxisPositionForChild(child); 1844 GridAxisPosition axisPosition = rowAxisPositionForChild(child);
3392 switch (axisPosition) { 1845 switch (axisPosition) {
3393 case GridAxisStart: 1846 case GridAxisStart:
3394 return startPosition; 1847 return startPosition;
3395 case GridAxisEnd: 1848 case GridAxisEnd:
3396 case GridAxisCenter: { 1849 case GridAxisCenter: {
3397 size_t childEndLine = columnsSpan.endLine(); 1850 size_t childEndLine = columnsSpan.endLine();
3398 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; 1851 LayoutUnit endOfColumn = m_columnPositions[childEndLine];
3399 // m_columnPositions include distribution offset (because of content 1852 // m_columnPositions include distribution offset (because of content
3400 // alignment) and gutters so we need to subtract them to get the actual 1853 // alignment) and gutters so we need to subtract them to get the actual
3401 // end position for a given column (this does not have to be done for the 1854 // end position for a given column (this does not have to be done for the
3402 // last track as there are no more m_columnPositions after it). 1855 // last track as there are no more m_columnPositions after it).
3403 LayoutUnit trackGap = 1856 LayoutUnit trackGap = gridGapForDirection(ForColumns, TrackSizing);
3404 gridGapForDirection(ForColumns, sizingData.sizingOperation);
3405 if (childEndLine < m_columnPositions.size() - 1) { 1857 if (childEndLine < m_columnPositions.size() - 1) {
3406 endOfColumn -= trackGap; 1858 endOfColumn -= trackGap;
3407 endOfColumn -= m_offsetBetweenColumns; 1859 endOfColumn -= m_offsetBetweenColumns;
3408 } 1860 }
3409 LayoutUnit rowAxisChildSize = 1861 LayoutUnit rowAxisChildSize =
3410 isOrthogonalChild(child) 1862 isOrthogonalChild(child)
3411 ? child.logicalHeight() + child.marginLogicalHeight() 1863 ? child.logicalHeight() + child.marginLogicalHeight()
3412 : child.logicalWidth() + child.marginLogicalWidth(); 1864 : child.logicalWidth() + child.marginLogicalWidth();
3413 OverflowAlignment overflow = justifySelfForChild(child).overflow(); 1865 OverflowAlignment overflow = justifySelfForChild(child).overflow();
3414 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset( 1866 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3555 2007
3556 LayoutUnit LayoutGrid::translateRTLCoordinate(LayoutUnit coordinate) const { 2008 LayoutUnit LayoutGrid::translateRTLCoordinate(LayoutUnit coordinate) const {
3557 ASSERT(!styleRef().isLeftToRightDirection()); 2009 ASSERT(!styleRef().isLeftToRightDirection());
3558 2010
3559 LayoutUnit alignmentOffset = m_columnPositions[0]; 2011 LayoutUnit alignmentOffset = m_columnPositions[0];
3560 LayoutUnit rightGridEdgePosition = 2012 LayoutUnit rightGridEdgePosition =
3561 m_columnPositions[m_columnPositions.size() - 1]; 2013 m_columnPositions[m_columnPositions.size() - 1];
3562 return rightGridEdgePosition + alignmentOffset - coordinate; 2014 return rightGridEdgePosition + alignmentOffset - coordinate;
3563 } 2015 }
3564 2016
3565 LayoutPoint LayoutGrid::findChildLogicalPosition( 2017 LayoutPoint LayoutGrid::findChildLogicalPosition(const LayoutBox& child) const {
3566 const LayoutBox& child, 2018 LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child);
3567 GridSizingData& sizingData) const { 2019 LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child);
3568 LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child, sizingData);
3569 LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child, sizingData);
3570 // We stored m_columnPosition's data ignoring the direction, hence we might 2020 // We stored m_columnPosition's data ignoring the direction, hence we might
3571 // need now to translate positions from RTL to LTR, as it's more convenient 2021 // need now to translate positions from RTL to LTR, as it's more convenient
3572 // for painting. 2022 // for painting.
3573 if (!style()->isLeftToRightDirection()) 2023 if (!style()->isLeftToRightDirection())
3574 rowAxisOffset = translateRTLCoordinate(rowAxisOffset) - 2024 rowAxisOffset = translateRTLCoordinate(rowAxisOffset) -
3575 (isOrthogonalChild(child) ? child.logicalHeight() 2025 (isOrthogonalChild(child) ? child.logicalHeight()
3576 : child.logicalWidth()); 2026 : child.logicalWidth());
3577 2027
3578 // "In the positioning phase [...] calculations are performed according to the 2028 // "In the positioning phase [...] calculations are performed according to the
3579 // writing mode of the containing block of the box establishing the orthogonal 2029 // writing mode of the containing block of the box establishing the orthogonal
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3621 if (direction == ForRows) 2071 if (direction == ForRows)
3622 return grid.numTracks(ForRows); 2072 return grid.numTracks(ForRows);
3623 2073
3624 return grid.numTracks(ForRows) 2074 return grid.numTracks(ForRows)
3625 ? grid.numTracks(ForColumns) 2075 ? grid.numTracks(ForColumns)
3626 : GridPositionsResolver::explicitGridColumnCount( 2076 : GridPositionsResolver::explicitGridColumnCount(
3627 styleRef(), grid.autoRepeatTracks(ForColumns)); 2077 styleRef(), grid.autoRepeatTracks(ForColumns));
3628 } 2078 }
3629 2079
3630 } // namespace blink 2080 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698