void BlockPainter::paintContinuationOutlines(const PaintInfo& info, const LayoutPoint& paintOffset) { LayoutInline* inlineCont = m_layoutBlock.inlineElementContinuation(); if (inlineCont && inlineCont->style()->hasOutline() && inlineCont->style()->visibility() == VISIBLE) { LayoutInline* inlineLayoutObject = toLayoutInline(inlineCont->node()->layoutObject()); LayoutBlock* cb = m_layoutBlock.containingBlock(); bool inlineEnclosedInSelfPaintingLayer = false; for (LayoutBoxModelObject* box = inlineLayoutObject; box != cb; box = box->parent()->enclosingBoxModelObject()) { if (box->hasSelfPaintingLayer()) { inlineEnclosedInSelfPaintingLayer = true; break; } } // Do not add continuations for outline painting by our containing block if we are a relative positioned // anonymous block (i.e. have our own layer), paint them straightaway instead. This is because a block depends on layoutObjects in its continuation table being // in the same layer. if (!inlineEnclosedInSelfPaintingLayer && !m_layoutBlock.hasLayer()) { cb->addContinuationWithOutline(inlineLayoutObject); } else if (!inlineLayoutObject->firstLineBox() || (!inlineEnclosedInSelfPaintingLayer && m_layoutBlock.hasLayer())) { // The outline might be painted multiple times if multiple blocks have the same inline element continuation, and the inline has a self-painting layer. ScopeRecorder scopeRecorder(*info.context); InlinePainter(*inlineLayoutObject).paintOutline(info, paintOffset - m_layoutBlock.locationOffset() + inlineLayoutObject->containingBlock()->location()); } } ContinuationOutlineTableMap* table = continuationOutlineTable(); if (table->isEmpty()) return; OwnPtr<ListHashSet<LayoutInline*>> continuations = table->take(&m_layoutBlock); if (!continuations) return; LayoutPoint accumulatedPaintOffset = paintOffset; // Paint each continuation outline. ListHashSet<LayoutInline*>::iterator end = continuations->end(); for (ListHashSet<LayoutInline*>::iterator it = continuations->begin(); it != end; ++it) { // Need to add in the coordinates of the intervening blocks. LayoutInline* flow = *it; LayoutBlock* block = flow->containingBlock(); for ( ; block && block != &m_layoutBlock; block = block->containingBlock()) accumulatedPaintOffset.moveBy(block->location()); ASSERT(block); InlinePainter(*flow).paintOutline(info, accumulatedPaintOffset); } }
void LineBoxListPainter::paint(RenderBoxModelObject* renderer, PaintInfo& paintInfo, const LayoutPoint& paintOffset) const { // Only paint during the foreground/selection phases. if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip && paintInfo.phase != PaintPhaseMask) return; ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could paint like this is if it has a layer. // If we have no lines then we have no work to do. if (!m_renderLineBoxList.firstLineBox()) return; if (!m_renderLineBoxList.anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset)) return; PaintInfo info(paintInfo); ListHashSet<RenderInline*> outlineObjects; info.setOutlineObjects(&outlineObjects); // See if our root lines intersect with the dirty rect. If so, then we paint // them. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = m_renderLineBoxList.firstLineBox(); curr; curr = curr->nextLineBox()) { if (m_renderLineBoxList.lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) { RootInlineBox& root = curr->root(); curr->paint(info, paintOffset, root.lineTop(), root.lineBottom()); } } if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) { ListHashSet<RenderInline*>::iterator end = info.outlineObjects()->end(); for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects()->begin(); it != end; ++it) { RenderInline* flow = *it; InlinePainter(*flow).paintOutline(info, paintOffset); } info.outlineObjects()->clear(); } }