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