Index: Source/core/rendering/RenderBlockFlow.cpp |
diff --git a/Source/core/rendering/RenderBlockFlow.cpp b/Source/core/rendering/RenderBlockFlow.cpp |
index 840108dd5a2c728bf4f935408859f787da4632f2..e5bace7e2a68f33bf722160107439dae0a7bf223 100644 |
--- a/Source/core/rendering/RenderBlockFlow.cpp |
+++ b/Source/core/rendering/RenderBlockFlow.cpp |
@@ -38,6 +38,7 @@ |
#include "core/rendering/LayoutRectRecorder.h" |
#include "core/rendering/LayoutRepainter.h" |
#include "core/rendering/RenderLayer.h" |
+#include "core/rendering/RenderMultiColumnBlock.h" |
#include "core/rendering/RenderNamedFlowFragment.h" |
#include "core/rendering/RenderNamedFlowThread.h" |
#include "core/rendering/RenderText.h" |
@@ -187,57 +188,45 @@ void RenderBlockFlow::willBeDestroyed() |
RenderBlock::willBeDestroyed(); |
} |
-bool RenderBlockFlow::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer& statePusher) |
+bool RenderBlockFlow::shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const |
{ |
- if (!hasColumns()) |
- return false; |
- |
- OwnPtr<RenderOverflow> savedOverflow = m_overflow.release(); |
- if (childrenInline()) |
- addOverflowFromInlineChildren(); |
- else |
- addOverflowFromBlockChildren(); |
- LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore(); |
- |
// FIXME: We don't balance properly at all in the presence of forced page breaks. We need to understand what |
// the distance between forced page breaks is so that we can avoid making the minimum column height too tall. |
ColumnInfo* colInfo = columnInfo(); |
- if (!hasSpecifiedPageLogicalHeight) { |
- LayoutUnit columnHeight = pageLogicalHeight; |
- int minColumnCount = colInfo->forcedBreaks() + 1; |
- int desiredColumnCount = colInfo->desiredColumnCount(); |
- if (minColumnCount >= desiredColumnCount) { |
- // The forced page breaks are in control of the balancing. Just set the column height to the |
- // maximum page break distance. |
- if (!pageLogicalHeight) { |
- LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(), |
- view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset()); |
- columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks); |
- } |
- } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) { |
- // Now that we know the intrinsic height of the columns, we have to rebalance them. |
- columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)layoutOverflowLogicalBottom / desiredColumnCount)); |
+ LayoutUnit columnHeight = pageLogicalHeight; |
+ const int minColumnCount = colInfo->forcedBreaks() + 1; |
+ const int desiredColumnCount = colInfo->desiredColumnCount(); |
+ if (minColumnCount >= desiredColumnCount) { |
+ // The forced page breaks are in control of the balancing. Just set the column height to the |
+ // maximum page break distance. |
+ if (!pageLogicalHeight) { |
+ LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(), |
+ view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset()); |
+ columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks); |
} |
+ } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) { |
+ // Now that we know the intrinsic height of the columns, we have to rebalance them. |
+ columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)layoutOverflowLogicalBottom / desiredColumnCount)); |
+ } |
- if (columnHeight && columnHeight != pageLogicalHeight) { |
- statePusher.pop(); |
- setEverHadLayout(true); |
- layoutBlockFlow(false, columnHeight); |
- return true; |
- } |
+ if (columnHeight && columnHeight != pageLogicalHeight) { |
+ pageLogicalHeight = columnHeight; |
+ return true; |
} |
+ return false; |
+} |
+ |
+void RenderBlockFlow::setColumnCountAndHeight(unsigned count, LayoutUnit pageLogicalHeight) |
+{ |
+ ColumnInfo* colInfo = columnInfo(); |
if (pageLogicalHeight) |
- colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight); |
+ colInfo->setColumnCountAndHeight(count, pageLogicalHeight); |
if (columnCount(colInfo)) { |
setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight()); |
m_overflow.clear(); |
- } else { |
- m_overflow = savedOverflow.release(); |
} |
- |
- return false; |
} |
bool RenderBlockFlow::isSelfCollapsingBlock() const |
@@ -248,11 +237,6 @@ bool RenderBlockFlow::isSelfCollapsingBlock() const |
void RenderBlockFlow::layoutBlock(bool relayoutChildren) |
{ |
- layoutBlockFlow(relayoutChildren); |
-} |
- |
-inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit pageLogicalHeight) |
-{ |
ASSERT(needsLayout()); |
ASSERT(isInlineBlockOrInlineTable() || !isInline()); |
@@ -264,6 +248,20 @@ inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit p |
if (!relayoutChildren && simplifiedLayout()) |
return; |
+ SubtreeLayoutScope layoutScope(this); |
+ |
+ // Multiple passes might be required for column and pagination based layout |
+ // In the case of the old column code the number of passes will only be two |
+ // however, in the newer column code the number of passes could equal the |
+ // number of columns. |
+ bool success = false; |
+ LayoutUnit pageLogicalHeight = 0; |
+ while (!success) |
+ success = tryLayoutBlockFlow(relayoutChildren, pageLogicalHeight, layoutScope); |
esprehn
2014/01/27 19:45:52
I'm not a fan of the success and try pattern here.
|
+} |
+ |
+inline bool RenderBlockFlow::tryLayoutBlockFlow(bool relayoutChildren, LayoutUnit &pageLogicalHeight, SubtreeLayoutScope& layoutScope) |
esprehn
2014/01/27 19:45:52
Do we need to rename this? It's not really "trying
|
+{ |
LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); |
if (updateLogicalWidthAndColumnWidth()) |
@@ -304,8 +302,6 @@ inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit p |
setPaginationStrut(0); |
} |
- SubtreeLayoutScope layoutScope(this); |
- |
LayoutUnit beforeEdge = borderBefore() + paddingBefore(); |
LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight(); |
LayoutUnit previousHeight = logicalHeight(); |
@@ -331,16 +327,41 @@ inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit p |
if (frameView()->partialLayout().isStopping()) { |
statePusher.pop(); |
- return; |
+ return true; |
} |
// Expand our intrinsic height to encompass floats. |
if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && expandsToEncloseOverhangingFloats()) |
setLogicalHeight(lowestFloatLogicalBottom() + afterEdge); |
- if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher) || relayoutToAvoidWidows(statePusher)) { |
- ASSERT(!shouldBreakAtLineToAvoidWidow()); |
- return; |
+ if (isRenderMultiColumnBlock()) { |
+ if (toRenderMultiColumnBlock(this)->shouldRelayoutMultiColumnBlock()) { |
+ setChildNeedsLayout(MarkOnlyThis); |
+ statePusher.pop(); |
+ return false; |
+ } |
+ } else if (hasColumns()) { |
+ OwnPtr<RenderOverflow> savedOverflow = m_overflow.release(); |
+ if (childrenInline()) |
+ addOverflowFromInlineChildren(); |
+ else |
+ addOverflowFromBlockChildren(); |
+ LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore(); |
+ m_overflow = savedOverflow.release(); |
+ |
+ if (!hasSpecifiedPageLogicalHeight && shouldRelayoutForPagination(pageLogicalHeight, layoutOverflowLogicalBottom)) { |
+ statePusher.pop(); |
+ setEverHadLayout(true); |
+ return false; |
+ } |
+ |
+ setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight); |
+ } |
+ |
+ if (shouldBreakAtLineToAvoidWidow()) { |
+ statePusher.pop(); |
+ setEverHadLayout(true); |
+ return false; |
} |
// Calculate our new height. |
@@ -383,7 +404,7 @@ inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit p |
fitBorderToLinesIfNeeded(); |
if (frameView()->partialLayout().isStopping()) |
- return; |
+ return true; |
if (renderView->layoutState()->m_pageLogicalHeight) |
setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop())); |
@@ -404,6 +425,7 @@ inline void RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit p |
} |
clearNeedsLayout(); |
+ return true; |
} |
void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom) |