void RenderMultiColumnBlock::ensureColumnSets() { // This function ensures we have the correct column set information before we get into layout. // 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 region. // // 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. if (!flowThread()) return; RenderMultiColumnSet* columnSet = firstChild()->isRenderMultiColumnSet() ? toRenderMultiColumnSet(firstChild()) : 0; if (!columnSet) { columnSet = RenderMultiColumnSet::createAnonymous(flowThread()); columnSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK)); RenderBlock::addChild(columnSet, firstChild()); } columnSet->setRequiresBalancing(requiresBalancing()); }
bool RenderMultiColumnBlock::relayoutForPagination(bool, LayoutUnit, LayoutStateMaintainer& statePusher) { 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(MarkOnlyThis); needsRelayout = true; } } if (needsRelayout) { // Layout again. Column balancing resulted in a new height. neededRelayout = true; m_flowThread->setChildNeedsLayout(MarkOnlyThis); setChildNeedsLayout(MarkOnlyThis); if (firstPass) statePusher.pop(); layoutBlock(false); } firstPass = false; } while (needsRelayout); m_inBalancingPass = false; return neededRelayout; }