| Index: third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
|
| index 45607bdde8b166eb4b9092b18e8d059939e91489..1ba071994ee615703c926bdedf4bb874cca748d3 100644
|
| --- a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
|
| @@ -10,15 +10,17 @@
|
|
|
| namespace blink {
|
|
|
| -ColumnBalancer::ColumnBalancer(const MultiColumnFragmentainerGroup& group)
|
| - : m_group(group)
|
| +ColumnBalancer::ColumnBalancer(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThread)
|
| + : m_columnSet(columnSet)
|
| + , m_logicalTopInFlowThread(logicalTopInFlowThread)
|
| + , m_logicalBottomInFlowThread(logicalBottomInFlowThread)
|
| , m_previousBreakAfterValue(BreakAuto)
|
| {
|
| }
|
|
|
| void ColumnBalancer::traverse()
|
| {
|
| - traverseSubtree(*m_group.columnSet().flowThread());
|
| + traverseSubtree(*columnSet().flowThread());
|
| ASSERT(!flowThreadOffset());
|
| }
|
|
|
| @@ -28,15 +30,15 @@ void ColumnBalancer::traverseSubtree(const LayoutBox& box)
|
| // Look for breaks between lines.
|
| for (const RootInlineBox* line = toLayoutBlockFlow(box).firstRootBox(); line; line = line->nextRootBox()) {
|
| LayoutUnit lineTopInFlowThread = m_flowThreadOffset + line->lineTopWithLeading();
|
| - if (lineTopInFlowThread < group().logicalTopInFlowThread())
|
| + if (lineTopInFlowThread < logicalTopInFlowThread())
|
| continue;
|
| - if (lineTopInFlowThread >= group().logicalBottomInFlowThread())
|
| + if (lineTopInFlowThread >= logicalBottomInFlowThread())
|
| break;
|
| examineLine(*line);
|
| }
|
| }
|
|
|
| - const LayoutFlowThread* flowThread = group().columnSet().flowThread();
|
| + const LayoutFlowThread* flowThread = columnSet().flowThread();
|
| bool isHorizontalWritingMode = flowThread->isHorizontalWritingMode();
|
|
|
| // Look for breaks between and inside block-level children. Even if this is a block flow with
|
| @@ -47,13 +49,13 @@ void ColumnBalancer::traverseSubtree(const LayoutBox& box)
|
| const LayoutBox& childBox = toLayoutBox(*child);
|
| LayoutRect overflowRect = childBox.layoutOverflowRect();
|
| LayoutUnit childLogicalBottomWithOverflow = childBox.logicalTop() + (isHorizontalWritingMode ? overflowRect.maxY() : overflowRect.maxX());
|
| - if (m_flowThreadOffset + childLogicalBottomWithOverflow <= group().logicalTopInFlowThread()) {
|
| - // This child is fully above the fragmentainer group we're examining.
|
| + if (m_flowThreadOffset + childLogicalBottomWithOverflow <= logicalTopInFlowThread()) {
|
| + // This child is fully above the flow thread portion we're examining.
|
| continue;
|
| }
|
| LayoutUnit childLogicalTopWithOverflow = childBox.logicalTop() + (isHorizontalWritingMode ? overflowRect.y() : overflowRect.x());
|
| - if (m_flowThreadOffset + childLogicalTopWithOverflow >= group().logicalBottomInFlowThread()) {
|
| - // This child is fully below the fragmentainer group we're examining. We cannot just
|
| + if (m_flowThreadOffset + childLogicalTopWithOverflow >= logicalBottomInFlowThread()) {
|
| + // This child is fully below the flow thread portion we're examining. We cannot just
|
| // stop here, though, thanks to negative margins. So keep looking.
|
| continue;
|
| }
|
| @@ -77,10 +79,10 @@ void ColumnBalancer::traverseSubtree(const LayoutBox& box)
|
| }
|
| }
|
|
|
| -InitialColumnHeightFinder::InitialColumnHeightFinder(const MultiColumnFragmentainerGroup& group)
|
| - : ColumnBalancer(group)
|
| +InitialColumnHeightFinder::InitialColumnHeightFinder(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThread)
|
| + : ColumnBalancer(columnSet, logicalTopInFlowThread, logicalBottomInFlowThread)
|
| {
|
| - m_shortestStruts.resize(group.columnSet().usedColumnCount());
|
| + m_shortestStruts.resize(columnSet.usedColumnCount());
|
| for (auto& strut : m_shortestStruts)
|
| strut = LayoutUnit::max();
|
| traverse();
|
| @@ -93,7 +95,7 @@ InitialColumnHeightFinder::InitialColumnHeightFinder(const MultiColumnFragmentai
|
| LayoutUnit InitialColumnHeightFinder::initialMinimalBalancedHeight() const
|
| {
|
| unsigned index = contentRunIndexWithTallestColumns();
|
| - LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : group().logicalTopInFlowThread();
|
| + LayoutUnit startOffset = index > 0 ? m_contentRuns[index - 1].breakOffset() : logicalTopInFlowThread();
|
| return m_contentRuns[index].columnLogicalHeight(startOffset);
|
| }
|
|
|
| @@ -157,11 +159,10 @@ void InitialColumnHeightFinder::examineLine(const RootInlineBox& line)
|
|
|
| void InitialColumnHeightFinder::recordStrutBeforeOffset(LayoutUnit offsetInFlowThread, LayoutUnit strut)
|
| {
|
| - const LayoutMultiColumnSet& columnSet = group().columnSet();
|
| - ASSERT(columnSet.usedColumnCount() >= 1);
|
| - unsigned columnCount = columnSet.usedColumnCount();
|
| + ASSERT(columnSet().usedColumnCount() >= 1);
|
| + unsigned columnCount = columnSet().usedColumnCount();
|
| ASSERT(m_shortestStruts.size() == columnCount);
|
| - unsigned index = group().columnIndexAtOffset(offsetInFlowThread - strut, MultiColumnFragmentainerGroup::AssumeNewColumns);
|
| + unsigned index = groupAtOffset(offsetInFlowThread).columnIndexAtOffset(offsetInFlowThread - strut, MultiColumnFragmentainerGroup::AssumeNewColumns);
|
| if (index >= columnCount)
|
| return;
|
| m_shortestStruts[index] = std::min(m_shortestStruts[index], strut);
|
| @@ -169,8 +170,8 @@ void InitialColumnHeightFinder::recordStrutBeforeOffset(LayoutUnit offsetInFlowT
|
|
|
| LayoutUnit InitialColumnHeightFinder::spaceUsedByStrutsAt(LayoutUnit offsetInFlowThread) const
|
| {
|
| - unsigned stopBeforeColumn = group().columnIndexAtOffset(offsetInFlowThread, MultiColumnFragmentainerGroup::AssumeNewColumns) + 1;
|
| - stopBeforeColumn = std::min(stopBeforeColumn, group().columnSet().usedColumnCount());
|
| + unsigned stopBeforeColumn = groupAtOffset(offsetInFlowThread).columnIndexAtOffset(offsetInFlowThread, MultiColumnFragmentainerGroup::AssumeNewColumns) + 1;
|
| + stopBeforeColumn = std::min(stopBeforeColumn, columnSet().usedColumnCount());
|
| ASSERT(stopBeforeColumn <= m_shortestStruts.size());
|
| LayoutUnit totalStrutSpace;
|
| for (unsigned i = 0; i < stopBeforeColumn; i++) {
|
| @@ -187,7 +188,7 @@ void InitialColumnHeightFinder::addContentRun(LayoutUnit endOffsetInFlowThread)
|
| return;
|
| // Append another item as long as we haven't exceeded used column count. What ends up in the
|
| // overflow area shouldn't affect column balancing.
|
| - if (m_contentRuns.size() < group().columnSet().usedColumnCount())
|
| + if (m_contentRuns.size() < columnSet().usedColumnCount())
|
| m_contentRuns.append(ContentRun(endOffsetInFlowThread));
|
| }
|
|
|
| @@ -195,7 +196,7 @@ unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const
|
| {
|
| unsigned indexWithLargestHeight = 0;
|
| LayoutUnit largestHeight;
|
| - LayoutUnit previousOffset = group().logicalTopInFlowThread();
|
| + LayoutUnit previousOffset = logicalTopInFlowThread();
|
| size_t runCount = m_contentRuns.size();
|
| ASSERT(runCount);
|
| for (size_t i = 0; i < runCount; i++) {
|
| @@ -212,9 +213,9 @@ unsigned InitialColumnHeightFinder::contentRunIndexWithTallestColumns() const
|
|
|
| void InitialColumnHeightFinder::distributeImplicitBreaks()
|
| {
|
| - // Insert a final content run to encompass all content. This will include overflow if this is
|
| - // the last group in the multicol container.
|
| - addContentRun(group().logicalBottomInFlowThread());
|
| + // Insert a final content run to encompass all content. This will include overflow if we're at
|
| + // the end of the multicol container.
|
| + addContentRun(logicalBottomInFlowThread());
|
| unsigned columnCount = m_contentRuns.size();
|
|
|
| // If there is room for more breaks (to reach the used value of column-count), imagine that we
|
| @@ -223,15 +224,15 @@ void InitialColumnHeightFinder::distributeImplicitBreaks()
|
| // column count by one and shrink its columns' height. Repeat until we have the desired total
|
| // number of breaks. The largest column height among the runs will then be the initial column
|
| // height for the balancer to use.
|
| - while (columnCount < group().columnSet().usedColumnCount()) {
|
| + while (columnCount < columnSet().usedColumnCount()) {
|
| unsigned index = contentRunIndexWithTallestColumns();
|
| m_contentRuns[index].assumeAnotherImplicitBreak();
|
| columnCount++;
|
| }
|
| }
|
|
|
| -MinimumSpaceShortageFinder::MinimumSpaceShortageFinder(const MultiColumnFragmentainerGroup& group)
|
| - : ColumnBalancer(group)
|
| +MinimumSpaceShortageFinder::MinimumSpaceShortageFinder(const LayoutMultiColumnSet& columnSet, LayoutUnit logicalTopInFlowThread, LayoutUnit logicalBottomInFlowThread)
|
| + : ColumnBalancer(columnSet, logicalTopInFlowThread, logicalBottomInFlowThread)
|
| , m_minimumSpaceShortage(LayoutUnit::max())
|
| , m_pendingStrut(LayoutUnit::min())
|
| , m_forcedBreaksCount(0)
|
| @@ -269,14 +270,15 @@ void MinimumSpaceShortageFinder::examineBoxAfterEntering(const LayoutBox& box)
|
| if (breakability != LayoutBox::ForbidBreaks) {
|
| // See if this breakable box crosses column boundaries.
|
| LayoutUnit bottomInFlowThread = flowThreadOffset() + box.logicalHeight();
|
| + const MultiColumnFragmentainerGroup& group = groupAtOffset(flowThreadOffset());
|
| if (isFirstAfterBreak(flowThreadOffset())
|
| - || group().columnLogicalTopForOffset(flowThreadOffset()) != group().columnLogicalTopForOffset(bottomInFlowThread)) {
|
| + || group.columnLogicalTopForOffset(flowThreadOffset()) != group.columnLogicalTopForOffset(bottomInFlowThread)) {
|
| // If the child crosses a column boundary, record space shortage, in case nothing
|
| // inside it has already done so. The column balancer needs to know by how much it
|
| // has to stretch the columns to make more content fit. If no breaks are reported
|
| // (but do occur), the balancer will have no clue. Only measure the space after the
|
| // last column boundary, in case it crosses more than one.
|
| - LayoutUnit spaceUsedInLastColumn = bottomInFlowThread - group().columnLogicalTopForOffset(bottomInFlowThread);
|
| + LayoutUnit spaceUsedInLastColumn = bottomInFlowThread - group.columnLogicalTopForOffset(bottomInFlowThread);
|
| recordSpaceShortage(spaceUsedInLastColumn);
|
| }
|
| }
|
| @@ -288,10 +290,12 @@ void MinimumSpaceShortageFinder::examineBoxAfterEntering(const LayoutBox& box)
|
| if (!flowThread || flowThread->isLayoutPagedFlowThread())
|
| return;
|
| for (const LayoutMultiColumnSet* columnSet = flowThread->firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) {
|
| - for (const MultiColumnFragmentainerGroup& row : columnSet->fragmentainerGroups()) {
|
| - MinimumSpaceShortageFinder innerFinder(row);
|
| - recordSpaceShortage(innerFinder.minimumSpaceShortage());
|
| - }
|
| + // Establish an inner shortage finder for this column set in the inner multicol
|
| + // container. We need to let it walk through all fragmentainer groups in one go, or we'd
|
| + // miss the column boundaries between each fragmentainer group. We need to record space
|
| + // shortage there too.
|
| + MinimumSpaceShortageFinder innerFinder(*columnSet, columnSet->logicalTopInFlowThread(), columnSet->logicalBottomInFlowThread());
|
| + recordSpaceShortage(innerFinder.minimumSpaceShortage());
|
| }
|
| }
|
|
|
| @@ -303,7 +307,7 @@ void MinimumSpaceShortageFinder::examineBoxBeforeLeaving(const LayoutBox& box)
|
| // The previous break was before a breakable block. Here's the first piece of unbreakable
|
| // content after / inside that block. We want to record the distance from the top of the column
|
| // to the bottom of this box as space shortage.
|
| - LayoutUnit logicalOffsetFromCurrentColumn = flowThreadOffset() - group().columnLogicalTopForOffset(flowThreadOffset());
|
| + LayoutUnit logicalOffsetFromCurrentColumn = offsetFromColumnLogicalTop(flowThreadOffset());
|
| recordSpaceShortage(logicalOffsetFromCurrentColumn + box.logicalHeight() - m_pendingStrut);
|
| m_pendingStrut = LayoutUnit::min();
|
| }
|
| @@ -317,7 +321,7 @@ void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line)
|
| // The previous break was before a breakable block. Here's the first line after / inside
|
| // that block. We want to record the distance from the top of the column to the bottom of
|
| // this box as space shortage.
|
| - LayoutUnit logicalOffsetFromCurrentColumn = lineTopInFlowThread - group().columnLogicalTopForOffset(lineTopInFlowThread);
|
| + LayoutUnit logicalOffsetFromCurrentColumn = offsetFromColumnLogicalTop(lineTopInFlowThread);
|
| recordSpaceShortage(logicalOffsetFromCurrentColumn + lineHeight - m_pendingStrut);
|
| m_pendingStrut = LayoutUnit::min();
|
| return;
|
| @@ -329,9 +333,10 @@ void MinimumSpaceShortageFinder::examineLine(const RootInlineBox& line)
|
| // Even if the line box itself fits fine inside a column, some content may overflow the line
|
| // box bottom (due to restrictive line-height, for instance). We should check if some portion
|
| // of said overflow ends up in the next column. That counts as space shortage.
|
| + const MultiColumnFragmentainerGroup& group = groupAtOffset(lineTopInFlowThread);
|
| LayoutUnit lineBottomWithOverflow = lineTopInFlowThread + line.lineBottom() - lineTop;
|
| - if (group().columnLogicalTopForOffset(lineTopInFlowThread) != group().columnLogicalTopForOffset(lineBottomWithOverflow)) {
|
| - LayoutUnit shortage = lineBottomWithOverflow - group().columnLogicalTopForOffset(lineBottomWithOverflow);
|
| + if (group.columnLogicalTopForOffset(lineTopInFlowThread) != group.columnLogicalTopForOffset(lineBottomWithOverflow)) {
|
| + LayoutUnit shortage = lineBottomWithOverflow - group.columnLogicalTopForOffset(lineBottomWithOverflow);
|
| recordSpaceShortage(shortage);
|
| }
|
| }
|
|
|