| Index: Source/core/layout/MultiColumnFragmentainerGroup.cpp
 | 
| diff --git a/Source/core/layout/MultiColumnFragmentainerGroup.cpp b/Source/core/layout/MultiColumnFragmentainerGroup.cpp
 | 
| index f72aed8e9ff4c97c425ad51281d6576fad697006..b67612d7a9ae65f8f537fac9f7397576837d8c7e 100644
 | 
| --- a/Source/core/layout/MultiColumnFragmentainerGroup.cpp
 | 
| +++ b/Source/core/layout/MultiColumnFragmentainerGroup.cpp
 | 
| @@ -28,6 +28,11 @@ LayoutSize MultiColumnFragmentainerGroup::offsetFromColumnSet() const
 | 
|      return offset;
 | 
|  }
 | 
|  
 | 
| +LayoutUnit MultiColumnFragmentainerGroup::blockOffsetInEnclosingFlowThread() const
 | 
| +{
 | 
| +    return logicalTop() + m_columnSet.logicalTop() + m_columnSet.multiColumnFlowThread()->blockOffsetInEnclosingFlowThread();
 | 
| +}
 | 
| +
 | 
|  bool MultiColumnFragmentainerGroup::heightIsAuto() const
 | 
|  {
 | 
|      // Only the last row may have auto height, and thus be balanced. There are no good reasons to
 | 
| @@ -45,10 +50,18 @@ void MultiColumnFragmentainerGroup::resetColumnHeight()
 | 
|  
 | 
|      LayoutUnit oldColumnHeight = m_columnHeight;
 | 
|  
 | 
| -    if (heightIsAuto())
 | 
| +    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(m_columnSet.multiColumnFlowThread()->columnHeightAvailable()));
 | 
| +    } else {
 | 
| +        setAndConstrainColumnHeight(heightAdjustedForRowOffset(flowThread->columnHeightAvailable()));
 | 
| +    }
 | 
|  
 | 
|      if (m_columnHeight != oldColumnHeight)
 | 
|          m_columnSet.setChildNeedsLayout(MarkOnlyThis);
 | 
