Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/ColumnBalancer.h" | 5 #include "core/layout/ColumnBalancer.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutMultiColumnFlowThread.h" | 7 #include "core/layout/LayoutMultiColumnFlowThread.h" |
| 8 #include "core/layout/LayoutMultiColumnSet.h" | 8 #include "core/layout/LayoutMultiColumnSet.h" |
| 9 #include "core/layout/api/LineLayoutBlockFlow.h" | 9 #include "core/layout/api/LineLayoutBlockFlow.h" |
| 10 | 10 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 strut = LayoutUnit::max(); | 136 strut = LayoutUnit::max(); |
| 137 traverse(); | 137 traverse(); |
| 138 // We have now found each explicit / forced break, and their location. Now we | 138 // We have now found each explicit / forced break, and their location. Now we |
| 139 // need to figure out how many additional implicit / soft breaks we need and | 139 // need to figure out how many additional implicit / soft breaks we need and |
| 140 // guess where they will occur, in order | 140 // guess where they will occur, in order |
| 141 // to provide an initial column height. | 141 // to provide an initial column height. |
| 142 distributeImplicitBreaks(); | 142 distributeImplicitBreaks(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { | 145 LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const { |
| 146 LayoutUnit rowLogicalTop; | |
| 147 if (m_contentRuns.size() > columnSet().usedColumnCount()) { | |
| 148 // We have not inserted additional fragmentainer groups yet (because we | |
| 149 // aren't able to calculate their constraints yet), but we already know for | |
| 150 // sure that there'll be more than one of them, due to the number of forced | |
| 151 // breaks in a nested multicol container. We will now attempt to take all | |
| 152 // the imaginary rows into account and calculate a minimal balanced logical | |
| 153 // height for everything. | |
| 154 unsigned stride = columnSet().usedColumnCount(); | |
| 155 LayoutUnit rowStartOffset = logicalTopInFlowThread(); | |
| 156 for (unsigned i = 0; i < firstContentRunIndexInLastRow(); i += stride) { | |
| 157 LayoutUnit rowEndOffset = m_contentRuns[i + stride - 1].breakOffset(); | |
| 158 float rowHeight = float(rowEndOffset - rowStartOffset) / float(stride); | |
| 159 rowLogicalTop += LayoutUnit::fromFloatCeil(rowHeight); | |
|
eae
2016/11/10 23:37:12
why ceil?
mstensho (USE GERRIT)
2016/11/11 08:47:46
That's what InitialColumnHeightFinder::ContentRun:
| |
| 160 rowStartOffset = rowEndOffset; | |
| 161 } | |
| 162 } | |
| 146 unsigned index = contentRunIndexWithTallestColumns(); | 163 unsigned index = contentRunIndexWithTallestColumns(); |
| 147 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() | 164 LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() |
| 148 : logicalTopInFlowThread(); | 165 : logicalTopInFlowThread(); |
| 149 return m_contentRuns[index].columnLogicalHeight(startOffset); | 166 LayoutUnit height = m_contentRuns[index].columnLogicalHeight(startOffset); |
| 167 return rowLogicalTop + std::max(height, m_tallestUnbreakableLogicalHeight); | |
| 150 } | 168 } |
| 151 | 169 |
| 152 void InitialColumnHeightFinder::examineBoxAfterEntering( | 170 void InitialColumnHeightFinder::examineBoxAfterEntering( |
| 153 const LayoutBox& box, | 171 const LayoutBox& box, |
| 154 LayoutUnit childLogicalHeight, | 172 LayoutUnit childLogicalHeight, |
| 155 EBreak previousBreakAfterValue) { | 173 EBreak previousBreakAfterValue) { |
| 156 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { | 174 if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { |
| 157 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { | 175 if (box.needsForcedBreakBefore(previousBreakAfterValue)) { |
| 158 addContentRun(flowThreadOffset()); | 176 addContentRun(flowThreadOffset()); |
| 159 } else { | 177 } else { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 return totalStrutSpace; | 266 return totalStrutSpace; |
| 249 } | 267 } |
| 250 | 268 |
| 251 void InitialColumnHeightFinder::addContentRun( | 269 void InitialColumnHeightFinder::addContentRun( |
| 252 LayoutUnit endOffsetInFlowThread) { | 270 LayoutUnit endOffsetInFlowThread) { |
| 253 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); | 271 endOffsetInFlowThread -= spaceUsedByStrutsAt(endOffsetInFlowThread); |
| 254 if (!m_contentRuns.isEmpty() && | 272 if (!m_contentRuns.isEmpty() && |
| 255 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) | 273 endOffsetInFlowThread <= m_contentRuns.last().breakOffset()) |
| 256 return; | 274 return; |
| 257 // Append another item as long as we haven't exceeded used column count. What | 275 // Append another item as long as we haven't exceeded used column count. What |
| 258 // ends up in the overflow area shouldn't affect column balancing. | 276 // ends up in the overflow area shouldn't affect column balancing. However, if |
| 259 if (m_contentRuns.size() < columnSet().usedColumnCount()) | 277 // we're in a nested fragmentation context, we may still need to record all |
| 260 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); | 278 // runs, since there'll be no overflow area in the inline direction then, but |
| 279 // rather additional rows of columns in multiple outer fragmentainers. | |
| 280 if (m_contentRuns.size() >= columnSet().usedColumnCount()) { | |
| 281 const auto* flowThread = columnSet().multiColumnFlowThread(); | |
| 282 if (!flowThread->enclosingFragmentationContext() || | |
| 283 columnSet().newFragmentainerGroupsAllowed()) | |
| 284 return; | |
| 285 } | |
| 286 m_contentRuns.append(ContentRun(endOffsetInFlowThread)); | |
| 261 } | 287 } |
| 262 | 288 |
| 263 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { | 289 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { |
| 264 unsigned indexWithLargestHeight = 0; | 290 unsigned indexWithLargestHeight = 0; |
| 265 LayoutUnit largestHeight; | 291 LayoutUnit largestHeight; |
| 266 LayoutUnit previousOffset = logicalTopInFlowThread(); | 292 LayoutUnit previousOffset = logicalTopInFlowThread(); |
| 267 size_t runCount = m_contentRuns.size(); | 293 size_t runCount = m_contentRuns.size(); |
| 268 ASSERT(runCount); | 294 ASSERT(runCount); |
| 269 for (size_t i = 0; i < runCount; i++) { | 295 for (size_t i = firstContentRunIndexInLastRow(); i < runCount; i++) { |
| 270 const ContentRun& run = m_contentRuns[i]; | 296 const ContentRun& run = m_contentRuns[i]; |
| 271 LayoutUnit height = run.columnLogicalHeight(previousOffset); | 297 LayoutUnit height = run.columnLogicalHeight(previousOffset); |
| 272 if (largestHeight < height) { | 298 if (largestHeight < height) { |
| 273 largestHeight = height; | 299 largestHeight = height; |
| 274 indexWithLargestHeight = i; | 300 indexWithLargestHeight = i; |
| 275 } | 301 } |
| 276 previousOffset = run.breakOffset(); | 302 previousOffset = run.breakOffset(); |
| 277 } | 303 } |
| 278 return indexWithLargestHeight; | 304 return indexWithLargestHeight; |
| 279 } | 305 } |
| 280 | 306 |
| 281 void InitialColumnHeightFinder::distributeImplicitBreaks() { | 307 void InitialColumnHeightFinder::distributeImplicitBreaks() { |
| 282 // Insert a final content run to encompass all content. This will include | 308 // Insert a final content run to encompass all content. This will include |
| 283 // overflow if we're at the end of the multicol container. | 309 // overflow if we're at the end of the multicol container. |
| 284 addContentRun(logicalBottomInFlowThread()); | 310 addContentRun(logicalBottomInFlowThread()); |
| 285 unsigned columnCount = m_contentRuns.size(); | 311 unsigned columnCount = m_contentRuns.size(); |
| 286 | 312 |
| 287 // If there is room for more breaks (to reach the used value of column-count), | 313 // If there is room for more breaks (to reach the used value of column-count), |
| 288 // imagine that we insert implicit breaks at suitable locations. At any given | 314 // imagine that we insert implicit breaks at suitable locations. At any given |
| 289 // time, the content run with the currently tallest columns will get another | 315 // time, the content run with the currently tallest columns will get another |
| 290 // implicit break "inserted", which will increase its column count by one and | 316 // implicit break "inserted", which will increase its column count by one and |
| 291 // shrink its columns' height. Repeat until we have the desired total number | 317 // shrink its columns' height. Repeat until we have the desired total number |
| 292 // of breaks. The largest column height among the runs will then be the | 318 // of breaks. The largest column height among the runs will then be the |
| 293 // initial column height for the balancer to use. | 319 // initial column height for the balancer to use. |
| 320 if (columnCount > columnSet().usedColumnCount()) { | |
| 321 // If we exceed used column-count (which we are allowed to do if we're at | |
| 322 // the initial balancing pass for a multicol that lives inside another | |
| 323 // to-be-balanced outer multicol container), we only care about content that | |
| 324 // could end up in the last row. We need to pad up the number of columns, so | |
| 325 // that all rows will contain as many columns as used column-count dictates. | |
| 326 columnCount %= columnSet().usedColumnCount(); | |
| 327 // If there are just enough explicit breaks to fill all rows with the right | |
| 328 // amount of columns, we won't be needing any implicit breaks. | |
| 329 if (!columnCount) | |
| 330 return; | |
| 331 } | |
| 294 while (columnCount < columnSet().usedColumnCount()) { | 332 while (columnCount < columnSet().usedColumnCount()) { |
| 295 unsigned index = contentRunIndexWithTallestColumns(); | 333 unsigned index = contentRunIndexWithTallestColumns(); |
| 296 m_contentRuns[index].assumeAnotherImplicitBreak(); | 334 m_contentRuns[index].assumeAnotherImplicitBreak(); |
| 297 columnCount++; | 335 columnCount++; |
| 298 } | 336 } |
| 299 } | 337 } |
| 300 | 338 |
| 301 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( | 339 MinimumSpaceShortageFinder::MinimumSpaceShortageFinder( |
| 302 const LayoutMultiColumnSet& columnSet, | 340 const LayoutMultiColumnSet& columnSet, |
| 303 LayoutUnit logicalTopInFlowThread, | 341 LayoutUnit logicalTopInFlowThread, |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != | 473 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != |
| 436 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { | 474 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { |
| 437 LayoutUnit shortage = | 475 LayoutUnit shortage = |
| 438 lineBottomWithOverflow - | 476 lineBottomWithOverflow - |
| 439 group.columnLogicalTopForOffset(lineBottomWithOverflow); | 477 group.columnLogicalTopForOffset(lineBottomWithOverflow); |
| 440 recordSpaceShortage(shortage); | 478 recordSpaceShortage(shortage); |
| 441 } | 479 } |
| 442 } | 480 } |
| 443 | 481 |
| 444 } // namespace blink | 482 } // namespace blink |
| OLD | NEW |