LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const { LayoutRect portionRect = flowThreadPortionRect(); if (isHorizontalWritingMode()) portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * pageLogicalHeight(), portionRect.width(), pageLogicalHeight()); else portionRect = LayoutRect(portionRect.x() + index * pageLogicalHeight(), portionRect.y(), pageLogicalHeight(), portionRect.height()); return portionRect; }
unsigned RenderMultiColumnSet::actualColumnCount() const { // We must always return a value of 1 or greater. Column count = 0 is a meaningless situation, // and will confuse and cause problems in other parts of the code. if (!pageLogicalHeight()) return 1; // Our portion rect determines our column count. We have as many columns as needed to fit all the content. LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width(); if (!logicalHeightInColumns) return 1; unsigned count = ceil(logicalHeightInColumns.toFloat() / pageLogicalHeight().toFloat()); ASSERT(count >= 1); return count; }
LayoutUnit RenderView::pageOrViewLogicalHeight() const { if (document().printing()) return pageLogicalHeight(); if (hasColumns() && !style()->hasInlineColumnAxis()) { if (int pageLength = frameView().pagination().pageLength) return pageLength; } return viewLogicalHeight(); }
void RenderMultiColumnSet::resetColumnHeight() { // Nuke previously stored minimum column height. Contents may have changed for all we know. m_minimumColumnHeight = 0; m_maxColumnHeight = calculateMaxColumnHeight(); LayoutUnit oldColumnHeight = pageLogicalHeight(); if (multiColumnFlowThread()->requiresBalancing()) m_columnHeight = 0; else setAndConstrainColumnHeight(heightAdjustedForSetOffset(multiColumnFlowThread()->columnHeightAvailable())); if (pageLogicalHeight() != oldColumnHeight) setChildNeedsLayout(MarkOnlyThis); // Content runs are only needed in the initial layout pass, in order to find an initial column // height, and should have been deleted afterwards. We're about to rebuild the content runs, so // the list needs to be empty. ASSERT(m_contentRuns.isEmpty()); }
void RenderNamedFlowFragment::invalidateRegionIfNeeded() { if (!isValid()) return; LayoutRect oldRegionRect(flowThreadPortionRect()); if (!isHorizontalWritingMode()) oldRegionRect = oldRegionRect.transposedRect(); if ((oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight()) && !m_flowThread->inFinalLayoutPhase()) { // This can happen even if we are in the inConstrainedLayoutPhase and it will trigger a pathological layout of the flow thread. m_flowThread->invalidateRegions(); } }
LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const { LayoutUnit colLogicalWidth = pageLogicalWidth(); LayoutUnit colLogicalHeight = pageLogicalHeight(); LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft(); LayoutUnit colGap = columnGap(); if (style()->isLeftToRightDirection()) colLogicalLeft += index * (colLogicalWidth + colGap); else colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap); if (isHorizontalWritingMode()) return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight); return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth); }
void RenderView::layout() { if (!document().paginated()) setPageLogicalHeight(0); if (shouldUsePrintingLayout()) m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth(); SubtreeLayoutScope layoutScope(*this); // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account. bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView || width() != viewWidth() || height() != viewHeight()); if (relayoutChildren) { layoutScope.setChildNeedsLayout(this); for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isSVGRoot()) continue; if ((child->isBox() && toRenderBox(child)->hasRelativeLogicalHeight()) || child->style()->logicalHeight().isPercent() || child->style()->logicalMinHeight().isPercent() || child->style()->logicalMaxHeight().isPercent()) layoutScope.setChildNeedsLayout(child); } if (document().svgExtensions()) document().accessSVGExtensions().invalidateSVGRootsWithRelativeLengthDescendents(&layoutScope); } ASSERT(!m_layoutState); if (!needsLayout()) return; LayoutState rootLayoutState(pageLogicalHeight(), pageLogicalHeightChanged(), *this); m_pageLogicalHeightChanged = false; layoutContent(); #if ENABLE(ASSERT) checkLayoutState(); #endif clearNeedsLayout(); }
unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset, ColumnIndexCalculationMode mode) const { LayoutRect portionRect(flowThreadPortionRect()); // Handle the offset being out of range. LayoutUnit flowThreadLogicalTop = isHorizontalWritingMode() ? portionRect.y() : portionRect.x(); if (offset < flowThreadLogicalTop) return 0; // If we're laying out right now, we cannot constrain against some logical bottom, since it // isn't known yet. Otherwise, just return the last column if we're past the logical bottom. if (mode == ClampToExistingColumns) { LayoutUnit flowThreadLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX(); if (offset >= flowThreadLogicalBottom) return actualColumnCount() - 1; } // Just divide by the column height to determine the correct column. return (offset - flowThreadLogicalTop).toFloat() / pageLogicalHeight().toFloat(); }
void LayoutState::computeLineGridPaginationOrigin(RenderBox* renderer) { // We need to cache a line grid pagination origin so that we understand how to reset the line grid // at the top of each column. // Get the current line grid and offset. if (!lineGrid() || lineGrid()->style().writingMode() != renderer->style().writingMode()) return; // Get the hypothetical line box used to establish the grid. RootInlineBox* lineGridBox = lineGrid()->lineGridBox(); if (!lineGridBox) return; bool isHorizontalWritingMode = lineGrid()->isHorizontalWritingMode(); LayoutUnit lineGridBlockOffset = isHorizontalWritingMode ? lineGridOffset().height() : lineGridOffset().width(); // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple // as established by the line box. // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume // the grid should honor line-box-contain. LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading(); if (!gridLineHeight) return; LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading(); if (isPaginated() && pageLogicalHeight()) { LayoutUnit pageLogicalTop = renderer->isHorizontalWritingMode() ? m_pageOffset.height() : m_pageOffset.width(); if (pageLogicalTop > firstLineTopWithLeading) { // Shift to the next highest line grid multiple past the page logical top. Cache the delta // between this new value and the page logical top as the pagination origin. LayoutUnit remainder = roundToInt(pageLogicalTop - firstLineTopWithLeading) % roundToInt(gridLineHeight); LayoutUnit paginationDelta = gridLineHeight - remainder; if (isHorizontalWritingMode) m_lineGridPaginationOrigin.setHeight(paginationDelta); else m_lineGridPaginationOrigin.setWidth(paginationDelta); } } }
void RenderRegion::layoutBlock(bool relayoutChildren, LayoutUnit) { StackStats::LayoutCheckPoint layoutCheckPoint; RenderBlock::layoutBlock(relayoutChildren); if (isValid()) { LayoutRect oldRegionRect(flowThreadPortionRect()); if (!isHorizontalWritingMode()) oldRegionRect = oldRegionRect.transposedRect(); if (hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase()) { m_flowThread->invalidateRegions(); clearOverrideLogicalContentHeight(); return; } if (!isRenderRegionSet() && (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight())) // This can happen even if we are in the inConstrainedLayoutPhase and it will trigger a pathological layout of the flow thread. m_flowThread->invalidateRegions(); } // FIXME: We need to find a way to set up overflow properly. Our flow thread hasn't gotten a layout // yet, so we can't look to it for correct information. It's possible we could wait until after the RenderFlowThread // gets a layout, and then try to propagate overflow information back to the region, and then mark for a second layout. // That second layout would then be able to use the information from the RenderFlowThread to set up overflow. // // The big problem though is that overflow needs to be region-specific. We can't simply use the RenderFlowThread's global // overflow values, since then we'd always think any narrow region had huge overflow (all the way to the width of the // RenderFlowThread itself). // // We'll need to expand RenderBoxRegionInfo to also hold left and right overflow values. }
LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const { return pageLogicalHeight(); }
void RenderNamedFlowFragment::layoutBlock(bool relayoutChildren, LayoutUnit) { StackStats::LayoutCheckPoint layoutCheckPoint; RenderRegion::layoutBlock(relayoutChildren); if (isValid()) { LayoutRect oldRegionRect(flowThreadPortionRect()); if (!isHorizontalWritingMode()) oldRegionRect = oldRegionRect.transposedRect(); if (m_flowThread->inOverflowLayoutPhase() || m_flowThread->inFinalLayoutPhase()) { computeOverflowFromFlowThread(); updateOversetState(); } if (hasAutoLogicalHeight() && m_flowThread->inMeasureContentLayoutPhase()) { m_flowThread->invalidateRegions(); clearComputedAutoHeight(); return; } if ((oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight()) && !m_flowThread->inFinalLayoutPhase()) // This can happen even if we are in the inConstrainedLayoutPhase and it will trigger a pathological layout of the flow thread. m_flowThread->invalidateRegions(); } }
LayoutUnit RenderView::viewLogicalHeightForPercentages() const { if (shouldUsePrintingLayout()) return pageLogicalHeight(); return viewLogicalHeight(); }
LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const { unsigned columnIndex = columnIndexAtOffset(offset, AssumeNewColumns); return logicalTopInFlowThread() + columnIndex * pageLogicalHeight(); }