void InitialColumnHeightFinder::examineBoxAfterEntering( const LayoutBox& box, LayoutUnit childLogicalHeight, EBreak previousBreakAfterValue) { if (m_lastBreakSeen > flowThreadOffset()) { // We have moved backwards. We're probably in a parallel flow, caused by // floats, sibling table cells, etc. m_lastBreakSeen = LayoutUnit(); } if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { if (box.needsForcedBreakBefore(previousBreakAfterValue)) { addContentRun(flowThreadOffset()); } else if (isFirstAfterBreak(flowThreadOffset()) && m_lastBreakSeen != flowThreadOffset()) { // This box is first after a soft break. m_lastBreakSeen = flowThreadOffset(); recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut()); } } if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { m_tallestUnbreakableLogicalHeight = std::max(m_tallestUnbreakableLogicalHeight, childLogicalHeight); return; } // Need to examine inner multicol containers to find their tallest unbreakable // piece of content. if (!box.isLayoutBlockFlow()) return; LayoutMultiColumnFlowThread* innerFlowThread = toLayoutBlockFlow(box).multiColumnFlowThread(); if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) return; LayoutUnit offsetInInnerFlowThread = flowThreadOffset() - innerFlowThread->blockOffsetInEnclosingFragmentationContext(); LayoutUnit innerUnbreakableHeight = innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread); m_tallestUnbreakableLogicalHeight = std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight); }
bool LayoutMultiColumnSet::heightIsAuto() const { LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread(); if (!flowThread->isLayoutPagedFlowThread()) { // If support for the column-fill property isn't enabled, we want to behave as if // column-fill were auto, so that multicol containers with specified height don't get their // columns balanced (auto-height multicol containers will still get their columns balanced, // even if column-fill isn't 'balance' - in accordance with the spec). Pretending that // column-fill is auto also matches the old multicol implementation, which has no support // for this property. if (multiColumnBlockFlow()->style()->getColumnFill() == ColumnFillBalance) return true; if (LayoutBox* next = nextSiblingBox()) { if (next->isLayoutMultiColumnSpannerPlaceholder()) { // If we're followed by a spanner, we need to balance. return true; } } } return !flowThread->columnHeightAvailable(); }
void InitialColumnHeightFinder::examineBoxAfterEntering( const LayoutBox& box, EBreak previousBreakAfterValue) { if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { if (box.needsForcedBreakBefore(previousBreakAfterValue)) { addContentRun(flowThreadOffset()); } else { ASSERT(isFirstAfterBreak(flowThreadOffset()) || !box.paginationStrut()); if (isFirstAfterBreak(flowThreadOffset())) { // This box is first after a soft break. recordStrutBeforeOffset(flowThreadOffset(), box.paginationStrut()); } } } if (box.getPaginationBreakability() != LayoutBox::AllowAnyBreaks) { LayoutUnit unsplittableLogicalHeight = box.logicalHeight(); if (box.isFloating()) unsplittableLogicalHeight += box.marginBefore() + box.marginAfter(); m_tallestUnbreakableLogicalHeight = std::max(m_tallestUnbreakableLogicalHeight, unsplittableLogicalHeight); return; } // Need to examine inner multicol containers to find their tallest unbreakable // piece of content. if (!box.isLayoutBlockFlow()) return; LayoutMultiColumnFlowThread* innerFlowThread = toLayoutBlockFlow(box).multiColumnFlowThread(); if (!innerFlowThread || innerFlowThread->isLayoutPagedFlowThread()) return; LayoutUnit offsetInInnerFlowThread = flowThreadOffset() - innerFlowThread->blockOffsetInEnclosingFragmentationContext(); LayoutUnit innerUnbreakableHeight = innerFlowThread->tallestUnbreakableLogicalHeight(offsetInInnerFlowThread); m_tallestUnbreakableLogicalHeight = std::max(m_tallestUnbreakableLogicalHeight, innerUnbreakableHeight); }
void MinimumSpaceShortageFinder::examineBoxAfterEntering( const LayoutBox& box, LayoutUnit childLogicalHeight, EBreak previousBreakAfterValue) { LayoutBox::PaginationBreakability breakability = box.getPaginationBreakability(); // Look for breaks before the child box. if (isLogicalTopWithinBounds(flowThreadOffset() - box.paginationStrut())) { if (box.needsForcedBreakBefore(previousBreakAfterValue)) { m_forcedBreaksCount++; } else { if (isFirstAfterBreak(flowThreadOffset())) { // This box is first after a soft break. LayoutUnit strut = box.paginationStrut(); // Figure out how much more space we would need to prevent it from being // pushed to the next column. recordSpaceShortage(childLogicalHeight - strut); if (breakability != LayoutBox::ForbidBreaks && m_pendingStrut == LayoutUnit::min()) { // We now want to look for the first piece of unbreakable content // (e.g. a line or a block-displayed image) inside this block. That // ought to be a good candidate for minimum space shortage; a much // better one than reporting space shortage for the entire block // (which we'll also do (further down), in case we couldn't find // anything more suitable). m_pendingStrut = strut; } } } } if (breakability != LayoutBox::ForbidBreaks) { // See if this breakable box crosses column boundaries. LayoutUnit bottomInFlowThread = flowThreadOffset() + childLogicalHeight; const MultiColumnFragmentainerGroup& group = groupAtOffset(flowThreadOffset()); if (isFirstAfterBreak(flowThreadOffset()) || group.columnLogicalTopForOffset(flowThreadOffset()) != group.columnLogicalTopForOffset(bottomInFlowThread)) { // If the child crosses a column boundary, record space shortage, in case // nothing inside it has already done so. The column balancer needs to // know by how much it has to stretch the columns to make more content // fit. If no breaks are reported (but do occur), the balancer will have // no clue. Only measure the space after the last column boundary, in case // it crosses more than one. LayoutUnit spaceUsedInLastColumn = bottomInFlowThread - group.columnLogicalTopForOffset(bottomInFlowThread); recordSpaceShortage(spaceUsedInLastColumn); } } // If this is an inner multicol container, look for space shortage inside it. if (!box.isLayoutBlockFlow()) return; LayoutMultiColumnFlowThread* flowThread = toLayoutBlockFlow(box).multiColumnFlowThread(); if (!flowThread || flowThread->isLayoutPagedFlowThread()) return; for (const LayoutMultiColumnSet* columnSet = flowThread->firstMultiColumnSet(); columnSet; columnSet = columnSet->nextSiblingMultiColumnSet()) { // Establish an inner shortage finder for this column set in the inner // multicol container. We need to let it walk through all fragmentainer // groups in one go, or we'd miss the column boundaries between each // fragmentainer group. We need to record space shortage there too. MinimumSpaceShortageFinder innerFinder( *columnSet, columnSet->logicalTopInFlowThread(), columnSet->logicalBottomInFlowThread()); recordSpaceShortage(innerFinder.minimumSpaceShortage()); } }