| @@ -119,14 +132,35 @@ bool MultiColumnFragmentainerGroup::recalculateColumnHeight(BalancedColumnHeight
 | 
|  
 | 
|  LayoutSize MultiColumnFragmentainerGroup::flowThreadTranslationAtOffset(LayoutUnit offsetInFlowThread) const
 | 
|  {
 | 
| -    LayoutFlowThread* flowThread = m_columnSet.flowThread();
 | 
| +    LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread();
 | 
|      unsigned columnIndex = columnIndexAtOffset(offsetInFlowThread);
 | 
|      LayoutRect portionRect(flowThreadPortionRectAt(columnIndex));
 | 
|      flowThread->flipForWritingMode(portionRect);
 | 
|      LayoutRect columnRect(columnRectAt(columnIndex));
 | 
|      m_columnSet.flipForWritingMode(columnRect);
 | 
|      LayoutSize translationRelativeToGroup = columnRect.location() - portionRect.location();
 | 
| -    return translationRelativeToGroup + offsetFromColumnSet() + m_columnSet.topLeftLocationOffset() - flowThread->topLeftLocationOffset();
 | 
| +
 | 
| +    LayoutSize enclosingTranslation;
 | 
| +    if (LayoutMultiColumnFlowThread* enclosingFlowThread = flowThread->enclosingFlowThread()) {
 | 
| +        // Translation that would map points in the coordinate space of the outermost flow thread to
 | 
| +        // visual points in the first column in the first fragmentainer group (row) in our multicol
 | 
| +        // container.
 | 
| +        LayoutSize enclosingTranslationOrigin = enclosingFlowThread->flowThreadTranslationAtOffset(flowThread->blockOffsetInEnclosingFlowThread());
 | 
| +
 | 
| +        // Translation that would map points in the coordinate space of the outermost flow thread to
 | 
| +        // visual points in the first column in this fragmentainer group.
 | 
| +        enclosingTranslation = enclosingFlowThread->flowThreadTranslationAtOffset(blockOffsetInEnclosingFlowThread());
 | 
| +
 | 
| +        // What we ultimately return from this method is a translation that maps points in the
 | 
| +        // coordinate space of our flow thread to a visual point in a certain column in this
 | 
| +        // fragmentainer group. We had to go all the way up to the outermost flow thread, since this
 | 
| +        // fragmentainer group may be in a different outer column than the first outer column that
 | 
| +        // this multicol container lives in. It's the visual distance between the first
 | 
| +        // fragmentainer group and this fragmentainer group that we need to add to the translation.
 | 
| +        enclosingTranslation -= enclosingTranslationOrigin;
 | 
| +    }
 | 
| +
 | 
| +    return enclosingTranslation + translationRelativeToGroup + offsetFromColumnSet() + m_columnSet.topLeftLocationOffset() - flowThread->topLeftLocationOffset();
 | 
|  }
 | 
|  
 | 
|  LayoutUnit MultiColumnFragmentainerGroup::columnLogicalTopForOffset(LayoutUnit offsetInFlowThread) const
 | 
| @@ -308,14 +342,26 @@ LayoutUnit MultiColumnFragmentainerGroup::calculateMaxColumnHeight() const
 | 
|  {
 | 
|      LayoutBlockFlow* multicolBlock = m_columnSet.multiColumnBlockFlow();
 | 
|      const ComputedStyle& multicolStyle = multicolBlock->styleRef();
 | 
| -    LayoutUnit availableHeight = m_columnSet.multiColumnFlowThread()->columnHeightAvailable();
 | 
| +    LayoutMultiColumnFlowThread* flowThread = m_columnSet.multiColumnFlowThread();
 | 
| +    LayoutUnit availableHeight = flowThread->columnHeightAvailable();
 | 
|      LayoutUnit maxColumnHeight = availableHeight ? availableHeight : LayoutUnit::max();
 | 
|      if (!multicolStyle.logicalMaxHeight().isMaxSizeNone()) {
 | 
|          LayoutUnit logicalMaxHeight = multicolBlock->computeContentLogicalHeight(MaxSize, multicolStyle.logicalMaxHeight(), -1);
 | 
|          if (logicalMaxHeight != -1 && maxColumnHeight > logicalMaxHeight)
 | 
|              maxColumnHeight = logicalMaxHeight;
 | 
|      }
 | 
| -    return heightAdjustedForRowOffset(maxColumnHeight);
 | 
| +    LayoutUnit maxHeight = heightAdjustedForRowOffset(maxColumnHeight);
 | 
| +    if (LayoutMultiColumnFlowThread* enclosingFlowThread = flowThread->enclosingFlowThread()) {
 | 
| +        if (enclosingFlowThread->isPageLogicalHeightKnown()) {
 | 
| +            // We're nested inside another fragmentation context whose fragmentainer heights are
 | 
| +            // known. This constrains the max height.
 | 
| +            LayoutUnit remainingOuterLogicalHeight = enclosingFlowThread->pageRemainingLogicalHeightForOffset(blockOffsetInEnclosingFlowThread(), LayoutBlock::AssociateWithLatterPage);
 | 
| +            ASSERT(remainingOuterLogicalHeight > 0);
 | 
| +            if (maxHeight > remainingOuterLogicalHeight)
 | 
| +                maxHeight = remainingOuterLogicalHeight;
 | 
| +        }
 | 
| +    }
 | 
| +    return maxHeight;
 | 
|  }
 | 
|  
 | 
|  void MultiColumnFragmentainerGroup::setAndConstrainColumnHeight(LayoutUnit newHeight)
 | 
| @@ -323,7 +369,6 @@ void MultiColumnFragmentainerGroup::setAndConstrainColumnHeight(LayoutUnit newHe
 | 
|      m_columnHeight = newHeight;
 | 
|      if (m_columnHeight > m_maxColumnHeight)
 | 
|          m_columnHeight = m_maxColumnHeight;
 | 
| -    // FIXME: the height may also be affected by the enclosing pagination context, if any.
 | 
|  }
 | 
|  
 | 
|  unsigned MultiColumnFragmentainerGroup::findRunWithTallestColumns() const
 | 
| @@ -469,16 +514,18 @@ LayoutRect MultiColumnFragmentainerGroup::flowThreadPortionOverflowRectAt(unsign
 | 
|      //
 | 
|      // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting
 | 
|      // mode that understands not to paint contents from a previous column in the overflow area of a following column.
 | 
| -    bool isFirstColumn = !columnIndex;
 | 
| -    bool isLastColumn = columnIndex == actualColumnCount() - 1;
 | 
| +    bool isFirstColumnInRow = !columnIndex;
 | 
| +    bool isLastColumnInRow = columnIndex == actualColumnCount() - 1;
 | 
|      bool isLTR = m_columnSet.style()->isLeftToRightDirection();
 | 
| -    bool isLeftmostColumn = isLTR ? isFirstColumn : isLastColumn;
 | 
| -    bool isRightmostColumn = isLTR ? isLastColumn : isFirstColumn;
 | 
| +    bool isLeftmostColumn = isLTR ? isFirstColumnInRow : isLastColumnInRow;
 | 
| +    bool isRightmostColumn = isLTR ? isLastColumnInRow : isFirstColumnInRow;
 | 
|  
 | 
|      LayoutRect portionRect = flowThreadPortionRectAt(columnIndex);
 | 
| +    bool isFirstColumnInMulticolContainer = isFirstColumnInRow && this == &m_columnSet.firstFragmentainerGroup() && !m_columnSet.previousSiblingMultiColumnSet();
 | 
| +    bool isLastColumnInMulticolContainer = isLastColumnInRow && this == &m_columnSet.lastFragmentainerGroup() && !m_columnSet.nextSiblingMultiColumnSet();
 | 
|      // Calculate the overflow rectangle, based on the flow thread's, clipped at column logical
 | 
|      // top/bottom unless it's the first/last column.
 | 
| -    LayoutRect overflowRect = m_columnSet.overflowRectForFlowThreadPortion(portionRect, isFirstColumn && !m_columnSet.previousSiblingMultiColumnSet(), isLastColumn && !m_columnSet.nextSiblingMultiColumnSet());
 | 
| +    LayoutRect overflowRect = m_columnSet.overflowRectForFlowThreadPortion(portionRect, isFirstColumnInMulticolContainer, isLastColumnInMulticolContainer);
 | 
|  
 | 
|      // Avoid overflowing into neighboring columns, by clipping in the middle of adjacent column
 | 
|      // gaps. Also make sure that we avoid rounding errors.
 | 
| 
 |