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())); |