Index: Source/core/rendering/RenderMultiColumnFlowThread.cpp |
diff --git a/Source/core/rendering/RenderMultiColumnFlowThread.cpp b/Source/core/rendering/RenderMultiColumnFlowThread.cpp |
index e44bfdb6a500ff6f43c2c01e83f19428b9aba1ea..f5c8ab08213f7691ebc6c824d189992227c17135 100644 |
--- a/Source/core/rendering/RenderMultiColumnFlowThread.cpp |
+++ b/Source/core/rendering/RenderMultiColumnFlowThread.cpp |
@@ -52,6 +52,41 @@ RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Docume |
return renderer; |
} |
+RenderMultiColumnSet* RenderMultiColumnFlowThread::firstMultiColumnSet() const |
+{ |
+ for (RenderObject* sibling = nextSibling(); sibling; sibling = sibling->nextSibling()) { |
+ if (sibling->isRenderMultiColumnSet()) |
+ return toRenderMultiColumnSet(sibling); |
+ } |
+ return 0; |
+} |
+ |
+RenderMultiColumnSet* RenderMultiColumnFlowThread::lastMultiColumnSet() const |
+{ |
+ for (RenderObject* sibling = multiColumnBlockFlow()->lastChild(); sibling; sibling = sibling->previousSibling()) { |
+ if (sibling->isRenderMultiColumnSet()) |
+ return toRenderMultiColumnSet(sibling); |
+ } |
+ return 0; |
+} |
+ |
+void RenderMultiColumnFlowThread::addChild(RenderObject* newChild, RenderObject* beforeChild) |
+{ |
+ RenderBlockFlow::addChild(newChild, beforeChild); |
+ if (firstMultiColumnSet()) |
+ return; |
+ |
+ // For now we only create one column set. It's created as soon as the multicol container gets |
+ // any content at all. |
+ RenderMultiColumnSet* newSet = RenderMultiColumnSet::createAnonymous(this, multiColumnBlockFlow()->style()); |
+ |
+ // Need to skip RenderBlockFlow's implementation of addChild(), or we'd get redirected right |
+ // back here. |
+ multiColumnBlockFlow()->RenderBlock::addChild(newSet); |
+ |
+ invalidateRegions(); |
+} |
+ |
void RenderMultiColumnFlowThread::populate() |
{ |
RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); |
@@ -67,12 +102,8 @@ void RenderMultiColumnFlowThread::evacuateAndDestroy() |
RenderBlockFlow* multicolContainer = multiColumnBlockFlow(); |
// Remove all sets. |
- for (RenderBox* sibling = nextSiblingBox(); sibling;) { |
- RenderBox* nextSibling = sibling->nextSiblingBox(); |
- if (sibling->isRenderMultiColumnSet()) |
- sibling->destroy(); |
- sibling = nextSibling; |
- } |
+ while (RenderMultiColumnSet* columnSet = firstMultiColumnSet()) |
+ columnSet->destroy(); |
ASSERT(!previousSibling()); |
ASSERT(!nextSibling()); |
@@ -97,15 +128,11 @@ void RenderMultiColumnFlowThread::layoutColumns(bool relayoutChildren, SubtreeLa |
// Update the dimensions of our regions before we lay out the flow thread. |
// FIXME: Eventually this is going to get way more complicated, and we will be destroying regions |
// instead of trying to keep them around. |
- RenderBlockFlow* container = multiColumnBlockFlow(); |
bool shouldInvalidateRegions = false; |
- for (RenderBox* childBox = container->firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { |
- if (childBox == this) |
- continue; |
- |
- if (relayoutChildren || childBox->needsLayout()) { |
- if (!m_inBalancingPass && childBox->isRenderMultiColumnSet()) |
- toRenderMultiColumnSet(childBox)->prepareForLayout(); |
+ for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) { |
+ if (relayoutChildren || columnSet->needsLayout()) { |
+ if (!m_inBalancingPass) |
+ columnSet->prepareForLayout(); |
shouldInvalidateRegions = true; |
} |
} |
@@ -173,13 +200,10 @@ bool RenderMultiColumnFlowThread::recalculateColumnHeights() |
// passes than that, though, but the number of retries should not exceed the number of |
// columns, unless we have a bug. |
bool needsRelayout = false; |
- for (RenderBox* childBox = multiColumnBlockFlow()->firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { |
- if (childBox != this && childBox->isRenderMultiColumnSet()) { |
- RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox); |
- if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) { |
- multicolSet->setChildNeedsLayout(MarkOnlyThis); |
- needsRelayout = true; |
- } |
+ for (RenderMultiColumnSet* multicolSet = firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { |
+ if (multicolSet->recalculateBalancedHeight(!m_inBalancingPass)) { |
+ multicolSet->setChildNeedsLayout(MarkOnlyThis); |
+ needsRelayout = true; |
} |
} |
@@ -195,6 +219,30 @@ const char* RenderMultiColumnFlowThread::renderName() const |
return "RenderMultiColumnFlowThread"; |
} |
+void RenderMultiColumnFlowThread::addRegionToThread(RenderRegion* renderRegion) |
+{ |
+ RenderMultiColumnSet* columnSet = toRenderMultiColumnSet(renderRegion); |
+ if (RenderMultiColumnSet* nextSet = columnSet->nextSiblingMultiColumnSet()) { |
+ RenderRegionList::iterator it = m_regionList.find(nextSet); |
+ ASSERT(it != m_regionList.end()); |
+ m_regionList.insertBefore(it, columnSet); |
+ } else { |
+ m_regionList.add(columnSet); |
+ } |
+ renderRegion->setIsValid(true); |
+} |
+ |
+void RenderMultiColumnFlowThread::willBeRemovedFromTree() |
+{ |
+ // Detach all column sets from the flow thread. Cannot destroy them at this point, since they |
+ // are siblings of this object, and there may be pointers to this object's sibling somewhere |
+ // further up on the call stack. |
+ for (RenderMultiColumnSet* columnSet = firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) |
+ columnSet->detachRegion(); |
+ multiColumnBlockFlow()->resetMultiColumnFlowThread(); |
+ RenderFlowThread::willBeRemovedFromTree(); |
+} |
+ |
void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const |
{ |
// We simply remain at our intrinsic height. |
@@ -207,45 +255,6 @@ LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const |
return columnWidth(); |
} |
-void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /*offset*/) |
-{ |
- // This function ensures we have the correct column set information at all times. |
- // For a simple multi-column layout in continuous media, only one column set child is required. |
- // Once a column is nested inside an enclosing pagination context, the number of column sets |
- // required becomes 2n-1, where n is the total number of nested pagination contexts. For example: |
- // |
- // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column set. |
- // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, all the subsequent pages, then the last page). |
- // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets. |
- // |
- // In addition, column spans will force a column set to "split" into before/after sets around the spanning element. |
- // |
- // Finally, we will need to deal with columns inside regions. If regions have variable widths, then there will need |
- // to be unique column sets created inside any region whose width is different from its surrounding regions. This is |
- // actually pretty similar to the spanning case, in that we break up the column sets whenever the width varies. |
- // |
- // FIXME: For now just make one column set. This matches the old multi-column code. |
- // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the |
- // new code as soon as possible. |
- RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion()); |
- if (firstSet) |
- return; |
- |
- invalidateRegions(); |
- |
- RenderBlockFlow* parentBlock = multiColumnBlockFlow(); |
- firstSet = RenderMultiColumnSet::createAnonymous(this); |
- firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock->style(), BLOCK)); |
- parentBlock->RenderBlock::addChild(firstSet); |
- |
- // Even though we aren't placed yet, we can go ahead and set up our size. At this point we're |
- // typically in the middle of laying out the thread, attempting to paginate, and we need to do |
- // some rudimentary "layout" of the set now, so that pagination will work. |
- firstSet->prepareForLayout(); |
- |
- validateRegions(); |
-} |
- |
void RenderMultiColumnFlowThread::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) |
{ |
if (RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(regionAtBlockOffset(offset))) |
@@ -258,6 +267,12 @@ void RenderMultiColumnFlowThread::updateMinimumPageHeight(LayoutUnit offset, Lay |
multicolSet->updateMinimumColumnHeight(minHeight); |
} |
+RenderRegion* RenderMultiColumnFlowThread::regionAtBlockOffset(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 = toRenderMultiColumnSet(regionAtBlockOffset(offset))) { |
@@ -271,12 +286,9 @@ bool RenderMultiColumnFlowThread::addForcedRegionBreak(LayoutUnit offset, Render |
bool RenderMultiColumnFlowThread::isPageLogicalHeightKnown() const |
{ |
- for (RenderBox* renderer = parentBox()->lastChildBox(); renderer; renderer = renderer->previousSiblingBox()) { |
- if (renderer->isRenderMultiColumnSet()) |
- return toRenderMultiColumnSet(renderer)->computedColumnHeight(); |
- } |
- // A column set hasn't been created yet. Height may already be known if column-fill is 'auto', though. |
- return !requiresBalancing(); |
+ if (RenderMultiColumnSet* columnSet = lastMultiColumnSet()) |
+ return columnSet->computedColumnHeight(); |
+ return false; |
} |
} |