LayoutUnit LayoutMultiColumnSet::pageLogicalHeightForOffset(LayoutUnit offsetInFlowThread) const
{
    const MultiColumnFragmentainerGroup &lastRow = lastFragmentainerGroup();
    if (!lastRow.logicalHeight()) {
        // In the first layout pass of an auto-height multicol container, height isn't set. No need
        // to perform the series of complicated dance steps below to figure out that we should
        // simply return 0. Bail now.
        ASSERT(m_fragmentainerGroups.size() == 1);
        return LayoutUnit();
    }
    if (offsetInFlowThread >= lastRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(lastRow)) {
        // The offset is outside the bounds of the fragmentainer groups that we have established at
        // this point. If we're nested inside another fragmentation context, we need to calculate
        // the height on our own.
        const LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread();
        if (FragmentationContext* enclosingFragmentationContext = flowThread->enclosingFragmentationContext()) {
            // We'd ideally like to translate |offsetInFlowThread| to an offset in the coordinate
            // space of the enclosing fragmentation context here, but that's hard, since the offset
            // is out of bounds. So just use the bottom we have found so far.
            LayoutUnit enclosingContextBottom = lastRow.blockOffsetInEnclosingFragmentationContext() + lastRow.logicalHeight();
            LayoutUnit enclosingFragmentainerHeight = enclosingFragmentationContext->fragmentainerLogicalHeightAt(enclosingContextBottom);
            // Constrain against specified height / max-height.
            LayoutUnit currentMulticolHeight = logicalTopFromMulticolContentEdge() + lastRow.logicalTop() + lastRow.logicalHeight();
            LayoutUnit multicolHeightWithExtraRow = currentMulticolHeight + enclosingFragmentainerHeight;
            multicolHeightWithExtraRow = std::min(multicolHeightWithExtraRow, flowThread->maxColumnLogicalHeight());
            return std::max(LayoutUnit(1), multicolHeightWithExtraRow - currentMulticolHeight);
        }
    }
    return fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread).logicalHeight();
}
LayoutUnit LayoutMultiColumnSet::pageRemainingLogicalHeightForOffset(LayoutUnit offsetInFlowThread, PageBoundaryRule pageBoundaryRule) const
{
    const MultiColumnFragmentainerGroup& row = fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread);
    LayoutUnit pageLogicalHeight = row.logicalHeight();
    ASSERT(pageLogicalHeight); // It's not allowed to call this method if the height is unknown.
    LayoutUnit pageLogicalBottom = row.columnLogicalTopForOffset(offsetInFlowThread) + pageLogicalHeight;
    LayoutUnit remainingLogicalHeight = pageLogicalBottom - offsetInFlowThread;

    if (pageBoundaryRule == AssociateWithFormerPage) {
        // An offset exactly at a column boundary will act as being part of the former column in
        // question (i.e. no remaining space), rather than being part of the latter (i.e. one whole
        // column length of remaining space).
        remainingLogicalHeight = intMod(remainingLogicalHeight, pageLogicalHeight);
    }
    return remainingLogicalHeight;
}
示例#3
0
void LayoutMultiColumnSet::recordSpaceShortage(LayoutUnit offsetInFlowThread, LayoutUnit spaceShortage)
{
    MultiColumnFragmentainerGroup& row = fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread);
    row.recordSpaceShortage(spaceShortage);

    // Since we're at a potential break here, take the opportunity to check if we need another
    // fragmentainer group. If we've run out of columns in the last fragmentainer group (column
    // row), we need to insert another fragmentainer group to hold more columns.
    if (!row.isLastGroup())
        return;
    LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread();
    if (!flowThread->multiColumnBlockFlow()->isInsideFlowThread())
        return; // Early bail. We're not nested, so waste no more time on this.
    if (!flowThread->isInInitialLayoutPass())
        return;
    // Move the offset to where the next column starts, if we're not there already.
    offsetInFlowThread += flowThread->pageRemainingLogicalHeightForOffset(offsetInFlowThread, AssociateWithFormerPage);

    flowThread->appendNewFragmentainerGroupIfNeeded(offsetInFlowThread);
}
LayoutUnit LayoutMultiColumnSet::pageRemainingLogicalHeightForOffset(LayoutUnit offsetInFlowThread, PageBoundaryRule pageBoundaryRule) const
{
    const MultiColumnFragmentainerGroup& row = fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread);
    LayoutUnit pageLogicalHeight = row.logicalHeight();
    ASSERT(pageLogicalHeight); // It's not allowed to call this method if the height is unknown.
    LayoutUnit pageLogicalBottom = row.columnLogicalTopForOffset(offsetInFlowThread) + pageLogicalHeight;
    LayoutUnit remainingLogicalHeight = pageLogicalBottom - offsetInFlowThread;

    if (pageBoundaryRule == AssociateWithFormerPage) {
        // An offset exactly at a column boundary will act as being part of the former column in
        // question (i.e. no remaining space), rather than being part of the latter (i.e. one whole
        // column length of remaining space).
        remainingLogicalHeight = intMod(remainingLogicalHeight, pageLogicalHeight);
    } else if (!remainingLogicalHeight) {
        // When pageBoundaryRule is AssociateWithLatterPage, we should never return 0, because if
        // there's no space left, it means that we should be at a column boundary, in which case we
        // should return the amount of space remaining in the *next* column. But this is not true if
        // the offset is "infinite" (saturated), so allow this to happen in that case.
        ASSERT(offsetInFlowThread.mightBeSaturated());
        remainingLogicalHeight = pageLogicalHeight;
    }
    return remainingLogicalHeight;
}
LayoutUnit LayoutMultiColumnSet::pageLogicalHeightForOffset(LayoutUnit offsetInFlowThread) const
{
    return fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread).logicalHeight();
}
LayoutUnit LayoutMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
{
    return fragmentainerGroupAtFlowThreadOffset(offset).columnLogicalTopForOffset(offset);
}
void LayoutMultiColumnSet::updateMinimumColumnHeight(LayoutUnit offsetInFlowThread, LayoutUnit height)
{
    fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread).updateMinimumColumnHeight(height);
}
LayoutSize LayoutMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockOffset) const
{
    return fragmentainerGroupAtFlowThreadOffset(blockOffset).flowThreadTranslationAtOffset(blockOffset);
}
LayoutSize LayoutMultiColumnSet::flowThreadTranslationAtOffset(LayoutUnit blockOffset, CoordinateSpaceConversion mode) const
{
    return fragmentainerGroupAtFlowThreadOffset(blockOffset).flowThreadTranslationAtOffset(blockOffset, mode);
}
示例#10
0
void LayoutMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage)
{
    if (!heightIsAuto())
        return;
    fragmentainerGroupAtFlowThreadOffset(endOffsetFromFirstPage).addContentRun(endOffsetFromFirstPage);
}
void LayoutMultiColumnSet::recordSpaceShortage(LayoutUnit offsetInFlowThread, LayoutUnit spaceShortage)
{
    fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread).recordSpaceShortage(spaceShortage);
}