Index: Source/core/rendering/RenderMultiColumnFlowThread.cpp |
diff --git a/Source/core/rendering/RenderMultiColumnFlowThread.cpp b/Source/core/rendering/RenderMultiColumnFlowThread.cpp |
index 3fcf0db63513c843ae6c22dc48c08d79324a6d2d..b14915da9591a2cd601237165ef3bce56cd7e669 100644 |
--- a/Source/core/rendering/RenderMultiColumnFlowThread.cpp |
+++ b/Source/core/rendering/RenderMultiColumnFlowThread.cpp |
@@ -32,7 +32,8 @@ |
namespace blink { |
RenderMultiColumnFlowThread::RenderMultiColumnFlowThread() |
- : m_columnCount(1) |
+ : m_lastSetWorkedOn(0) |
+ , m_columnCount(1) |
, m_columnHeightAvailable(0) |
, m_inBalancingPass(false) |
, m_needsColumnHeightsRecalculation(false) |
@@ -150,11 +151,35 @@ bool RenderMultiColumnFlowThread::needsNewWidth() const |
return newWidth != logicalWidth(); |
} |
+RenderMultiColumnSet* RenderMultiColumnFlowThread::columnSetAtBlockOffset(LayoutUnit offset) const |
+{ |
+ if (m_lastSetWorkedOn) { |
+ // Layout in progress. We are calculating the set heights as we speak, so the column set range |
+ // information is not up-to-date. |
+ return m_lastSetWorkedOn; |
+ } |
+ |
+ ASSERT(!m_regionsInvalidated); |
+ if (m_multiColumnSetList.isEmpty()) |
+ return 0; |
+ if (offset <= 0) |
+ return m_multiColumnSetList.first(); |
+ |
+ MultiColumnSetSearchAdapter adapter(offset); |
+ m_multiColumnSetIntervalTree.allOverlapsWithAdapter<MultiColumnSetSearchAdapter>(adapter); |
+ |
+ // If no set was found, the offset is in the flow thread overflow. |
+ if (!adapter.result() && !m_multiColumnSetList.isEmpty()) |
+ return m_multiColumnSetList.last(); |
+ return adapter.result(); |
+} |
+ |
void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLayoutScope& layoutScope) |
{ |
if (relayoutChildren) |
layoutScope.setChildNeedsLayout(this); |
+ m_needsColumnHeightsRecalculation = false; |
if (!needsLayout()) { |
// Just before the multicol container (our parent RenderBlockFlow) finishes laying out, it |
// will call recalculateColumnHeights() on us unconditionally, but we only want that method |
@@ -162,13 +187,13 @@ void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa |
// machinery would kick in needlessly, and trigger additional layout passes. Furthermore, we |
// actually depend on a proper flowthread layout pass in order to do balancing, since it's |
// flowthread layout that sets up content runs. |
- m_needsColumnHeightsRecalculation = false; |
return; |
} |
- for (RenderBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = columnBox->nextSiblingBox()) { |
+ for (RenderBox* columnBox = firstMultiColumnBox(); columnBox; columnBox = columnBox->nextSiblingMultiColumnBox()) { |
if (!columnBox->isRenderMultiColumnSet()) { |
ASSERT(columnBox->isRenderMultiColumnSpannerPlaceholder()); // no other type is expected. |
+ m_needsColumnHeightsRecalculation = true; |
continue; |
} |
RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(columnBox); |
@@ -177,10 +202,11 @@ void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa |
// typically have changed. |
columnSet->resetColumnHeight(); |
} |
+ if (!m_needsColumnHeightsRecalculation) |
+ m_needsColumnHeightsRecalculation = columnSet->heightIsAuto(); |
} |
invalidateRegions(); |
- m_needsColumnHeightsRecalculation = heightIsAuto(); |
layout(); |
} |
@@ -327,6 +353,34 @@ void RenderMultiColumnFlowThread::willBeRemovedFromTree() |
RenderFlowThread::willBeRemovedFromTree(); |
} |
+LayoutUnit RenderMultiColumnFlowThread::skipColumnSpanner(RenderBox* renderer, LayoutUnit logicalTopInFlowThread) |
+{ |
+ ASSERT(renderer->isColumnSpanAll()); |
+ RenderMultiColumnSpannerPlaceholder* placeholder = renderer->spannerPlaceholder(); |
+ LayoutUnit adjustment; |
+ RenderBox* previousColumnBox = placeholder->previousSiblingMultiColumnBox(); |
+ if (previousColumnBox && previousColumnBox->isRenderMultiColumnSet()) { |
+ // Pad flow thread offset to a column boundary, so that any column content that's supposed |
+ // to come after the spanner doesn't bleed into the column row preceding the spanner. |
+ RenderMultiColumnSet* previousSet = toRenderMultiColumnSet(previousColumnBox); |
+ if (previousSet->pageLogicalHeight()) { |
+ LayoutUnit columnLogicalTopInFlowThread = previousSet->pageLogicalTopForOffset(logicalTopInFlowThread); |
+ if (columnLogicalTopInFlowThread != logicalTopInFlowThread) { |
+ adjustment = columnLogicalTopInFlowThread + previousSet->pageLogicalHeight() - logicalTopInFlowThread; |
+ logicalTopInFlowThread += adjustment; |
+ } |
+ } |
+ previousSet->endFlow(logicalTopInFlowThread); |
+ } |
+ RenderBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox(); |
+ if (nextColumnBox && nextColumnBox->isRenderMultiColumnSet()) { |
+ RenderMultiColumnSet* nextSet = toRenderMultiColumnSet(nextColumnBox); |
+ m_lastSetWorkedOn = nextSet; |
+ nextSet->beginFlow(logicalTopInFlowThread); |
+ } |
+ return adjustment; |
+} |
+ |
void RenderMultiColumnFlowThread::flowThreadDescendantWasInserted(RenderObject* descendant) |
{ |
ASSERT(!m_isBeingEvacuated); |
@@ -390,11 +444,19 @@ void RenderMultiColumnFlowThread::updateLogicalWidth() |
void RenderMultiColumnFlowThread::layout() |
{ |
+ ASSERT(!m_lastSetWorkedOn); |
+ m_lastSetWorkedOn = firstMultiColumnSet(); |
+ if (m_lastSetWorkedOn) |
+ m_lastSetWorkedOn->beginFlow(LayoutUnit()); |
RenderFlowThread::layout(); |
if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) { |
- if (!lastSet->nextSiblingMultiColumnBox()) |
+ ASSERT(lastSet == m_lastSetWorkedOn); |
+ if (!lastSet->nextSiblingMultiColumnBox()) { |
+ lastSet->endFlow(logicalHeight()); |
lastSet->expandToEncompassFlowThreadContentsIfNeeded(); |
+ } |
} |
+ m_lastSetWorkedOn = 0; |
} |
void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) |
@@ -416,12 +478,6 @@ void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay |
multicolSet->updateMinimumColumnHeight(minHeight); |
} |
-RenderMultiColumnSet* RenderMultiColumnFlowThread::columnSetAtBlockOffset(LayoutUnit /*offset*/) const |
-{ |
- // For now there's only one column set, so this is easy: |
- return firstMultiColumnSet(); |
-} |
- |
bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, RenderObject* /*breakChild*/, bool /*isBefore*/, LayoutUnit* offsetBreakAdjustment) |
{ |
if (RenderMultiColumnSet* multicolSet = columnSetAtBlockOffset(offset)) { |