Index: Source/core/rendering/RenderMultiColumnBlock.cpp |
diff --git a/Source/core/rendering/RenderMultiColumnBlock.cpp b/Source/core/rendering/RenderMultiColumnBlock.cpp |
index e4418294368262a56d2b6d0321e096ee391a754e..434fccd5b863f4eb007033a6c1ad26a8eea93018 100644 |
--- a/Source/core/rendering/RenderMultiColumnBlock.cpp |
+++ b/Source/core/rendering/RenderMultiColumnBlock.cpp |
@@ -27,6 +27,8 @@ |
#include "core/rendering/RenderMultiColumnBlock.h" |
#include "core/rendering/RenderMultiColumnFlowThread.h" |
+#include "core/rendering/RenderMultiColumnSet.h" |
+#include "core/rendering/RenderView.h" |
using namespace std; |
@@ -37,8 +39,8 @@ RenderMultiColumnBlock::RenderMultiColumnBlock(Element* element) |
, m_flowThread(0) |
, m_columnCount(1) |
, m_columnWidth(0) |
- , m_columnHeight(0) |
- , m_requiresBalancing(false) |
+ , m_columnHeightAvailable(0) |
+ , m_inBalancingPass(false) |
{ |
} |
@@ -89,21 +91,49 @@ void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& / |
{ |
// We don't actually update any of the variables. We just subclassed to adjust our column height. |
updateLogicalHeight(); |
- LayoutUnit newContentLogicalHeight = contentLogicalHeight(); |
- m_requiresBalancing = !newContentLogicalHeight; |
- if (!m_requiresBalancing) { |
- // The regions will be invalidated when we lay them out and they change size to |
- // the new column height. |
- if (columnHeight() != newContentLogicalHeight) |
- setColumnHeight(newContentLogicalHeight); |
- } |
+ m_columnHeightAvailable = max<LayoutUnit>(contentLogicalHeight(), 0); |
setLogicalHeight(0); |
} |
-bool RenderMultiColumnBlock::relayoutForPagination(bool, LayoutUnit, LayoutStateMaintainer&) |
+bool RenderMultiColumnBlock::relayoutForPagination(bool, LayoutUnit, LayoutStateMaintainer& statePusher) |
{ |
- // FIXME: Implement. |
- return false; |
+ if (m_inBalancingPass || !requiresBalancing()) |
+ return false; |
+ m_inBalancingPass = true; // Prevent re-entering this method (and recursion into layout). |
+ |
+ bool needsRelayout; |
+ bool neededRelayout = false; |
+ bool firstPass = true; |
+ do { |
+ // Column heights may change here because of balancing. We may have to do multiple layout |
+ // passes, depending on how the contents is fitted to the changed column heights. In most |
+ // cases, laying out again twice or even just once will suffice. Sometimes we need more |
+ // passes than that, though, but the number of retries should not exceed the number of |
+ // columns, unless we have a bug. |
+ needsRelayout = false; |
+ for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { |
+ if (childBox != m_flowThread && childBox->isRenderMultiColumnSet()) { |
+ RenderMultiColumnSet* multicolSet = toRenderMultiColumnSet(childBox); |
+ if (multicolSet->calculateBalancedHeight(firstPass)) { |
+ multicolSet->setChildNeedsLayout(true, MarkOnlyThis); |
+ needsRelayout = true; |
+ } |
+ } |
+ } |
+ |
+ if (needsRelayout) { |
+ // Layout again. Column balancing resulted in a new height. |
+ neededRelayout = true; |
+ m_flowThread->setChildNeedsLayout(true, MarkOnlyThis); |
+ setChildNeedsLayout(true, MarkOnlyThis); |
+ if (firstPass) |
+ statePusher.pop(); |
+ layoutBlock(false); |
+ } |
+ firstPass = false; |
+ } while (needsRelayout); |
+ m_inBalancingPass = false; |
+ return neededRelayout; |
} |
void RenderMultiColumnBlock::addChild(RenderObject* newChild, RenderObject* beforeChild) |
@@ -121,17 +151,17 @@ RenderObject* RenderMultiColumnBlock::layoutSpecialExcludedChild(bool relayoutCh |
if (!m_flowThread) |
return 0; |
- // Update the sizes of our regions (but not the placement) before we lay out the flow thread. |
+ // 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. |
bool shouldInvalidateRegions = false; |
for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { |
if (childBox == m_flowThread) |
continue; |
- |
+ |
if (relayoutChildren || childBox->needsLayout()) { |
- childBox->updateLogicalWidth(); |
- childBox->updateLogicalHeight(); |
+ if (!m_inBalancingPass && childBox->isRenderMultiColumnSet()) |
+ toRenderMultiColumnSet(childBox)->prepareForLayout(); |
shouldInvalidateRegions = true; |
} |
} |