| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/layout/Grid.h" |
| 6 |
| 7 #include "core/layout/LayoutGrid.h" |
| 8 |
| 9 namespace blink { |
| 10 |
| 11 Grid::Grid(const LayoutGrid* grid) : m_orderIterator(grid) {} |
| 12 |
| 13 size_t Grid::numTracks(GridTrackSizingDirection direction) const { |
| 14 if (direction == ForRows) |
| 15 return m_grid.size(); |
| 16 return m_grid.size() ? m_grid[0].size() : 0; |
| 17 } |
| 18 |
| 19 void Grid::ensureGridSize(size_t maximumRowSize, size_t maximumColumnSize) { |
| 20 const size_t oldRowSize = numTracks(ForRows); |
| 21 if (maximumRowSize > oldRowSize) { |
| 22 m_grid.grow(maximumRowSize); |
| 23 for (size_t row = oldRowSize; row < numTracks(ForRows); ++row) |
| 24 m_grid[row].grow(numTracks(ForColumns)); |
| 25 } |
| 26 |
| 27 if (maximumColumnSize > numTracks(ForColumns)) { |
| 28 for (size_t row = 0; row < numTracks(ForRows); ++row) |
| 29 m_grid[row].grow(maximumColumnSize); |
| 30 } |
| 31 } |
| 32 |
| 33 void Grid::insert(LayoutBox& child, const GridArea& area) { |
| 34 DCHECK(area.rows.isTranslatedDefinite() && |
| 35 area.columns.isTranslatedDefinite()); |
| 36 ensureGridSize(area.rows.endLine(), area.columns.endLine()); |
| 37 |
| 38 for (const auto& row : area.rows) { |
| 39 for (const auto& column : area.columns) |
| 40 m_grid[row][column].push_back(&child); |
| 41 } |
| 42 |
| 43 setGridItemArea(child, area); |
| 44 } |
| 45 |
| 46 void Grid::setSmallestTracksStart(int rowStart, int columnStart) { |
| 47 m_smallestRowStart = rowStart; |
| 48 m_smallestColumnStart = columnStart; |
| 49 } |
| 50 |
| 51 int Grid::smallestTrackStart(GridTrackSizingDirection direction) const { |
| 52 return direction == ForRows ? m_smallestRowStart : m_smallestColumnStart; |
| 53 } |
| 54 |
| 55 GridArea Grid::gridItemArea(const LayoutBox& item) const { |
| 56 DCHECK(m_gridItemArea.contains(&item)); |
| 57 return m_gridItemArea.get(&item); |
| 58 } |
| 59 |
| 60 void Grid::setGridItemArea(const LayoutBox& item, GridArea area) { |
| 61 m_gridItemArea.set(&item, area); |
| 62 } |
| 63 |
| 64 size_t Grid::gridItemPaintOrder(const LayoutBox& item) const { |
| 65 return m_gridItemsIndexesMap.get(&item); |
| 66 } |
| 67 |
| 68 void Grid::setGridItemPaintOrder(const LayoutBox& item, size_t order) { |
| 69 m_gridItemsIndexesMap.set(&item, order); |
| 70 } |
| 71 |
| 72 const GridCell& Grid::cell(size_t row, size_t column) const { |
| 73 return m_grid[row][column]; |
| 74 } |
| 75 |
| 76 #if DCHECK_IS_ON() |
| 77 bool Grid::hasAnyGridItemPaintOrder() const { |
| 78 return !m_gridItemsIndexesMap.isEmpty(); |
| 79 } |
| 80 #endif |
| 81 |
| 82 void Grid::setAutoRepeatTracks(size_t autoRepeatRows, |
| 83 size_t autoRepeatColumns) { |
| 84 m_autoRepeatRows = autoRepeatRows; |
| 85 m_autoRepeatColumns = autoRepeatColumns; |
| 86 } |
| 87 |
| 88 size_t Grid::autoRepeatTracks(GridTrackSizingDirection direction) const { |
| 89 return direction == ForRows ? m_autoRepeatRows : m_autoRepeatColumns; |
| 90 } |
| 91 |
| 92 void Grid::setAutoRepeatEmptyColumns( |
| 93 std::unique_ptr<OrderedTrackIndexSet> autoRepeatEmptyColumns) { |
| 94 m_autoRepeatEmptyColumns = std::move(autoRepeatEmptyColumns); |
| 95 } |
| 96 |
| 97 void Grid::setAutoRepeatEmptyRows( |
| 98 std::unique_ptr<OrderedTrackIndexSet> autoRepeatEmptyRows) { |
| 99 m_autoRepeatEmptyRows = std::move(autoRepeatEmptyRows); |
| 100 } |
| 101 |
| 102 bool Grid::hasAutoRepeatEmptyTracks(GridTrackSizingDirection direction) const { |
| 103 return direction == ForColumns ? !!m_autoRepeatEmptyColumns |
| 104 : !!m_autoRepeatEmptyRows; |
| 105 } |
| 106 |
| 107 bool Grid::isEmptyAutoRepeatTrack(GridTrackSizingDirection direction, |
| 108 size_t line) const { |
| 109 DCHECK(hasAutoRepeatEmptyTracks(direction)); |
| 110 return autoRepeatEmptyTracks(direction)->contains(line); |
| 111 } |
| 112 |
| 113 OrderedTrackIndexSet* Grid::autoRepeatEmptyTracks( |
| 114 GridTrackSizingDirection direction) const { |
| 115 DCHECK(hasAutoRepeatEmptyTracks(direction)); |
| 116 return direction == ForColumns ? m_autoRepeatEmptyColumns.get() |
| 117 : m_autoRepeatEmptyRows.get(); |
| 118 } |
| 119 |
| 120 GridSpan Grid::gridItemSpan(const LayoutBox& gridItem, |
| 121 GridTrackSizingDirection direction) const { |
| 122 GridArea area = gridItemArea(gridItem); |
| 123 return direction == ForColumns ? area.columns : area.rows; |
| 124 } |
| 125 |
| 126 void Grid::setHasAnyOrthogonalGridItem(bool hasAnyOrthogonalGridItem) { |
| 127 m_hasAnyOrthogonalGridItem = hasAnyOrthogonalGridItem; |
| 128 } |
| 129 |
| 130 void Grid::setNeedsItemsPlacement(bool needsItemsPlacement) { |
| 131 m_needsItemsPlacement = needsItemsPlacement; |
| 132 |
| 133 if (!needsItemsPlacement) { |
| 134 m_grid.shrinkToFit(); |
| 135 return; |
| 136 } |
| 137 |
| 138 m_grid.resize(0); |
| 139 m_gridItemArea.clear(); |
| 140 m_gridItemsIndexesMap.clear(); |
| 141 m_hasAnyOrthogonalGridItem = false; |
| 142 m_smallestRowStart = 0; |
| 143 m_smallestColumnStart = 0; |
| 144 m_autoRepeatColumns = 0; |
| 145 m_autoRepeatRows = 0; |
| 146 m_autoRepeatEmptyColumns = nullptr; |
| 147 m_autoRepeatEmptyRows = nullptr; |
| 148 } |
| 149 |
| 150 GridIterator::GridIterator(const Grid& grid, |
| 151 GridTrackSizingDirection direction, |
| 152 size_t fixedTrackIndex, |
| 153 size_t varyingTrackIndex) |
| 154 : m_grid(grid.m_grid), |
| 155 m_direction(direction), |
| 156 m_rowIndex((direction == ForColumns) ? varyingTrackIndex |
| 157 : fixedTrackIndex), |
| 158 m_columnIndex((direction == ForColumns) ? fixedTrackIndex |
| 159 : varyingTrackIndex), |
| 160 m_childIndex(0) { |
| 161 DCHECK(!m_grid.isEmpty()); |
| 162 DCHECK(!m_grid[0].isEmpty()); |
| 163 DCHECK(m_rowIndex < m_grid.size()); |
| 164 DCHECK(m_columnIndex < m_grid[0].size()); |
| 165 } |
| 166 |
| 167 LayoutBox* GridIterator::nextGridItem() { |
| 168 DCHECK(!m_grid.isEmpty()); |
| 169 DCHECK(!m_grid[0].isEmpty()); |
| 170 |
| 171 size_t& varyingTrackIndex = |
| 172 (m_direction == ForColumns) ? m_rowIndex : m_columnIndex; |
| 173 const size_t endOfVaryingTrackIndex = |
| 174 (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size(); |
| 175 for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) { |
| 176 const GridCell& children = m_grid[m_rowIndex][m_columnIndex]; |
| 177 if (m_childIndex < children.size()) |
| 178 return children[m_childIndex++]; |
| 179 |
| 180 m_childIndex = 0; |
| 181 } |
| 182 return nullptr; |
| 183 } |
| 184 |
| 185 bool GridIterator::checkEmptyCells(size_t rowSpan, size_t columnSpan) const { |
| 186 DCHECK(!m_grid.isEmpty()); |
| 187 DCHECK(!m_grid[0].isEmpty()); |
| 188 |
| 189 // Ignore cells outside current grid as we will grow it later if needed. |
| 190 size_t maxRows = std::min(m_rowIndex + rowSpan, m_grid.size()); |
| 191 size_t maxColumns = std::min(m_columnIndex + columnSpan, m_grid[0].size()); |
| 192 |
| 193 // This adds a O(N^2) behavior that shouldn't be a big deal as we expect |
| 194 // spanning areas to be small. |
| 195 for (size_t row = m_rowIndex; row < maxRows; ++row) { |
| 196 for (size_t column = m_columnIndex; column < maxColumns; ++column) { |
| 197 const GridCell& children = m_grid[row][column]; |
| 198 if (!children.isEmpty()) |
| 199 return false; |
| 200 } |
| 201 } |
| 202 |
| 203 return true; |
| 204 } |
| 205 |
| 206 std::unique_ptr<GridArea> GridIterator::nextEmptyGridArea( |
| 207 size_t fixedTrackSpan, |
| 208 size_t varyingTrackSpan) { |
| 209 DCHECK(!m_grid.isEmpty()); |
| 210 DCHECK(!m_grid[0].isEmpty()); |
| 211 DCHECK(fixedTrackSpan >= 1 && varyingTrackSpan >= 1); |
| 212 |
| 213 size_t rowSpan = |
| 214 (m_direction == ForColumns) ? varyingTrackSpan : fixedTrackSpan; |
| 215 size_t columnSpan = |
| 216 (m_direction == ForColumns) ? fixedTrackSpan : varyingTrackSpan; |
| 217 |
| 218 size_t& varyingTrackIndex = |
| 219 (m_direction == ForColumns) ? m_rowIndex : m_columnIndex; |
| 220 const size_t endOfVaryingTrackIndex = |
| 221 (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size(); |
| 222 for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) { |
| 223 if (checkEmptyCells(rowSpan, columnSpan)) { |
| 224 std::unique_ptr<GridArea> result = WTF::wrapUnique( |
| 225 new GridArea(GridSpan::translatedDefiniteGridSpan( |
| 226 m_rowIndex, m_rowIndex + rowSpan), |
| 227 GridSpan::translatedDefiniteGridSpan( |
| 228 m_columnIndex, m_columnIndex + columnSpan))); |
| 229 // Advance the iterator to avoid an infinite loop where we would return |
| 230 // the same grid area over and over. |
| 231 ++varyingTrackIndex; |
| 232 return result; |
| 233 } |
| 234 } |
| 235 return nullptr; |
| 236 } |
| 237 |
| 238 } // namespace blink |
| OLD | NEW |