| 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.
|
|
|