bool MultiColumnFragmentainerGroup::recalculateColumnHeight(BalancedColumnHeightCalculation calculationMode) { LayoutUnit oldColumnHeight = m_columnHeight; m_maxColumnHeight = calculateMaxColumnHeight(); if (heightIsAuto()) { if (calculationMode == GuessFromFlowThreadPortion) { // Post-process the content runs and find out where the implicit breaks will occur. distributeImplicitBreaks(); } LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); setAndConstrainColumnHeight(newColumnHeight); // After having calculated an initial column height, the multicol container typically needs at // least one more layout pass with a new column height, but if a height was specified, we only // need to do this if we think that we need less space than specified. Conversely, if we // determined that the columns need to be as tall as the specified height of the container, we // have already laid it out correctly, and there's no need for another pass. } else { // The position of the column set may have changed, in which case height available for // columns may have changed as well. setAndConstrainColumnHeight(m_columnHeight); } // We can get rid of the content runs now, if we haven't already done so. They are only needed // to calculate the initial balanced column height. In fact, we have to get rid of them before // the next layout pass, since each pass will rebuild this. m_contentRuns.clear(); if (m_columnHeight == oldColumnHeight) return false; // No change. We're done. m_minSpaceShortage = LayoutUnit::max(); return true; // Need another pass. }
bool MultiColumnFragmentainerGroup::recalculateColumnHeight(BalancedColumnHeightCalculation calculationMode) { LayoutUnit oldColumnHeight = m_columnHeight; m_maxColumnHeight = calculateMaxColumnHeight(); if (heightIsAuto()) { LayoutUnit newColumnHeight = calculateColumnHeight(calculationMode); setAndConstrainColumnHeight(newColumnHeight); // After having calculated an initial column height, the multicol container typically needs at // least one more layout pass with a new column height, but if a height was specified, we only // need to do this if we think that we need less space than specified. Conversely, if we // determined that the columns need to be as tall as the specified height of the container, we // have already laid it out correctly, and there's no need for another pass. } else { // The position of the column set may have changed, in which case height available for // columns may have changed as well. setAndConstrainColumnHeight(m_columnHeight); } if (m_columnHeight == oldColumnHeight) return false; // No change. We're done. return true; // Need another pass. }
bool MultiColumnFragmentainerGroup::recalculateColumnHeight( LayoutMultiColumnSet& columnSet) { LayoutUnit oldColumnHeight = m_columnHeight; m_maxColumnHeight = calculateMaxColumnHeight(); // Only the last row may have auto height, and thus be balanced. There are no // good reasons to balance the preceding rows, and that could potentially lead // to an insane number of layout passes as well. if (isLastGroup() && columnSet.heightIsAuto()) { LayoutUnit newColumnHeight; if (!columnSet.isInitialHeightCalculated()) { // Initial balancing: Start with the lowest imaginable column height. Also // calculate the height of the tallest piece of unbreakable content. // Columns should never get any shorter than that (unless constrained by // max-height). Propagate this to our containing column set, in case there // is an outer multicol container that also needs to balance. After having // calculated the initial column height, the multicol container needs // another layout pass with the column height that we just calculated. InitialColumnHeightFinder initialHeightFinder( columnSet, logicalTopInFlowThread(), logicalBottomInFlowThread()); LayoutUnit tallestUnbreakableLogicalHeight = initialHeightFinder.tallestUnbreakableLogicalHeight(); columnSet.propagateTallestUnbreakableLogicalHeight( tallestUnbreakableLogicalHeight); newColumnHeight = std::max(initialHeightFinder.initialMinimalBalancedHeight(), tallestUnbreakableLogicalHeight); } else { // Rebalancing: After having laid out again, we'll need to rebalance if // the height wasn't enough and we're allowed to stretch it, and then // re-lay out. There are further details on the column balancing // machinery in ColumnBalancer and its derivates. newColumnHeight = rebalanceColumnHeightIfNeeded(); } setAndConstrainColumnHeight(newColumnHeight); } else { // The position of the column set may have changed, in which case height // available for columns may have changed as well. setAndConstrainColumnHeight(m_columnHeight); } if (m_columnHeight == oldColumnHeight) return false; // No change. We're done. return true; // Need another pass. }
void MultiColumnFragmentainerGroup::resetColumnHeight() { m_maxColumnHeight = calculateMaxColumnHeight(); LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread(); if (m_columnSet.heightIsAuto()) { FragmentationContext* enclosingFragmentationContext = flowThread->enclosingFragmentationContext(); if (enclosingFragmentationContext && enclosingFragmentationContext->isFragmentainerLogicalHeightKnown()) { // Even if height is auto, we set an initial height, in order to tell how much content // this MultiColumnFragmentainerGroup can hold, and when we need to append a new one. m_columnHeight = m_maxColumnHeight; } else { m_columnHeight = LayoutUnit(); } } else { setAndConstrainColumnHeight(heightAdjustedForRowOffset(flowThread->columnHeightAvailable())); } }
void MultiColumnFragmentainerGroup::resetColumnHeight() { // Nuke previously stored minimum column height. Contents may have changed for all we know. m_minimumColumnHeight = 0; m_maxColumnHeight = calculateMaxColumnHeight(); LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread(); LayoutMultiColumnFlowThread* enclosingFlowThread = flowThread->enclosingFlowThread(); if (enclosingFlowThread && enclosingFlowThread->isPageLogicalHeightKnown()) { // TODO(mstensho): Do this better. If height is auto here, we shouldn't set a // height, or forced breaks and pagination struts might mess up column balancing. LayoutUnit columnHeight = heightIsAuto() ? m_maxColumnHeight : heightAdjustedForRowOffset(flowThread->columnHeightAvailable()); setAndConstrainColumnHeight(columnHeight); } else if (heightIsAuto()) { m_columnHeight = LayoutUnit(); } else { setAndConstrainColumnHeight(heightAdjustedForRowOffset(flowThread->columnHeightAvailable())); } }
void MultiColumnFragmentainerGroup::resetColumnHeight() { // Nuke previously stored minimum column height. Contents may have changed for all we know. m_minimumColumnHeight = 0; m_maxColumnHeight = calculateMaxColumnHeight(); LayoutUnit oldColumnHeight = m_columnHeight; if (heightIsAuto()) m_columnHeight = LayoutUnit(); else setAndConstrainColumnHeight(heightAdjustedForRowOffset(m_columnSet.multiColumnFlowThread()->columnHeightAvailable())); if (m_columnHeight != oldColumnHeight) m_columnSet.setChildNeedsLayout(MarkOnlyThis); // Content runs are only needed in the initial layout pass, in order to find an initial column // height, and should have been deleted afterwards. We're about to rebuild the content runs, so // the list needs to be empty. ASSERT(m_contentRuns.isEmpty()); }