void RenderView::addChild(RenderObject* newChild, RenderObject* beforeChild) { // Seamless iframes are considered part of an enclosing render flow thread from the parent document. This is necessary for them to look // up regions in the parent document during layout. if (newChild && !newChild->isRenderFlowThread()) { RenderBox* seamlessBox = enclosingSeamlessRenderer(document()); if (seamlessBox && seamlessBox->flowThreadContainingBlock()) newChild->setFlowThreadState(seamlessBox->flowThreadState()); } RenderBlock::addChild(newChild, beforeChild); }
LayoutState::LayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo, bool containingBlockLogicalWidthChanged) : m_containingBlockLogicalWidthChanged(containingBlockLogicalWidthChanged) , m_columnInfo(columnInfo) , m_next(renderer.view()->layoutState()) , m_renderer(renderer) { m_flowThread = renderer.isRenderFlowThread() ? toRenderFlowThread(&renderer) : m_next->flowThread(); renderer.view()->pushLayoutState(*this); bool fixed = renderer.isOutOfFlowPositioned() && renderer.style()->position() == FixedPosition; if (fixed) { // FIXME: This doesn't work correctly with transforms. FloatPoint fixedOffset = renderer.view()->localToAbsolute(FloatPoint(), IsFixed); m_layoutOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset; } else { m_layoutOffset = m_next->m_layoutOffset + offset; } if (renderer.isOutOfFlowPositioned() && !fixed) { if (RenderObject* container = renderer.container()) { if (container->style()->hasInFlowPosition() && container->isRenderInline()) m_layoutOffset += toRenderInline(container)->offsetForInFlowPositionedInline(renderer); } } // If we establish a new page height, then cache the offset to the top of the first page. // We can compare this later on to figure out what part of the page we're actually on, if (pageLogicalHeight || m_columnInfo || renderer.isRenderFlowThread()) { m_pageLogicalHeight = pageLogicalHeight; bool isFlipped = renderer.style()->isFlippedBlocksWritingMode(); m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer.borderLeft() + renderer.paddingLeft() : renderer.borderRight() + renderer.paddingRight()), m_layoutOffset.height() + (!isFlipped ? renderer.borderTop() + renderer.paddingTop() : renderer.borderBottom() + renderer.paddingBottom())); m_pageLogicalHeightChanged = pageLogicalHeightChanged; m_isPaginated = true; } else { // If we don't establish a new page height, then propagate the old page height and offset down. m_pageLogicalHeight = m_next->m_pageLogicalHeight; m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged; m_pageOffset = m_next->m_pageOffset; // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and // writing mode roots. if (renderer.isUnsplittableForPagination()) { m_pageLogicalHeight = 0; m_isPaginated = false; } else { m_isPaginated = m_pageLogicalHeight || m_next->m_columnInfo || renderer.flowThreadContainingBlock(); } } if (!m_columnInfo) m_columnInfo = m_next->m_columnInfo; // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present. }
bool RenderView::initializeLayoutState(LayoutState& state) { bool isSeamlessAncestorInFlowThread = false; // FIXME: May be better to push a clip and avoid issuing offscreen repaints. state.m_clipped = false; // Check the writing mode of the seamless ancestor. It has to match our document's writing mode, or we won't inherit any // pagination information. RenderBox* seamlessAncestor = enclosingSeamlessRenderer(document()); LayoutState* seamlessLayoutState = seamlessAncestor ? seamlessAncestor->view().layoutState() : 0; bool shouldInheritPagination = seamlessLayoutState && !m_pageLogicalHeight && seamlessAncestor->style()->writingMode() == style()->writingMode(); state.m_pageLogicalHeight = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeight : m_pageLogicalHeight; state.m_pageLogicalHeightChanged = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeightChanged : m_pageLogicalHeightChanged; state.m_isPaginated = state.m_pageLogicalHeight; if (state.m_isPaginated && shouldInheritPagination) { // Set up the correct pagination offset. We can use a negative offset in order to push the top of the RenderView into its correct place // on a page. We can take the iframe's offset from the logical top of the first page and make the negative into the pagination offset within the child // view. bool isFlipped = seamlessAncestor->style()->isFlippedBlocksWritingMode(); LayoutSize layoutOffset = seamlessLayoutState->layoutOffset(); LayoutSize iFrameOffset(layoutOffset.width() + seamlessAncestor->x() + (!isFlipped ? seamlessAncestor->borderLeft() + seamlessAncestor->paddingLeft() : seamlessAncestor->borderRight() + seamlessAncestor->paddingRight()), layoutOffset.height() + seamlessAncestor->y() + (!isFlipped ? seamlessAncestor->borderTop() + seamlessAncestor->paddingTop() : seamlessAncestor->borderBottom() + seamlessAncestor->paddingBottom())); LayoutSize offsetDelta = seamlessLayoutState->m_pageOffset - iFrameOffset; state.m_pageOffset = offsetDelta; // Set the current render flow thread to point to our ancestor. This will allow the seamless document to locate the correct // regions when doing a layout. if (seamlessAncestor->flowThreadContainingBlock()) { flowThreadController().setCurrentRenderFlowThread(seamlessAncestor->view().flowThreadController().currentRenderFlowThread()); isSeamlessAncestorInFlowThread = true; } } // FIXME: We need to make line grids and exclusions work with seamless iframes as well here. Basically all layout state information needs // to propagate here and not just pagination information. return isSeamlessAncestorInFlowThread; }