| 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 |
| 11 namespace blink { | 11 namespace blink { |
| 12 | 12 |
| 13 ColumnBalancer::ColumnBalancer(const LayoutMultiColumnSet& columnSet, | 13 ColumnBalancer::ColumnBalancer(const LayoutMultiColumnSet& columnSet, |
| 14 LayoutUnit logicalTopInFlowThread, | 14 LayoutUnit logicalTopInFlowThread, |
| 15 LayoutUnit logicalBottomInFlowThread) | 15 LayoutUnit logicalBottomInFlowThread) |
| 16 : m_columnSet(columnSet), | 16 : m_columnSet(columnSet), |
| 17 m_logicalTopInFlowThread(logicalTopInFlowThread), | 17 m_logicalTopInFlowThread(logicalTopInFlowThread), |
| 18 m_logicalBottomInFlowThread(logicalBottomInFlowThread) { | 18 m_logicalBottomInFlowThread(logicalBottomInFlowThread) { |
| 19 DCHECK_GE(columnSet.usedColumnCount(), 1U); | 19 DCHECK_GE(columnSet.usedColumnCount(), 1U); |
| 20 } | 20 } |
| 21 | 21 |
| 22 void ColumnBalancer::traverse() { | 22 void ColumnBalancer::traverse() { |
| 23 traverseSubtree(*columnSet().flowThread()); | 23 traverseSubtree(*columnSet().flowThread()); |
| 24 ASSERT(!flowThreadOffset()); | 24 DCHECK(!flowThreadOffset()); |
| 25 } | 25 } |
| 26 | 26 |
| 27 void ColumnBalancer::traverseSubtree(const LayoutBox& box) { | 27 void ColumnBalancer::traverseSubtree(const LayoutBox& box) { |
| 28 if (box.childrenInline() && box.isLayoutBlockFlow()) { | 28 if (box.childrenInline() && box.isLayoutBlockFlow()) { |
| 29 // Look for breaks between lines. | 29 // Look for breaks between lines. |
| 30 traverseLines(toLayoutBlockFlow(box)); | 30 traverseLines(toLayoutBlockFlow(box)); |
| 31 } | 31 } |
| 32 | 32 |
| 33 // Look for breaks between and inside block-level children. Even if this is a | 33 // Look for breaks between and inside block-level children. Even if this is a |
| 34 // block flow with inline children, there may be interesting floats to examine | 34 // block flow with inline children, there may be interesting floats to examine |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 | 236 |
| 237 void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) { | 237 void InitialColumnHeightFinder::examineLine(const RootInlineBox& line) { |
| 238 LayoutUnit lineTop = line.lineTopWithLeading(); | 238 LayoutUnit lineTop = line.lineTopWithLeading(); |
| 239 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; | 239 LayoutUnit lineTopInFlowThread = flowThreadOffset() + lineTop; |
| 240 LayoutUnit minimumLogialHeight = | 240 LayoutUnit minimumLogialHeight = |
| 241 columnLogicalHeightRequirementForLine(line.block().styleRef(), line); | 241 columnLogicalHeightRequirementForLine(line.block().styleRef(), line); |
| 242 if (lineTopInFlowThread < LayoutUnit()) | 242 if (lineTopInFlowThread < LayoutUnit()) |
| 243 minimumLogialHeight += lineTopInFlowThread; | 243 minimumLogialHeight += lineTopInFlowThread; |
| 244 m_tallestUnbreakableLogicalHeight = | 244 m_tallestUnbreakableLogicalHeight = |
| 245 std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight); | 245 std::max(m_tallestUnbreakableLogicalHeight, minimumLogialHeight); |
| 246 ASSERT( | 246 DCHECK( |
| 247 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || | 247 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || |
| 248 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); | 248 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); |
| 249 if (isFirstAfterBreak(lineTopInFlowThread) && | 249 if (isFirstAfterBreak(lineTopInFlowThread) && |
| 250 m_lastBreakSeen != lineTopInFlowThread) { | 250 m_lastBreakSeen != lineTopInFlowThread) { |
| 251 m_lastBreakSeen = lineTopInFlowThread; | 251 m_lastBreakSeen = lineTopInFlowThread; |
| 252 recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut()); | 252 recordStrutBeforeOffset(lineTopInFlowThread, line.paginationStrut()); |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 void InitialColumnHeightFinder::recordStrutBeforeOffset( | 256 void InitialColumnHeightFinder::recordStrutBeforeOffset( |
| 257 LayoutUnit offsetInFlowThread, | 257 LayoutUnit offsetInFlowThread, |
| 258 LayoutUnit strut) { | 258 LayoutUnit strut) { |
| 259 unsigned columnCount = columnSet().usedColumnCount(); | 259 unsigned columnCount = columnSet().usedColumnCount(); |
| 260 ASSERT(m_shortestStruts.size() == columnCount); | 260 DCHECK_EQ(m_shortestStruts.size(), columnCount); |
| 261 unsigned index = groupAtOffset(offsetInFlowThread) | 261 unsigned index = groupAtOffset(offsetInFlowThread) |
| 262 .columnIndexAtOffset(offsetInFlowThread - strut, | 262 .columnIndexAtOffset(offsetInFlowThread - strut, |
| 263 LayoutBox::AssociateWithFormerPage); | 263 LayoutBox::AssociateWithFormerPage); |
| 264 if (index >= columnCount) | 264 if (index >= columnCount) |
| 265 return; | 265 return; |
| 266 m_shortestStruts[index] = std::min(m_shortestStruts[index], strut); | 266 m_shortestStruts[index] = std::min(m_shortestStruts[index], strut); |
| 267 } | 267 } |
| 268 | 268 |
| 269 LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt( | 269 LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt( |
| 270 LayoutUnit offsetInFlowThread) const { | 270 LayoutUnit offsetInFlowThread) const { |
| 271 unsigned stopBeforeColumn = | 271 unsigned stopBeforeColumn = |
| 272 groupAtOffset(offsetInFlowThread) | 272 groupAtOffset(offsetInFlowThread) |
| 273 .columnIndexAtOffset(offsetInFlowThread, | 273 .columnIndexAtOffset(offsetInFlowThread, |
| 274 LayoutBox::AssociateWithLatterPage) + | 274 LayoutBox::AssociateWithLatterPage) + |
| 275 1; | 275 1; |
| 276 stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount()); | 276 stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount()); |
| 277 ASSERT(stopBeforeColumn <= m_shortestStruts.size()); | 277 DCHECK_LE(stopBeforeColumn, m_shortestStruts.size()); |
| 278 LayoutUnit totalStrutSpace; | 278 LayoutUnit totalStrutSpace; |
| 279 for (unsigned i = 0; i < stopBeforeColumn; i++) { | 279 for (unsigned i = 0; i < stopBeforeColumn; i++) { |
| 280 if (m_shortestStruts[i] != LayoutUnit::max()) | 280 if (m_shortestStruts[i] != LayoutUnit::max()) |
| 281 totalStrutSpace += m_shortestStruts[i]; | 281 totalStrutSpace += m_shortestStruts[i]; |
| 282 } | 282 } |
| 283 return totalStrutSpace; | 283 return totalStrutSpace; |
| 284 } | 284 } |
| 285 | 285 |
| 286 void InitialColumnHeightFinder::addContentRun( | 286 void InitialColumnHeightFinder::addContentRun( |
| 287 LayoutUnit endOffsetInFlowThread) { | 287 LayoutUnit endOffsetInFlowThread) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 301 return; | 301 return; |
| 302 } | 302 } |
| 303 m_contentRuns.push_back(ContentRun(endOffsetInFlowThread)); | 303 m_contentRuns.push_back(ContentRun(endOffsetInFlowThread)); |
| 304 } | 304 } |
| 305 | 305 |
| 306 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { | 306 unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const { |
| 307 unsigned indexWithLargestHeight = 0; | 307 unsigned indexWithLargestHeight = 0; |
| 308 LayoutUnit largestHeight; | 308 LayoutUnit largestHeight; |
| 309 LayoutUnit previousOffset = logicalTopInFlowThread(); | 309 LayoutUnit previousOffset = logicalTopInFlowThread(); |
| 310 size_t runCount = m_contentRuns.size(); | 310 size_t runCount = m_contentRuns.size(); |
| 311 ASSERT(runCount); | 311 DCHECK(runCount); |
| 312 for (size_t i = firstContentRunIndexInLastRow(); i < runCount; i++) { | 312 for (size_t i = firstContentRunIndexInLastRow(); i < runCount; i++) { |
| 313 const ContentRun& run = m_contentRuns[i]; | 313 const ContentRun& run = m_contentRuns[i]; |
| 314 LayoutUnit height = run.columnLogicalHeight(previousOffset); | 314 LayoutUnit height = run.columnLogicalHeight(previousOffset); |
| 315 if (largestHeight < height) { | 315 if (largestHeight < height) { |
| 316 largestHeight = height; | 316 largestHeight = height; |
| 317 indexWithLargestHeight = i; | 317 indexWithLargestHeight = i; |
| 318 } | 318 } |
| 319 previousOffset = run.breakOffset(); | 319 previousOffset = run.breakOffset(); |
| 320 } | 320 } |
| 321 return indexWithLargestHeight; | 321 return indexWithLargestHeight; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 // The previous break was before a breakable block. Here's the first line | 466 // The previous break was before a breakable block. Here's the first line |
| 467 // after / inside that block. We want to record the distance from the top of | 467 // after / inside that block. We want to record the distance from the top of |
| 468 // the column to the bottom of this box as space shortage. | 468 // the column to the bottom of this box as space shortage. |
| 469 LayoutUnit logicalOffsetFromCurrentColumn = | 469 LayoutUnit logicalOffsetFromCurrentColumn = |
| 470 offsetFromColumnLogicalTop(lineTopInFlowThread); | 470 offsetFromColumnLogicalTop(lineTopInFlowThread); |
| 471 recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight - | 471 recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight - |
| 472 m_pendingStrut); | 472 m_pendingStrut); |
| 473 m_pendingStrut = LayoutUnit::min(); | 473 m_pendingStrut = LayoutUnit::min(); |
| 474 return; | 474 return; |
| 475 } | 475 } |
| 476 ASSERT( | 476 DCHECK( |
| 477 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || | 477 isFirstAfterBreak(lineTopInFlowThread) || !line.paginationStrut() || |
| 478 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); | 478 !isLogicalTopWithinBounds(lineTopInFlowThread - line.paginationStrut())); |
| 479 if (isFirstAfterBreak(lineTopInFlowThread)) | 479 if (isFirstAfterBreak(lineTopInFlowThread)) |
| 480 recordSpaceShortage(lineHeight - line.paginationStrut()); | 480 recordSpaceShortage(lineHeight - line.paginationStrut()); |
| 481 | 481 |
| 482 // Even if the line box itself fits fine inside a column, some content may | 482 // Even if the line box itself fits fine inside a column, some content may |
| 483 // overflow the line box bottom (due to restrictive line-height, for | 483 // overflow the line box bottom (due to restrictive line-height, for |
| 484 // instance). We should check if some portion of said overflow ends up in the | 484 // instance). We should check if some portion of said overflow ends up in the |
| 485 // next column. That counts as space shortage. | 485 // next column. That counts as space shortage. |
| 486 const MultiColumnFragmentainerGroup& group = | 486 const MultiColumnFragmentainerGroup& group = |
| 487 groupAtOffset(lineTopInFlowThread); | 487 groupAtOffset(lineTopInFlowThread); |
| 488 LayoutUnit lineBottomWithOverflow = | 488 LayoutUnit lineBottomWithOverflow = |
| 489 lineTopInFlowThread + line.lineBottom() - lineTop; | 489 lineTopInFlowThread + line.lineBottom() - lineTop; |
| 490 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != | 490 if (group.columnLogicalTopForOffset(lineTopInFlowThread) != |
| 491 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { | 491 group.columnLogicalTopForOffset(lineBottomWithOverflow)) { |
| 492 LayoutUnit shortage = | 492 LayoutUnit shortage = |
| 493 lineBottomWithOverflow - | 493 lineBottomWithOverflow - |
| 494 group.columnLogicalTopForOffset(lineBottomWithOverflow); | 494 group.columnLogicalTopForOffset(lineBottomWithOverflow); |
| 495 recordSpaceShortage(shortage); | 495 recordSpaceShortage(shortage); |
| 496 } | 496 } |
| 497 } | 497 } |
| 498 | 498 |
| 499 } // namespace blink | 499 } // namespace blink |
| OLD | NEW |