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());
}