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; }
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); }
void LayoutMultiColumnSet::addContentRun(LayoutUnit endOffsetFromFirstPage) { if (!heightIsAuto()) return; fragmentainerGroupAtFlowThreadOffset(endOffsetFromFirstPage).addContentRun(endOffsetFromFirstPage); }
void LayoutMultiColumnSet::recordSpaceShortage(LayoutUnit offsetInFlowThread, LayoutUnit spaceShortage) { fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread).recordSpaceShortage(spaceShortage); }