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

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: Build fixes 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 LayoutUnit freeSpace =
568 DCHECK(sizingData.isValidTransition(direction)); 150 availableSpace - guttersSize(m_grid, direction, 0,
569 sizingData.setAvailableSpace(availableSpace); 151 m_grid.numTracks(direction), TrackSizing);
570 sizingData.freeSpace(direction) = 152 m_trackSizingAlgorithm.setup(direction, numTracks(direction, m_grid),
571 availableSpace - guttersSize(sizingData.grid(), direction, 0, 153 TrackSizing, availableSpace, freeSpace);
572 sizingData.grid().numTracks(direction), 154 m_trackSizingAlgorithm.run();
573 sizingData.sizingOperation);
574 sizingData.sizingOperation = TrackSizing;
575 155
576 LayoutUnit baseSizes, growthLimits; 156 DCHECK(m_trackSizingAlgorithm.tracksAreWiderThanMinTrackBreadth());
577 computeUsedBreadthOfGridTracks(direction, sizingData, baseSizes,
578 growthLimits);
579 ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData));
580 sizingData.nextState();
581 } 157 }
582 158
583 void LayoutGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, 159 void LayoutGrid::repeatTracksSizingIfNeeded(LayoutUnit availableSpaceForColumns,
584 LayoutUnit availableSpaceForColumns,
585 LayoutUnit availableSpaceForRows) { 160 LayoutUnit availableSpaceForRows) {
586 DCHECK(sizingData.sizingState > GridSizingData::RowSizingFirstIteration);
587
588 // In orthogonal flow cases column track's size is determined by using the 161 // 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 162 // computed row track's size, which it was estimated during the first cycle of
590 // the sizing algorithm. 163 // the sizing algorithm.
591 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns 164 // Hence we need to repeat computeUsedBreadthOfGridTracks for both, columns
592 // and rows, to determine the final values. 165 // and rows, to determine the final values.
593 // TODO (lajava): orthogonal flows is just one of the cases which may require 166 // 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 167 // 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 168 // 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 169 // more specific condition to detect whether child's min-content contribution
597 // has changed or not. 170 // has changed or not.
598 if (sizingData.grid().hasAnyOrthogonalGridItem()) { 171 if (m_grid.hasAnyOrthogonalGridItem()) {
599 computeTrackSizesForDefiniteSize(ForColumns, sizingData, 172 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
600 availableSpaceForColumns); 173 computeTrackSizesForDefiniteSize(ForRows, availableSpaceForRows);
601 computeTrackSizesForDefiniteSize(ForRows, sizingData,
602 availableSpaceForRows);
603 } 174 }
604 } 175 }
605 176
606 void LayoutGrid::layoutBlock(bool relayoutChildren) { 177 void LayoutGrid::layoutBlock(bool relayoutChildren) {
607 ASSERT(needsLayout()); 178 ASSERT(needsLayout());
608 179
609 // We cannot perform a simplifiedLayout() on a dirty grid that 180 // We cannot perform a simplifiedLayout() on a dirty grid that
610 // has positioned items to be laid out. 181 // has positioned items to be laid out.
611 if (!relayoutChildren && 182 if (!relayoutChildren &&
612 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) && 183 (!m_grid.needsItemsPlacement() || !posChildNeedsLayout()) &&
(...skipping 24 matching lines...) Expand all
637 } 208 }
638 } 209 }
639 210
640 updateLogicalWidth(); 211 updateLogicalWidth();
641 m_hasDefiniteLogicalHeight = hasDefiniteLogicalHeight(); 212 m_hasDefiniteLogicalHeight = hasDefiniteLogicalHeight();
642 213
643 TextAutosizer::LayoutScope textAutosizerLayoutScope(this, &layoutScope); 214 TextAutosizer::LayoutScope textAutosizerLayoutScope(this, &layoutScope);
644 215
645 placeItemsOnGrid(m_grid, TrackSizing); 216 placeItemsOnGrid(m_grid, TrackSizing);
646 217
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 218 // 1- First, the track sizing algorithm is used to resolve the sizes of the
651 // grid columns. 219 // grid columns.
652 // At this point the logical width is always definite as the above call to 220 // At this point the logical width is always definite as the above call to
653 // updateLogicalWidth() properly resolves intrinsic sizes. We cannot do the 221 // updateLogicalWidth() properly resolves intrinsic sizes. We cannot do the
654 // same for heights though because many code paths inside 222 // same for heights though because many code paths inside
655 // updateLogicalHeight() require a previous call to setLogicalHeight() to 223 // updateLogicalHeight() require a previous call to setLogicalHeight() to
656 // resolve heights properly (like for positioned items for example). 224 // resolve heights properly (like for positioned items for example).
657 LayoutUnit availableSpaceForColumns = availableLogicalWidth(); 225 LayoutUnit availableSpaceForColumns = availableLogicalWidth();
658 computeTrackSizesForDefiniteSize(ForColumns, sizingData, 226 computeTrackSizesForDefiniteSize(ForColumns, availableSpaceForColumns);
659 availableSpaceForColumns);
660 227
661 // 2- Next, the track sizing algorithm resolves the sizes of the grid rows, 228 // 2- Next, the track sizing algorithm resolves the sizes of the grid rows,
662 // using the grid column sizes calculated in the previous step. 229 // using the grid column sizes calculated in the previous step.
663 if (cachedHasDefiniteLogicalHeight()) { 230 if (cachedHasDefiniteLogicalHeight()) {
664 computeTrackSizesForDefiniteSize( 231 computeTrackSizesForDefiniteSize(
665 ForRows, sizingData, 232 ForRows, availableLogicalHeight(ExcludeMarginBorderPadding));
666 availableLogicalHeight(ExcludeMarginBorderPadding));
667 } else { 233 } else {
668 computeTrackSizesForIndefiniteSize( 234 computeTrackSizesForIndefiniteSize(m_trackSizingAlgorithm, ForRows,
669 ForRows, sizingData, m_minContentHeight, m_maxContentHeight); 235 m_grid, m_minContentHeight,
670 sizingData.nextState(); 236 m_maxContentHeight);
671 sizingData.sizingOperation = TrackSizing;
672 } 237 }
673 LayoutUnit trackBasedLogicalHeight = 238 LayoutUnit trackBasedLogicalHeight = computeTrackBasedLogicalHeight() +
674 computeTrackBasedLogicalHeight(sizingData) + 239 borderAndPaddingLogicalHeight() +
675 borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(); 240 scrollbarLogicalHeight();
676 setLogicalHeight(trackBasedLogicalHeight); 241 setLogicalHeight(trackBasedLogicalHeight);
677 242
678 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); 243 LayoutUnit oldClientAfterEdge = clientLogicalBottom();
679 updateLogicalHeight(); 244 updateLogicalHeight();
680 245
681 // Once grid's indefinite height is resolved, we can compute the 246 // Once grid's indefinite height is resolved, we can compute the
682 // available free space for Content Alignment. 247 // available free space for Content Alignment.
683 if (!cachedHasDefiniteLogicalHeight()) 248 if (!cachedHasDefiniteLogicalHeight()) {
684 sizingData.freeSpace(ForRows) = logicalHeight() - trackBasedLogicalHeight; 249 m_trackSizingAlgorithm.freeSpace(ForRows) =
250 logicalHeight() - trackBasedLogicalHeight;
251 }
685 252
686 // 3- If the min-content contribution of any grid items have changed based 253 // 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 254 // on the row sizes calculated in step 2, steps 1 and 2 are repeated with
688 // the new min-content contribution (once only). 255 // the new min-content contribution (once only).
689 repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, 256 repeatTracksSizingIfNeeded(availableSpaceForColumns,
690 contentLogicalHeight()); 257 contentLogicalHeight());
691 258
692 // Grid container should have the minimum height of a line if it's editable. 259 // Grid container should have the minimum height of a line if it's editable.
693 // That doesn't affect track sizing though. 260 // That doesn't affect track sizing though.
694 if (hasLineIfEmpty()) 261 if (hasLineIfEmpty())
695 setLogicalHeight( 262 setLogicalHeight(
696 std::max(logicalHeight(), minimumLogicalHeightForEmptyLine())); 263 std::max(logicalHeight(), minimumLogicalHeightForEmptyLine()));
697 264
698 applyStretchAlignmentToTracksIfNeeded(ForColumns, sizingData); 265 applyStretchAlignmentToTracksIfNeeded(ForColumns);
699 applyStretchAlignmentToTracksIfNeeded(ForRows, sizingData); 266 applyStretchAlignmentToTracksIfNeeded(ForRows);
700 267
701 layoutGridItems(sizingData); 268 layoutGridItems();
269 m_trackSizingAlgorithm.reset();
702 270
703 if (size() != previousSize) 271 if (size() != previousSize)
704 relayoutChildren = true; 272 relayoutChildren = true;
705 273
706 layoutPositionedObjects(relayoutChildren || isDocumentElement()); 274 layoutPositionedObjects(relayoutChildren || isDocumentElement());
707 275
708 computeOverflow(oldClientAfterEdge); 276 computeOverflow(oldClientAfterEdge);
709 } 277 }
710 278
711 updateLayerTransformAfterLayout(); 279 updateLayerTransformAfterLayout();
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 366
799 return gapAccumulator; 367 return gapAccumulator;
800 } 368 }
801 369
802 void LayoutGrid::computeIntrinsicLogicalWidths( 370 void LayoutGrid::computeIntrinsicLogicalWidths(
803 LayoutUnit& minLogicalWidth, 371 LayoutUnit& minLogicalWidth,
804 LayoutUnit& maxLogicalWidth) const { 372 LayoutUnit& maxLogicalWidth) const {
805 Grid grid(this); 373 Grid grid(this);
806 placeItemsOnGrid(grid, IntrinsicSizeComputation); 374 placeItemsOnGrid(grid, IntrinsicSizeComputation);
807 375
808 GridSizingData sizingData(numTracks(ForColumns, grid), 376 GridTrackSizingAlgorithm algorithm(this, grid);
809 numTracks(ForRows, grid), grid); 377 computeTrackSizesForIndefiniteSize(algorithm, ForColumns, grid,
810 378 minLogicalWidth, maxLogicalWidth);
811 computeTrackSizesForIndefiniteSize(ForColumns, sizingData, minLogicalWidth,
812 maxLogicalWidth);
813 379
814 LayoutUnit scrollbarWidth = LayoutUnit(scrollbarLogicalWidth()); 380 LayoutUnit scrollbarWidth = LayoutUnit(scrollbarLogicalWidth());
815 minLogicalWidth += scrollbarWidth; 381 minLogicalWidth += scrollbarWidth;
816 maxLogicalWidth += scrollbarWidth; 382 maxLogicalWidth += scrollbarWidth;
817 } 383 }
818 384
819 void LayoutGrid::computeTrackSizesForIndefiniteSize( 385 void LayoutGrid::computeTrackSizesForIndefiniteSize(
386 GridTrackSizingAlgorithm& algo,
820 GridTrackSizingDirection direction, 387 GridTrackSizingDirection direction,
821 GridSizingData& sizingData, 388 Grid& grid,
822 LayoutUnit& minIntrinsicSize, 389 LayoutUnit& minIntrinsicSize,
823 LayoutUnit& maxIntrinsicSize) const { 390 LayoutUnit& maxIntrinsicSize) const {
824 DCHECK(sizingData.isValidTransition(direction)); 391 algo.setup(direction, numTracks(direction, grid), IntrinsicSizeComputation,
825 sizingData.setAvailableSpace(LayoutUnit()); 392 LayoutUnit(), LayoutUnit());
826 sizingData.freeSpace(direction) = LayoutUnit(); 393 algo.run();
827 sizingData.sizingOperation = IntrinsicSizeComputation;
828 394
829 computeUsedBreadthOfGridTracks(direction, sizingData, minIntrinsicSize, 395 minIntrinsicSize = algo.minContentSize();
830 maxIntrinsicSize); 396 maxIntrinsicSize = algo.maxContentSize();
831 397
832 size_t numberOfTracks = direction == ForColumns 398 size_t numberOfTracks = algo.tracks(direction).size();
833 ? sizingData.columnTracks.size()
834 : sizingData.rowTracks.size();
835 LayoutUnit totalGuttersSize = 399 LayoutUnit totalGuttersSize =
836 guttersSize(sizingData.grid(), direction, 0, numberOfTracks, 400 guttersSize(grid, direction, 0, numberOfTracks, IntrinsicSizeComputation);
837 sizingData.sizingOperation);
838 minIntrinsicSize += totalGuttersSize; 401 minIntrinsicSize += totalGuttersSize;
839 maxIntrinsicSize += totalGuttersSize; 402 maxIntrinsicSize += totalGuttersSize;
840 403
841 #if DCHECK_IS_ON() 404 #if DCHECK_IS_ON()
842 DCHECK(tracksAreWiderThanMinTrackBreadth(direction, sizingData)); 405 DCHECK(algo.tracksAreWiderThanMinTrackBreadth());
843 #endif 406 #endif
844 } 407 }
845 408
846 LayoutUnit LayoutGrid::computeIntrinsicLogicalContentHeightUsing( 409 LayoutUnit LayoutGrid::computeIntrinsicLogicalContentHeightUsing(
847 const Length& logicalHeightLength, 410 const Length& logicalHeightLength,
848 LayoutUnit intrinsicContentHeight, 411 LayoutUnit intrinsicContentHeight,
849 LayoutUnit borderAndPadding) const { 412 LayoutUnit borderAndPadding) const {
850 if (logicalHeightLength.isMinContent()) 413 if (logicalHeightLength.isMinContent())
851 return m_minContentHeight; 414 return m_minContentHeight;
852 415
(...skipping 10 matching lines...) Expand all
863 } 426 }
864 427
865 if (logicalHeightLength.isFillAvailable()) 428 if (logicalHeightLength.isFillAvailable())
866 return containingBlock()->availableLogicalHeight( 429 return containingBlock()->availableLogicalHeight(
867 ExcludeMarginBorderPadding) - 430 ExcludeMarginBorderPadding) -
868 borderAndPadding; 431 borderAndPadding;
869 ASSERT_NOT_REACHED(); 432 ASSERT_NOT_REACHED();
870 return LayoutUnit(); 433 return LayoutUnit();
871 } 434 }
872 435
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->insert(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( 436 static LayoutUnit overrideContainingBlockContentSizeForChild(
1188 const LayoutBox& child, 437 const LayoutBox& child,
1189 GridTrackSizingDirection direction) { 438 GridTrackSizingDirection direction) {
1190 return direction == ForColumns 439 return direction == ForColumns
1191 ? child.overrideContainingBlockContentLogicalWidth() 440 ? child.overrideContainingBlockContentLogicalWidth()
1192 : child.overrideContainingBlockContentLogicalHeight(); 441 : child.overrideContainingBlockContentLogicalHeight();
1193 } 442 }
1194 443
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 { 444 bool LayoutGrid::isOrthogonalChild(const LayoutBox& child) const {
1307 return child.isHorizontalWritingMode() != isHorizontalWritingMode(); 445 return child.isHorizontalWritingMode() != isHorizontalWritingMode();
1308 } 446 }
1309 447
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.insert(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( 448 size_t LayoutGrid::computeAutoRepeatTracksCount(
1946 GridTrackSizingDirection direction, 449 GridTrackSizingDirection direction,
1947 SizingOperation sizingOperation) const { 450 SizingOperation sizingOperation) const {
1948 bool isRowAxis = direction == ForColumns; 451 bool isRowAxis = direction == ForColumns;
1949 const auto& autoRepeatTracks = isRowAxis ? styleRef().gridAutoRepeatColumns() 452 const auto& autoRepeatTracks = isRowAxis ? styleRef().gridAutoRepeatColumns()
1950 : styleRef().gridAutoRepeatRows(); 453 : styleRef().gridAutoRepeatRows();
1951 size_t autoRepeatTrackListLength = autoRepeatTracks.size(); 454 size_t autoRepeatTrackListLength = autoRepeatTracks.size();
1952 455
1953 if (!autoRepeatTrackListLength) 456 if (!autoRepeatTrackListLength)
1954 return 0; 457 return 0;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 // Clamp the number of repetitions so we don't end up with too many tracks. 548 // Clamp the number of repetitions so we don't end up with too many tracks.
2046 if (repetitions > kGridMaxTracks) { 549 if (repetitions > kGridMaxTracks) {
2047 DCHECK_GT(autoRepeatTrackListLength, 0u); 550 DCHECK_GT(autoRepeatTrackListLength, 0u);
2048 repetitions = 551 repetitions =
2049 (kGridMaxTracks - trackSizes.size()) / autoRepeatTrackListLength; 552 (kGridMaxTracks - trackSizes.size()) / autoRepeatTrackListLength;
2050 } 553 }
2051 554
2052 return repetitions * autoRepeatTrackListLength; 555 return repetitions * autoRepeatTrackListLength;
2053 } 556 }
2054 557
2055 std::unique_ptr<LayoutGrid::OrderedTrackIndexSet> 558 std::unique_ptr<OrderedTrackIndexSet>
2056 LayoutGrid::computeEmptyTracksForAutoRepeat( 559 LayoutGrid::computeEmptyTracksForAutoRepeat(
2057 Grid& grid, 560 Grid& grid,
2058 GridTrackSizingDirection direction) const { 561 GridTrackSizingDirection direction) const {
2059 bool isRowAxis = direction == ForColumns; 562 bool isRowAxis = direction == ForColumns;
2060 if ((isRowAxis && styleRef().gridAutoRepeatColumnsType() != AutoFit) || 563 if ((isRowAxis && styleRef().gridAutoRepeatColumnsType() != AutoFit) ||
2061 (!isRowAxis && styleRef().gridAutoRepeatRowsType() != AutoFit)) 564 (!isRowAxis && styleRef().gridAutoRepeatRowsType() != AutoFit))
2062 return nullptr; 565 return nullptr;
2063 566
2064 std::unique_ptr<OrderedTrackIndexSet> emptyTrackIndexes; 567 std::unique_ptr<OrderedTrackIndexSet> emptyTrackIndexes;
2065 size_t insertionPoint = isRowAxis 568 size_t insertionPoint = isRowAxis
(...skipping 16 matching lines...) Expand all
2082 if (!iterator.nextGridItem()) { 585 if (!iterator.nextGridItem()) {
2083 if (!emptyTrackIndexes) 586 if (!emptyTrackIndexes)
2084 emptyTrackIndexes = WTF::wrapUnique(new OrderedTrackIndexSet); 587 emptyTrackIndexes = WTF::wrapUnique(new OrderedTrackIndexSet);
2085 emptyTrackIndexes->add(trackIndex); 588 emptyTrackIndexes->add(trackIndex);
2086 } 589 }
2087 } 590 }
2088 } 591 }
2089 return emptyTrackIndexes; 592 return emptyTrackIndexes;
2090 } 593 }
2091 594
2092 void LayoutGrid::placeItemsOnGrid(LayoutGrid::Grid& grid, 595 void LayoutGrid::placeItemsOnGrid(Grid& grid,
2093 SizingOperation sizingOperation) const { 596 SizingOperation sizingOperation) const {
2094 size_t autoRepeatRows = 597 size_t autoRepeatRows =
2095 computeAutoRepeatTracksCount(ForRows, sizingOperation); 598 computeAutoRepeatTracksCount(ForRows, sizingOperation);
2096 size_t autoRepeatColumns = 599 size_t autoRepeatColumns =
2097 computeAutoRepeatTracksCount(ForColumns, sizingOperation); 600 computeAutoRepeatTracksCount(ForColumns, sizingOperation);
2098 if (autoRepeatRows != grid.autoRepeatTracks(ForRows) || 601 if (autoRepeatRows != grid.autoRepeatTracks(ForRows) ||
2099 autoRepeatColumns != grid.autoRepeatTracks(ForColumns)) { 602 autoRepeatColumns != grid.autoRepeatTracks(ForColumns)) {
2100 grid.setNeedsItemsPlacement(true); 603 grid.setNeedsItemsPlacement(true);
2101 grid.setAutoRepeatTracks(autoRepeatRows, autoRepeatColumns); 604 grid.setAutoRepeatTracks(autoRepeatRows, autoRepeatColumns);
2102 } 605 }
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 return tracks; 975 return tracks;
2473 } 976 }
2474 977
2475 static const StyleContentAlignmentData& contentAlignmentNormalBehavior() { 978 static const StyleContentAlignmentData& contentAlignmentNormalBehavior() {
2476 static const StyleContentAlignmentData normalBehavior = { 979 static const StyleContentAlignmentData normalBehavior = {
2477 ContentPositionNormal, ContentDistributionStretch}; 980 ContentPositionNormal, ContentDistributionStretch};
2478 return normalBehavior; 981 return normalBehavior;
2479 } 982 }
2480 983
2481 void LayoutGrid::applyStretchAlignmentToTracksIfNeeded( 984 void LayoutGrid::applyStretchAlignmentToTracksIfNeeded(
2482 GridTrackSizingDirection direction, 985 GridTrackSizingDirection direction) {
2483 GridSizingData& sizingData) { 986 LayoutUnit& availableSpace = m_trackSizingAlgorithm.freeSpace(direction);
2484 LayoutUnit& availableSpace = sizingData.freeSpace(direction);
2485 if (availableSpace <= 0 || 987 if (availableSpace <= 0 ||
2486 (direction == ForColumns && 988 (direction == ForColumns &&
2487 styleRef().resolvedJustifyContentDistribution( 989 styleRef().resolvedJustifyContentDistribution(
2488 contentAlignmentNormalBehavior()) != ContentDistributionStretch) || 990 contentAlignmentNormalBehavior()) != ContentDistributionStretch) ||
2489 (direction == ForRows && 991 (direction == ForRows &&
2490 styleRef().resolvedAlignContentDistribution( 992 styleRef().resolvedAlignContentDistribution(
2491 contentAlignmentNormalBehavior()) != ContentDistributionStretch)) 993 contentAlignmentNormalBehavior()) != ContentDistributionStretch))
2492 return; 994 return;
2493 995
2494 // Spec defines auto-sized tracks as the ones with an 'auto' max-sizing 996 // Spec defines auto-sized tracks as the ones with an 'auto' max-sizing
2495 // function. 997 // function.
2496 Vector<GridTrack>& tracks = (direction == ForColumns) 998 Vector<GridTrack>& allTracks = m_trackSizingAlgorithm.tracks(direction);
2497 ? sizingData.columnTracks
2498 : sizingData.rowTracks;
2499 Vector<unsigned> autoSizedTracksIndex; 999 Vector<unsigned> autoSizedTracksIndex;
2500 for (unsigned i = 0; i < tracks.size(); ++i) { 1000 for (unsigned i = 0; i < allTracks.size(); ++i) {
2501 const GridTrackSize& trackSize = gridTrackSize(direction, i, sizingData); 1001 const GridTrackSize& trackSize =
1002 m_trackSizingAlgorithm.gridTrackSize(direction, i, TrackSizing);
2502 if (trackSize.hasAutoMaxTrackBreadth()) 1003 if (trackSize.hasAutoMaxTrackBreadth())
2503 autoSizedTracksIndex.push_back(i); 1004 autoSizedTracksIndex.push_back(i);
2504 } 1005 }
2505 1006
2506 unsigned numberOfAutoSizedTracks = autoSizedTracksIndex.size(); 1007 unsigned numberOfAutoSizedTracks = autoSizedTracksIndex.size();
2507 if (numberOfAutoSizedTracks < 1) 1008 if (numberOfAutoSizedTracks < 1)
2508 return; 1009 return;
2509 1010
2510 LayoutUnit sizeToIncrease = availableSpace / numberOfAutoSizedTracks; 1011 LayoutUnit sizeToIncrease = availableSpace / numberOfAutoSizedTracks;
2511 for (const auto& trackIndex : autoSizedTracksIndex) { 1012 for (const auto& trackIndex : autoSizedTracksIndex) {
2512 GridTrack* track = tracks.data() + trackIndex; 1013 GridTrack* track = allTracks.data() + trackIndex;
2513 LayoutUnit baseSize = track->baseSize() + sizeToIncrease; 1014 LayoutUnit baseSize = track->baseSize() + sizeToIncrease;
2514 track->setBaseSize(baseSize); 1015 track->setBaseSize(baseSize);
2515 } 1016 }
1017
2516 availableSpace = LayoutUnit(); 1018 availableSpace = LayoutUnit();
2517 } 1019 }
2518 1020
2519 void LayoutGrid::layoutGridItems(GridSizingData& sizingData) { 1021 void LayoutGrid::layoutGridItems() {
2520 DCHECK_EQ(sizingData.sizingOperation, TrackSizing); 1022 populateGridPositionsForDirection(ForColumns);
2521 populateGridPositionsForDirection(sizingData, ForColumns); 1023 populateGridPositionsForDirection(ForRows);
2522 populateGridPositionsForDirection(sizingData, ForRows);
2523 m_gridItemsOverflowingGridArea.resize(0); 1024 m_gridItemsOverflowingGridArea.resize(0);
2524 1025
2525 for (LayoutBox* child = firstChildBox(); child; 1026 for (LayoutBox* child = firstChildBox(); child;
2526 child = child->nextSiblingBox()) { 1027 child = child->nextSiblingBox()) {
2527 if (child->isOutOfFlowPositioned()) { 1028 if (child->isOutOfFlowPositioned()) {
2528 prepareChildForPositionedLayout(*child); 1029 prepareChildForPositionedLayout(*child);
2529 continue; 1030 continue;
2530 } 1031 }
2531 1032
2532 // Because the grid area cannot be styled, we don't need to adjust 1033 // Because the grid area cannot be styled, we don't need to adjust
2533 // the grid breadth to account for 'box-sizing'. 1034 // the grid breadth to account for 'box-sizing'.
2534 LayoutUnit oldOverrideContainingBlockContentLogicalWidth = 1035 LayoutUnit oldOverrideContainingBlockContentLogicalWidth =
2535 child->hasOverrideContainingBlockLogicalWidth() 1036 child->hasOverrideContainingBlockLogicalWidth()
2536 ? child->overrideContainingBlockContentLogicalWidth() 1037 ? child->overrideContainingBlockContentLogicalWidth()
2537 : LayoutUnit(); 1038 : LayoutUnit();
2538 LayoutUnit oldOverrideContainingBlockContentLogicalHeight = 1039 LayoutUnit oldOverrideContainingBlockContentLogicalHeight =
2539 child->hasOverrideContainingBlockLogicalHeight() 1040 child->hasOverrideContainingBlockLogicalHeight()
2540 ? child->overrideContainingBlockContentLogicalHeight() 1041 ? child->overrideContainingBlockContentLogicalHeight()
2541 : LayoutUnit(); 1042 : LayoutUnit();
2542 1043
2543 LayoutUnit overrideContainingBlockContentLogicalWidth = 1044 LayoutUnit overrideContainingBlockContentLogicalWidth =
2544 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForColumns, 1045 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForColumns);
2545 sizingData);
2546 LayoutUnit overrideContainingBlockContentLogicalHeight = 1046 LayoutUnit overrideContainingBlockContentLogicalHeight =
2547 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows, 1047 gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows);
2548 sizingData);
2549 1048
2550 if (oldOverrideContainingBlockContentLogicalWidth != 1049 if (oldOverrideContainingBlockContentLogicalWidth !=
2551 overrideContainingBlockContentLogicalWidth || 1050 overrideContainingBlockContentLogicalWidth ||
2552 (oldOverrideContainingBlockContentLogicalHeight != 1051 (oldOverrideContainingBlockContentLogicalHeight !=
2553 overrideContainingBlockContentLogicalHeight && 1052 overrideContainingBlockContentLogicalHeight &&
2554 child->hasRelativeLogicalHeight())) 1053 child->hasRelativeLogicalHeight()))
2555 child->setNeedsLayout(LayoutInvalidationReason::GridChanged); 1054 child->setNeedsLayout(LayoutInvalidationReason::GridChanged);
2556 1055
2557 child->setOverrideContainingBlockContentLogicalWidth( 1056 child->setOverrideContainingBlockContentLogicalWidth(
2558 overrideContainingBlockContentLogicalWidth); 1057 overrideContainingBlockContentLogicalWidth);
2559 child->setOverrideContainingBlockContentLogicalHeight( 1058 child->setOverrideContainingBlockContentLogicalHeight(
2560 overrideContainingBlockContentLogicalHeight); 1059 overrideContainingBlockContentLogicalHeight);
2561 1060
2562 // Stretching logic might force a child layout, so we need to run it before 1061 // Stretching logic might force a child layout, so we need to run it before
2563 // the layoutIfNeeded call to avoid unnecessary relayouts. This might imply 1062 // the layoutIfNeeded call to avoid unnecessary relayouts. This might imply
2564 // that child margins, needed to correctly determine the available space 1063 // that child margins, needed to correctly determine the available space
2565 // before stretching, are not set yet. 1064 // before stretching, are not set yet.
2566 applyStretchAlignmentToChildIfNeeded(*child); 1065 applyStretchAlignmentToChildIfNeeded(*child);
2567 1066
2568 child->layoutIfNeeded(); 1067 child->layoutIfNeeded();
2569 1068
2570 // We need pending layouts to be done in order to compute auto-margins 1069 // We need pending layouts to be done in order to compute auto-margins
2571 // properly. 1070 // properly.
2572 updateAutoMarginsInColumnAxisIfNeeded(*child); 1071 updateAutoMarginsInColumnAxisIfNeeded(*child);
2573 updateAutoMarginsInRowAxisIfNeeded(*child); 1072 updateAutoMarginsInRowAxisIfNeeded(*child);
2574 1073
2575 const GridArea& area = sizingData.grid().gridItemArea(*child); 1074 const GridArea& area = m_grid.gridItemArea(*child);
2576 #if DCHECK_IS_ON() 1075 #if DCHECK_IS_ON()
2577 ASSERT(area.columns.startLine() < sizingData.columnTracks.size()); 1076 DCHECK(area.columns.startLine() <
2578 ASSERT(area.rows.startLine() < sizingData.rowTracks.size()); 1077 m_trackSizingAlgorithm.tracks(ForColumns).size());
1078 DCHECK(area.rows.startLine() <
1079 m_trackSizingAlgorithm.tracks(ForRows).size());
2579 #endif 1080 #endif
2580 child->setLogicalLocation(findChildLogicalPosition(*child, sizingData)); 1081 child->setLogicalLocation(findChildLogicalPosition(*child));
2581 1082
2582 // Keep track of children overflowing their grid area as we might need to 1083 // Keep track of children overflowing their grid area as we might need to
2583 // paint them even if the grid-area is not visible. Using physical 1084 // paint them even if the grid-area is not visible. Using physical
2584 // dimensions for simplicity, so we can forget about orthogonalty. 1085 // dimensions for simplicity, so we can forget about orthogonalty.
2585 LayoutUnit childGridAreaHeight = 1086 LayoutUnit childGridAreaHeight =
2586 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalHeight 1087 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalHeight
2587 : overrideContainingBlockContentLogicalWidth; 1088 : overrideContainingBlockContentLogicalWidth;
2588 LayoutUnit childGridAreaWidth = 1089 LayoutUnit childGridAreaWidth =
2589 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalWidth 1090 isHorizontalWritingMode() ? overrideContainingBlockContentLogicalWidth
2590 : overrideContainingBlockContentLogicalHeight; 1091 : overrideContainingBlockContentLogicalHeight;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2737 1238
2738 if (endLine > 0 && endLine < lastLine) { 1239 if (endLine > 0 && endLine < lastLine) {
2739 DCHECK(!m_grid.needsItemsPlacement()); 1240 DCHECK(!m_grid.needsItemsPlacement());
2740 offset += guttersSize(m_grid, direction, endLine - 1, 2, TrackSizing); 1241 offset += guttersSize(m_grid, direction, endLine - 1, 2, TrackSizing);
2741 offset += isForColumns ? m_offsetBetweenColumns : m_offsetBetweenRows; 1242 offset += isForColumns ? m_offsetBetweenColumns : m_offsetBetweenRows;
2742 } 1243 }
2743 } 1244 }
2744 } 1245 }
2745 } 1246 }
2746 1247
2747 LayoutUnit LayoutGrid::assumedRowsSizeForOrthogonalChild(
2748 const LayoutBox& child,
2749 const GridSizingData& sizingData) const {
2750 DCHECK(isOrthogonalChild(child));
2751 const Grid& grid = sizingData.grid();
2752 const GridSpan& span = grid.gridItemSpan(child, ForRows);
2753 LayoutUnit gridAreaSize;
2754 bool gridAreaIsIndefinite = false;
2755 LayoutUnit containingBlockAvailableSize =
2756 containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
2757 for (auto trackPosition : span) {
2758 GridLength maxTrackSize =
2759 gridTrackSize(ForRows, trackPosition, sizingData).maxTrackBreadth();
2760 if (maxTrackSize.isContentSized() || maxTrackSize.isFlex())
2761 gridAreaIsIndefinite = true;
2762 else
2763 gridAreaSize +=
2764 valueForLength(maxTrackSize.length(), containingBlockAvailableSize);
2765 }
2766
2767 gridAreaSize += guttersSize(grid, ForRows, span.startLine(),
2768 span.integerSpan(), sizingData.sizingOperation);
2769
2770 return gridAreaIsIndefinite
2771 ? std::max(child.maxPreferredLogicalWidth(), gridAreaSize)
2772 : gridAreaSize;
2773 }
2774
2775 LayoutUnit LayoutGrid::gridAreaBreadthForChild(
2776 const LayoutBox& child,
2777 GridTrackSizingDirection direction,
2778 const GridSizingData& sizingData) const {
2779 // To determine the column track's size based on an orthogonal grid item we
2780 // need it's logical height, which may depend on the row track's size. It's
2781 // possible that the row tracks sizing logic has not been performed yet, so we
2782 // will need to do an estimation.
2783 if (direction == ForRows &&
2784 sizingData.sizingState == GridSizingData::ColumnSizingFirstIteration)
2785 return assumedRowsSizeForOrthogonalChild(child, sizingData);
2786
2787 const Vector<GridTrack>& tracks =
2788 direction == ForColumns ? sizingData.columnTracks : sizingData.rowTracks;
2789 const GridSpan& span = sizingData.grid().gridItemSpan(child, direction);
2790 LayoutUnit gridAreaBreadth;
2791 for (const auto& trackPosition : span)
2792 gridAreaBreadth += tracks[trackPosition].baseSize();
2793
2794 gridAreaBreadth +=
2795 guttersSize(sizingData.grid(), direction, span.startLine(),
2796 span.integerSpan(), sizingData.sizingOperation);
2797
2798 return gridAreaBreadth;
2799 }
2800
2801 LayoutUnit LayoutGrid::gridAreaBreadthForChildIncludingAlignmentOffsets( 1248 LayoutUnit LayoutGrid::gridAreaBreadthForChildIncludingAlignmentOffsets(
2802 const LayoutBox& child, 1249 const LayoutBox& child,
2803 GridTrackSizingDirection direction, 1250 GridTrackSizingDirection direction) const {
2804 const GridSizingData& sizingData) const {
2805 // We need the cached value when available because Content Distribution 1251 // We need the cached value when available because Content Distribution
2806 // alignment properties may have some influence in the final grid area 1252 // alignment properties may have some influence in the final grid area
2807 // breadth. 1253 // breadth.
2808 const Vector<GridTrack>& tracks = (direction == ForColumns) 1254 const Vector<GridTrack>& tracks = m_trackSizingAlgorithm.tracks(direction);
2809 ? sizingData.columnTracks 1255 const GridSpan& span =
2810 : sizingData.rowTracks; 1256 m_trackSizingAlgorithm.grid().gridItemSpan(child, direction);
2811 const GridSpan& span = sizingData.grid().gridItemSpan(child, direction);
2812 const Vector<LayoutUnit>& linePositions = 1257 const Vector<LayoutUnit>& linePositions =
2813 (direction == ForColumns) ? m_columnPositions : m_rowPositions; 1258 (direction == ForColumns) ? m_columnPositions : m_rowPositions;
2814 LayoutUnit initialTrackPosition = linePositions[span.startLine()]; 1259 LayoutUnit initialTrackPosition = linePositions[span.startLine()];
2815 LayoutUnit finalTrackPosition = linePositions[span.endLine() - 1]; 1260 LayoutUnit finalTrackPosition = linePositions[span.endLine() - 1];
2816 // Track Positions vector stores the 'start' grid line of each track, so we 1261 // Track Positions vector stores the 'start' grid line of each track, so we
2817 // have to add last track's baseSize. 1262 // have to add last track's baseSize.
2818 return finalTrackPosition - initialTrackPosition + 1263 return finalTrackPosition - initialTrackPosition +
2819 tracks[span.endLine() - 1].baseSize(); 1264 tracks[span.endLine() - 1].baseSize();
2820 } 1265 }
2821 1266
2822 void LayoutGrid::populateGridPositionsForDirection( 1267 void LayoutGrid::populateGridPositionsForDirection(
2823 GridSizingData& sizingData,
2824 GridTrackSizingDirection direction) { 1268 GridTrackSizingDirection direction) {
2825 // Since we add alignment offsets and track gutters, grid lines are not always 1269 // Since we add alignment offsets and track gutters, grid lines are not always
2826 // adjacent. Hence we will have to assume from now on that we just store 1270 // adjacent. Hence we will have to assume from now on that we just store
2827 // positions of the initial grid lines of each track, except the last one, 1271 // positions of the initial grid lines of each track, except the last one,
2828 // which is the only one considered as a final grid line of a track. 1272 // which is the only one considered as a final grid line of a track.
2829 1273
2830 // The grid container's frame elements (border, padding and <content-position> 1274 // The grid container's frame elements (border, padding and <content-position>
2831 // offset) are sensible to the inline-axis flow direction. However, column 1275 // offset) are sensible to the inline-axis flow direction. However, column
2832 // lines positions are 'direction' unaware. This simplification allows us to 1276 // lines positions are 'direction' unaware. This simplification allows us to
2833 // use the same indexes to identify the columns independently on the 1277 // use the same indexes to identify the columns independently on the
2834 // inline-axis direction. 1278 // inline-axis direction.
2835 bool isRowAxis = direction == ForColumns; 1279 bool isRowAxis = direction == ForColumns;
2836 auto& tracks = isRowAxis ? sizingData.columnTracks : sizingData.rowTracks; 1280 auto& tracks = m_trackSizingAlgorithm.tracks(direction);
2837 size_t numberOfTracks = tracks.size(); 1281 size_t numberOfTracks = tracks.size();
2838 size_t numberOfLines = numberOfTracks + 1; 1282 size_t numberOfLines = numberOfTracks + 1;
2839 size_t lastLine = numberOfLines - 1; 1283 size_t lastLine = numberOfLines - 1;
2840 ContentAlignmentData offset = computeContentPositionAndDistributionOffset( 1284 ContentAlignmentData offset = computeContentPositionAndDistributionOffset(
2841 direction, sizingData.freeSpace(direction), numberOfTracks); 1285 direction, m_trackSizingAlgorithm.freeSpace(direction), numberOfTracks);
2842 auto& positions = isRowAxis ? m_columnPositions : m_rowPositions; 1286 auto& positions = isRowAxis ? m_columnPositions : m_rowPositions;
2843 positions.resize(numberOfLines); 1287 positions.resize(numberOfLines);
2844 auto borderAndPadding = 1288 auto borderAndPadding =
2845 isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore(); 1289 isRowAxis ? borderAndPaddingLogicalLeft() : borderAndPaddingBefore();
2846 positions[0] = borderAndPadding + offset.positionOffset; 1290 positions[0] = borderAndPadding + offset.positionOffset;
2847 const Grid& grid = sizingData.grid(); 1291 const Grid& grid = m_trackSizingAlgorithm.grid();
2848 if (numberOfLines > 1) { 1292 if (numberOfLines > 1) {
2849 // If we have collapsed tracks we just ignore gaps here and add them later 1293 // If we have collapsed tracks we just ignore gaps here and add them later
2850 // as we might not compute the gap between two consecutive tracks without 1294 // as we might not compute the gap between two consecutive tracks without
2851 // examining the surrounding ones. 1295 // examining the surrounding ones.
2852 bool hasCollapsedTracks = grid.hasAutoRepeatEmptyTracks(direction); 1296 bool hasCollapsedTracks = grid.hasAutoRepeatEmptyTracks(direction);
2853 LayoutUnit gap = 1297 LayoutUnit gap = !hasCollapsedTracks
2854 !hasCollapsedTracks 1298 ? gridGapForDirection(direction, TrackSizing)
2855 ? gridGapForDirection(direction, sizingData.sizingOperation) 1299 : LayoutUnit();
2856 : LayoutUnit();
2857 size_t nextToLastLine = numberOfLines - 2; 1300 size_t nextToLastLine = numberOfLines - 2;
2858 for (size_t i = 0; i < nextToLastLine; ++i) 1301 for (size_t i = 0; i < nextToLastLine; ++i)
2859 positions[i + 1] = 1302 positions[i + 1] =
2860 positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap; 1303 positions[i] + offset.distributionOffset + tracks[i].baseSize() + gap;
2861 positions[lastLine] = 1304 positions[lastLine] =
2862 positions[nextToLastLine] + tracks[nextToLastLine].baseSize(); 1305 positions[nextToLastLine] + tracks[nextToLastLine].baseSize();
2863 1306
2864 // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to 1307 // Adjust collapsed gaps. Collapsed tracks cause the surrounding gutters to
2865 // collapse (they coincide exactly) except on the edges of the grid where 1308 // collapse (they coincide exactly) except on the edges of the grid where
2866 // they become 0. 1309 // they become 0.
2867 if (hasCollapsedTracks) { 1310 if (hasCollapsedTracks) {
2868 gap = gridGapForDirection(direction, sizingData.sizingOperation); 1311 gap = gridGapForDirection(direction, TrackSizing);
2869 size_t remainingEmptyTracks = 1312 size_t remainingEmptyTracks =
2870 grid.autoRepeatEmptyTracks(direction)->size(); 1313 grid.autoRepeatEmptyTracks(direction)->size();
2871 LayoutUnit gapAccumulator; 1314 LayoutUnit gapAccumulator;
2872 for (size_t i = 1; i < lastLine; ++i) { 1315 for (size_t i = 1; i < lastLine; ++i) {
2873 if (grid.isEmptyAutoRepeatTrack(direction, i - 1)) { 1316 if (grid.isEmptyAutoRepeatTrack(direction, i - 1)) {
2874 --remainingEmptyTracks; 1317 --remainingEmptyTracks;
2875 } else { 1318 } else {
2876 // Add gap between consecutive non empty tracks. Add it also just once 1319 // Add gap between consecutive non empty tracks. Add it also just once
2877 // for an arbitrary number of empty tracks between two non empty ones. 1320 // for an arbitrary number of empty tracks between two non empty ones.
2878 bool allRemainingTracksAreEmpty = 1321 bool allRemainingTracksAreEmpty =
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 const LayoutBox& child) const { 1413 const LayoutBox& child) const {
2971 if (!child.isAnonymous()) 1414 if (!child.isAnonymous())
2972 return child.styleRef().resolvedJustifySelf(ItemPositionStretch); 1415 return child.styleRef().resolvedJustifySelf(ItemPositionStretch);
2973 // All the 'auto' values has been solved by the StyleAdjuster, but it's 1416 // All the 'auto' values has been solved by the StyleAdjuster, but it's
2974 // possible that some grid items generate Anonymous boxes, which need to be 1417 // possible that some grid items generate Anonymous boxes, which need to be
2975 // solved during layout. 1418 // solved during layout.
2976 return child.styleRef().resolvedJustifySelf(selfAlignmentNormalBehavior(), 1419 return child.styleRef().resolvedJustifySelf(selfAlignmentNormalBehavior(),
2977 style()); 1420 style());
2978 } 1421 }
2979 1422
1423 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild(
1424 const LayoutBox& child,
1425 GridTrackSizingDirection direction) const {
1426 return !isOrthogonalChild(child)
1427 ? direction
1428 : (direction == ForColumns ? ForRows : ForColumns);
1429 }
1430
2980 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to 1431 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to
2981 // LayoutBox. 1432 // LayoutBox.
2982 void LayoutGrid::applyStretchAlignmentToChildIfNeeded(LayoutBox& child) { 1433 void LayoutGrid::applyStretchAlignmentToChildIfNeeded(LayoutBox& child) {
2983 // We clear height override values because we will decide now whether it's 1434 // We clear height override values because we will decide now whether it's
2984 // allowed or not, evaluating the conditions which might have changed since 1435 // allowed or not, evaluating the conditions which might have changed since
2985 // the old values were set. 1436 // the old values were set.
2986 child.clearOverrideLogicalContentHeight(); 1437 child.clearOverrideLogicalContentHeight();
2987 1438
2988 GridTrackSizingDirection childBlockDirection = 1439 GridTrackSizingDirection childBlockDirection =
2989 flowAwareDirectionForChild(child, ForRows); 1440 flowAwareDirectionForChild(child, ForRows);
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
3335 return GridAxisStart; 1786 return GridAxisStart;
3336 case ItemPositionAuto: 1787 case ItemPositionAuto:
3337 case ItemPositionNormal: 1788 case ItemPositionNormal:
3338 break; 1789 break;
3339 } 1790 }
3340 1791
3341 ASSERT_NOT_REACHED(); 1792 ASSERT_NOT_REACHED();
3342 return GridAxisStart; 1793 return GridAxisStart;
3343 } 1794 }
3344 1795
3345 LayoutUnit LayoutGrid::columnAxisOffsetForChild( 1796 LayoutUnit LayoutGrid::columnAxisOffsetForChild(const LayoutBox& child) const {
3346 const LayoutBox& child, 1797 const GridSpan& rowsSpan =
3347 GridSizingData& sizingData) const { 1798 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForRows);
3348 const GridSpan& rowsSpan = sizingData.grid().gridItemSpan(child, ForRows);
3349 size_t childStartLine = rowsSpan.startLine(); 1799 size_t childStartLine = rowsSpan.startLine();
3350 LayoutUnit startOfRow = m_rowPositions[childStartLine]; 1800 LayoutUnit startOfRow = m_rowPositions[childStartLine];
3351 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); 1801 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
3352 if (hasAutoMarginsInColumnAxis(child)) 1802 if (hasAutoMarginsInColumnAxis(child))
3353 return startPosition; 1803 return startPosition;
3354 GridAxisPosition axisPosition = columnAxisPositionForChild(child); 1804 GridAxisPosition axisPosition = columnAxisPositionForChild(child);
3355 switch (axisPosition) { 1805 switch (axisPosition) {
3356 case GridAxisStart: 1806 case GridAxisStart:
3357 return startPosition; 1807 return startPosition;
3358 case GridAxisEnd: 1808 case GridAxisEnd:
3359 case GridAxisCenter: { 1809 case GridAxisCenter: {
3360 size_t childEndLine = rowsSpan.endLine(); 1810 size_t childEndLine = rowsSpan.endLine();
3361 LayoutUnit endOfRow = m_rowPositions[childEndLine]; 1811 LayoutUnit endOfRow = m_rowPositions[childEndLine];
3362 // m_rowPositions include distribution offset (because of content 1812 // m_rowPositions include distribution offset (because of content
3363 // alignment) and gutters so we need to subtract them to get the actual 1813 // alignment) and gutters so we need to subtract them to get the actual
3364 // end position for a given row (this does not have to be done for the 1814 // end position for a given row (this does not have to be done for the
3365 // last track as there are no more m_columnPositions after it). 1815 // last track as there are no more m_columnPositions after it).
3366 LayoutUnit trackGap = 1816 LayoutUnit trackGap = gridGapForDirection(ForRows, TrackSizing);
3367 gridGapForDirection(ForRows, sizingData.sizingOperation);
3368 if (childEndLine < m_rowPositions.size() - 1) { 1817 if (childEndLine < m_rowPositions.size() - 1) {
3369 endOfRow -= trackGap; 1818 endOfRow -= trackGap;
3370 endOfRow -= m_offsetBetweenRows; 1819 endOfRow -= m_offsetBetweenRows;
3371 } 1820 }
3372 LayoutUnit columnAxisChildSize = 1821 LayoutUnit columnAxisChildSize =
3373 isOrthogonalChild(child) 1822 isOrthogonalChild(child)
3374 ? child.logicalWidth() + child.marginLogicalWidth() 1823 ? child.logicalWidth() + child.marginLogicalWidth()
3375 : child.logicalHeight() + child.marginLogicalHeight(); 1824 : child.logicalHeight() + child.marginLogicalHeight();
3376 OverflowAlignment overflow = alignSelfForChild(child).overflow(); 1825 OverflowAlignment overflow = alignSelfForChild(child).overflow();
3377 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset( 1826 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(
3378 overflow, endOfRow - startOfRow, columnAxisChildSize); 1827 overflow, endOfRow - startOfRow, columnAxisChildSize);
3379 return startPosition + (axisPosition == GridAxisEnd 1828 return startPosition + (axisPosition == GridAxisEnd
3380 ? offsetFromStartPosition 1829 ? offsetFromStartPosition
3381 : offsetFromStartPosition / 2); 1830 : offsetFromStartPosition / 2);
3382 } 1831 }
3383 } 1832 }
3384 1833
3385 ASSERT_NOT_REACHED(); 1834 ASSERT_NOT_REACHED();
3386 return LayoutUnit(); 1835 return LayoutUnit();
3387 } 1836 }
3388 1837
3389 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child, 1838 LayoutUnit LayoutGrid::rowAxisOffsetForChild(const LayoutBox& child) const {
3390 GridSizingData& sizingData) const {
3391 const GridSpan& columnsSpan = 1839 const GridSpan& columnsSpan =
3392 sizingData.grid().gridItemSpan(child, ForColumns); 1840 m_trackSizingAlgorithm.grid().gridItemSpan(child, ForColumns);
3393 size_t childStartLine = columnsSpan.startLine(); 1841 size_t childStartLine = columnsSpan.startLine();
3394 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; 1842 LayoutUnit startOfColumn = m_columnPositions[childStartLine];
3395 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); 1843 LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
3396 if (hasAutoMarginsInRowAxis(child)) 1844 if (hasAutoMarginsInRowAxis(child))
3397 return startPosition; 1845 return startPosition;
3398 GridAxisPosition axisPosition = rowAxisPositionForChild(child); 1846 GridAxisPosition axisPosition = rowAxisPositionForChild(child);
3399 switch (axisPosition) { 1847 switch (axisPosition) {
3400 case GridAxisStart: 1848 case GridAxisStart:
3401 return startPosition; 1849 return startPosition;
3402 case GridAxisEnd: 1850 case GridAxisEnd:
3403 case GridAxisCenter: { 1851 case GridAxisCenter: {
3404 size_t childEndLine = columnsSpan.endLine(); 1852 size_t childEndLine = columnsSpan.endLine();
3405 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; 1853 LayoutUnit endOfColumn = m_columnPositions[childEndLine];
3406 // m_columnPositions include distribution offset (because of content 1854 // m_columnPositions include distribution offset (because of content
3407 // alignment) and gutters so we need to subtract them to get the actual 1855 // alignment) and gutters so we need to subtract them to get the actual
3408 // end position for a given column (this does not have to be done for the 1856 // end position for a given column (this does not have to be done for the
3409 // last track as there are no more m_columnPositions after it). 1857 // last track as there are no more m_columnPositions after it).
3410 LayoutUnit trackGap = 1858 LayoutUnit trackGap = gridGapForDirection(ForColumns, TrackSizing);
3411 gridGapForDirection(ForColumns, sizingData.sizingOperation);
3412 if (childEndLine < m_columnPositions.size() - 1) { 1859 if (childEndLine < m_columnPositions.size() - 1) {
3413 endOfColumn -= trackGap; 1860 endOfColumn -= trackGap;
3414 endOfColumn -= m_offsetBetweenColumns; 1861 endOfColumn -= m_offsetBetweenColumns;
3415 } 1862 }
3416 LayoutUnit rowAxisChildSize = 1863 LayoutUnit rowAxisChildSize =
3417 isOrthogonalChild(child) 1864 isOrthogonalChild(child)
3418 ? child.logicalHeight() + child.marginLogicalHeight() 1865 ? child.logicalHeight() + child.marginLogicalHeight()
3419 : child.logicalWidth() + child.marginLogicalWidth(); 1866 : child.logicalWidth() + child.marginLogicalWidth();
3420 OverflowAlignment overflow = justifySelfForChild(child).overflow(); 1867 OverflowAlignment overflow = justifySelfForChild(child).overflow();
3421 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset( 1868 LayoutUnit offsetFromStartPosition = computeOverflowAlignmentOffset(
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3562 2009
3563 LayoutUnit LayoutGrid::translateRTLCoordinate(LayoutUnit coordinate) const { 2010 LayoutUnit LayoutGrid::translateRTLCoordinate(LayoutUnit coordinate) const {
3564 ASSERT(!styleRef().isLeftToRightDirection()); 2011 ASSERT(!styleRef().isLeftToRightDirection());
3565 2012
3566 LayoutUnit alignmentOffset = m_columnPositions[0]; 2013 LayoutUnit alignmentOffset = m_columnPositions[0];
3567 LayoutUnit rightGridEdgePosition = 2014 LayoutUnit rightGridEdgePosition =
3568 m_columnPositions[m_columnPositions.size() - 1]; 2015 m_columnPositions[m_columnPositions.size() - 1];
3569 return rightGridEdgePosition + alignmentOffset - coordinate; 2016 return rightGridEdgePosition + alignmentOffset - coordinate;
3570 } 2017 }
3571 2018
3572 LayoutPoint LayoutGrid::findChildLogicalPosition( 2019 LayoutPoint LayoutGrid::findChildLogicalPosition(const LayoutBox& child) const {
3573 const LayoutBox& child, 2020 LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child);
3574 GridSizingData& sizingData) const { 2021 LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child);
3575 LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child, sizingData);
3576 LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child, sizingData);
3577 // We stored m_columnPosition's data ignoring the direction, hence we might 2022 // We stored m_columnPosition's data ignoring the direction, hence we might
3578 // need now to translate positions from RTL to LTR, as it's more convenient 2023 // need now to translate positions from RTL to LTR, as it's more convenient
3579 // for painting. 2024 // for painting.
3580 if (!style()->isLeftToRightDirection()) 2025 if (!style()->isLeftToRightDirection())
3581 rowAxisOffset = translateRTLCoordinate(rowAxisOffset) - 2026 rowAxisOffset = translateRTLCoordinate(rowAxisOffset) -
3582 (isOrthogonalChild(child) ? child.logicalHeight() 2027 (isOrthogonalChild(child) ? child.logicalHeight()
3583 : child.logicalWidth()); 2028 : child.logicalWidth());
3584 2029
3585 // "In the positioning phase [...] calculations are performed according to the 2030 // "In the positioning phase [...] calculations are performed according to the
3586 // writing mode of the containing block of the box establishing the orthogonal 2031 // writing mode of the containing block of the box establishing the orthogonal
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3628 if (direction == ForRows) 2073 if (direction == ForRows)
3629 return grid.numTracks(ForRows); 2074 return grid.numTracks(ForRows);
3630 2075
3631 return grid.numTracks(ForRows) 2076 return grid.numTracks(ForRows)
3632 ? grid.numTracks(ForColumns) 2077 ? grid.numTracks(ForColumns)
3633 : GridPositionsResolver::explicitGridColumnCount( 2078 : GridPositionsResolver::explicitGridColumnCount(
3634 styleRef(), grid.autoRepeatTracks(ForColumns)); 2079 styleRef(), grid.autoRepeatTracks(ForColumns));
3635 } 2080 }
3636 2081
3637 } // namespace blink 2082 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698