Chromium Code Reviews| Index: Source/core/rendering/RenderMultiColumnSet.cpp |
| diff --git a/Source/core/rendering/RenderMultiColumnSet.cpp b/Source/core/rendering/RenderMultiColumnSet.cpp |
| index 7311e3a30991dff23693f17ea58459514545cd1a..c3db030944e2ce0e9fe1f4293a47ca286e51e3fa 100644 |
| --- a/Source/core/rendering/RenderMultiColumnSet.cpp |
| +++ b/Source/core/rendering/RenderMultiColumnSet.cpp |
| @@ -29,6 +29,7 @@ |
| #include "core/rendering/PaintInfo.h" |
| #include "core/rendering/RenderLayer.h" |
| #include "core/rendering/RenderMultiColumnFlowThread.h" |
| +#include "core/rendering/RenderMultiColumnSpannerPlaceholder.h" |
| using namespace std; |
| @@ -70,6 +71,92 @@ RenderMultiColumnSet* RenderMultiColumnSet::previousSiblingMultiColumnSet() cons |
| return 0; |
| } |
| +RenderObject* RenderMultiColumnSet::firstRendererInFlowThread() const |
| +{ |
| + if (RenderBox* sibling = RenderMultiColumnFlowThread::previousColumnSetOrSpannerSiblingOf(this)) { |
| + // Adjacent sets should not occur. Currently we would have no way of figuring out what each |
| + // of them contains then. |
| + ASSERT(!sibling->isRenderMultiColumnSet()); |
| + RenderMultiColumnSpannerPlaceholder* placeholder = multiColumnFlowThread()->findColumnSpannerPlaceholder(sibling); |
|
rune
2014/07/01 08:41:38
Perhaps add an ASSERT(placeholder) as well?
mstensho (USE GERRIT)
2014/08/26 09:43:58
Is it really necessary? It's gonna crash if it's N
rune
2014/08/27 07:00:01
It adds the information that it's not missing a nu
|
| + return placeholder->nextInPreOrderAfterChildren(); |
| + } |
| + return flowThread()->firstChild(); |
| +} |
| + |
| +RenderObject* RenderMultiColumnSet::lastRendererInFlowThread() const |
| +{ |
| + if (RenderBox* sibling = RenderMultiColumnFlowThread::nextColumnSetOrSpannerSiblingOf(this)) { |
| + // Adjacent sets should not occur. Currently we would have no way of figuring out what each |
| + // of them contains then. |
| + ASSERT(!sibling->isRenderMultiColumnSet()); |
| + RenderMultiColumnSpannerPlaceholder* placeholder = multiColumnFlowThread()->findColumnSpannerPlaceholder(sibling); |
| + return placeholder->previousInPreOrder(); |
| + } |
| + return flowThread()->lastLeafChild(); |
| +} |
| + |
| +static bool precedesRenderer(RenderObject* renderer, RenderObject* boundary) |
| +{ |
| + for (; renderer; renderer = renderer->nextInPreOrder()) { |
| + if (renderer == boundary) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +bool RenderMultiColumnSet::renders(RenderObject* renderer) const |
| +{ |
| + if (!previousSiblingMultiColumnSet() && !nextSiblingMultiColumnSet()) { |
| + // There is only one set. This is easy, then. |
| + return renderer->isDescendantOf(m_flowThread); |
| + } |
| + |
| + RenderObject* firstRenderer = firstRendererInFlowThread(); |
| + RenderObject* lastRenderer = lastRendererInFlowThread(); |
| + ASSERT(firstRenderer); |
| + ASSERT(lastRenderer); |
| + |
| + // This is SLOW! But luckily very uncommon. |
|
rune
2014/07/01 08:41:38
Perhaps note in which cases it happens. Is it when
mstensho (USE GERRIT)
2014/08/26 09:43:58
Done.
rune
2014/08/27 08:17:38
Acknowledged.
|
| + return precedesRenderer(firstRenderer, renderer) && precedesRenderer(renderer, lastRenderer); |
|
rune
2014/07/01 08:41:38
Do you need to check both? From where you call ren
mstensho (USE GERRIT)
2014/08/26 09:43:58
Done.
We don't look inside spanners here, so no n
rune
2014/08/27 08:17:38
I see that this code has been transformed in an op
mstensho (USE GERRIT)
2014/08/27 08:24:05
This code is new in this CL and an issue was raise
rune
2014/08/27 08:36:31
It such a long time since I reviewed this as well.
mstensho (USE GERRIT)
2014/08/27 08:47:02
That's what I did in practice. But I lumped it all
rune
2014/08/27 10:22:27
Acknowledged.
|
| +} |
| + |
| +void RenderMultiColumnSet::setLogicalTopInFlowThread(LayoutUnit logicalTop) |
| +{ |
| + LayoutRect rect = flowThreadPortionRect(); |
| + if (isHorizontalWritingMode()) |
| + rect.setY(logicalTop); |
| + else |
| + rect.setX(logicalTop); |
| + setFlowThreadPortionRect(rect); |
| +} |
| + |
| +void RenderMultiColumnSet::setLogicalBottomInFlowThread(LayoutUnit logicalBottom) |
| +{ |
| + LayoutRect rect = flowThreadPortionRect(); |
| + if (isHorizontalWritingMode()) |
| + rect.shiftMaxYEdgeTo(logicalBottom); |
| + else |
| + rect.shiftMaxXEdgeTo(logicalBottom); |
| + setFlowThreadPortionRect(rect); |
| +} |
| + |
| +bool RenderMultiColumnSet::heightIsAuto() const |
| +{ |
| + RenderMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
| + if (!flowThread->isRenderPagedFlowThread()) { |
| + if (RenderBox* next = RenderMultiColumnFlowThread::nextColumnSetOrSpannerSiblingOf(this)) { |
| + if (!next->isRenderMultiColumnSet()) { |
| + // If we're followed by a spanner, we need to balance. |
| + ASSERT(flowThread->findColumnSpannerPlaceholder(next)); |
| + return true; |
| + } |
| + } |
| + if (multiColumnBlockFlow()->style()->columnFill() == ColumnFillBalance) |
| + return true; |
| + } |
| + return !flowThread->columnHeightAvailable(); |
| +} |
| + |
| LayoutSize RenderMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockOffset) const |
| { |
| unsigned columnIndex = columnIndexAtOffset(blockOffset); |
| @@ -90,7 +177,7 @@ LayoutUnit RenderMultiColumnSet::heightAdjustedForSetOffset(LayoutUnit height) c |
| // a wasted layout iteration. Of course all other sets (if any) have this problem in the first |
| // layout pass too, but there's really nothing we can do there until the flow thread has been |
| // laid out anyway. |
| - if (previousSiblingMultiColumnSet()) { |
| + if (RenderMultiColumnFlowThread::previousColumnSetOrSpannerSiblingOf(this)) { |
| RenderBlockFlow* multicolBlock = multiColumnBlockFlow(); |
| LayoutUnit contentLogicalTop = logicalTop() - multicolBlock->borderAndPaddingBefore(); |
| height -= contentLogicalTop; |
| @@ -193,7 +280,7 @@ LayoutUnit RenderMultiColumnSet::calculateColumnHeight(BalancedHeightCalculation |
| void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) |
| { |
| - if (!multiColumnFlowThread()->heightIsAuto()) |
| + if (!heightIsAuto()) |
| return; |
| if (!m_contentRuns.isEmpty() && endOffsetFromFirstPage <= m_contentRuns.last().breakOffset()) |
| return; |
| @@ -205,21 +292,27 @@ void RenderMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) |
| bool RenderMultiColumnSet::recalculateColumnHeight(BalancedHeightCalculation calculationMode) |
| { |
| - ASSERT(multiColumnFlowThread()->heightIsAuto()); |
| - |
| LayoutUnit oldColumnHeight = m_columnHeight; |
| - if (calculationMode == GuessFromFlowThreadPortion) { |
| - // Post-process the content runs and find out where the implicit breaks will occur. |
| - distributeImplicitBreaks(); |
| - } |
| - LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); |
| - setAndConstrainColumnHeight(newColumnHeight); |
| - // After having calculated an initial column height, the multicol container typically needs at |
| - // least one more layout pass with a new column height, but if a height was specified, we only |
| - // need to do this if we think that we need less space than specified. Conversely, if we |
| - // determined that the columns need to be as tall as the specified height of the container, we |
| - // have already laid it out correctly, and there's no need for another pass. |
| + m_maxColumnHeight = calculateMaxColumnHeight(); |
| + |
| + if (heightIsAuto()) { |
| + if (calculationMode == GuessFromFlowThreadPortion) { |
| + // Post-process the content runs and find out where the implicit breaks will occur. |
| + distributeImplicitBreaks(); |
| + } |
| + LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); |
| + setAndConstrainColumnHeight(newColumnHeight); |
| + // After having calculated an initial column height, the multicol container typically needs at |
| + // least one more layout pass with a new column height, but if a height was specified, we only |
| + // need to do this if we think that we need less space than specified. Conversely, if we |
| + // determined that the columns need to be as tall as the specified height of the container, we |
| + // have already laid it out correctly, and there's no need for another pass. |
| + } else { |
| + // The position of the column set may have changed, in which case height available for |
| + // columns may have changed as well. |
| + setAndConstrainColumnHeight(m_columnHeight); |
| + } |
| // We can get rid of the content runs now, if we haven't already done so. They are only needed |
| // to calculate the initial balanced column height. In fact, we have to get rid of them before |
| @@ -254,7 +347,7 @@ void RenderMultiColumnSet::resetColumnHeight() |
| LayoutUnit oldColumnHeight = pageLogicalHeight(); |
| - if (multiColumnFlowThread()->heightIsAuto()) |
| + if (heightIsAuto()) |
| m_columnHeight = 0; |
| else |
| setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowThread()->columnHeightAvailable())); |