void SVGImagePainter::paint(PaintInfo& paintInfo) { ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage); if (paintInfo.phase != PaintPhaseForeground || m_renderSVGImage.style()->visibility() == HIDDEN || !m_renderSVGImage.imageResource()->hasImage()) return; FloatRect boundingBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates(); if (!SVGRenderSupport::paintInfoIntersectsPaintInvalidationRect(boundingBox, m_renderSVGImage.localToParentTransform(), paintInfo)) return; PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(*childPaintInfo.context, false); childPaintInfo.applyTransform(m_renderSVGImage.localToParentTransform(), &stateSaver); if (!m_renderSVGImage.objectBoundingBox().isEmpty()) { // SVGRenderingContext may taint the state - make sure we're always saving. stateSaver.saveIfNeeded(); SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo); if (renderingContext.isRenderingPrepared()) { if (m_renderSVGImage.style()->svgStyle().bufferedRendering() == BR_STATIC && renderingContext.bufferForeground(m_renderSVGImage.bufferedForeground())) return; paintForeground(m_renderSVGImage, childPaintInfo); } } if (m_renderSVGImage.style()->outlineWidth()) ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(boundingBox)); }
void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && !paintInfo.context->paintController().skippingCache()) { if (m_layoutInline.paintOffsetChanged(paintOffset)) { paintInfo.context->paintController().invalidatePaintOffset(m_layoutInline); LineBoxListPainter(*m_layoutInline.lineBoxes()).invalidateLineBoxPaintOffsets(paintInfo); } // Set previousPaintOffset here in case that m_layoutInline paints nothing and no // LayoutObjectDrawingRecorder updates its previousPaintOffset. // TODO(wangxianzhu): Integrate paint offset checking into new paint invalidation. m_layoutInline.mutableForPainting().setPreviousPaintOffset(paintOffset); } // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872), // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase. if (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffset); if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseChildOutlines) { ObjectPainter painter(m_layoutInline); if (paintInfo.phase != PaintPhaseSelfOutline) painter.paintInlineChildrenOutlines(paintInfo, paintOffset); if (paintInfo.phase != PaintPhaseChildOutlines && !m_layoutInline.isElementContinuation()) painter.paintOutline(paintInfo, paintOffset); return; } LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(m_layoutInline, paintInfo, paintOffset); }
void BlockFlowPainter::paintFloats(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!m_layoutBlockFlow.floatingObjects()) return; ASSERT(paintInfo.phase == PaintPhaseFloat); PaintInfo floatPaintInfo(paintInfo); floatPaintInfo.phase = PaintPhaseForeground; for (const auto& floatingObject : m_layoutBlockFlow.floatingObjects()->set()) { if (!floatingObject->shouldPaint()) continue; const LayoutBox* floatingLayoutObject = floatingObject->layoutObject(); if (floatingLayoutObject->hasSelfPaintingLayer()) continue; // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make this much cleaner. LayoutPoint childPoint = m_layoutBlockFlow.flipFloatForWritingModeForChild( *floatingObject, LayoutPoint(paintOffset.x() + m_layoutBlockFlow.xPositionForFloatIncludingMargin(*floatingObject) - floatingLayoutObject->location().x(), paintOffset.y() + m_layoutBlockFlow.yPositionForFloatIncludingMargin(*floatingObject) - floatingLayoutObject->location().y())); ObjectPainter(*floatingLayoutObject).paintAsPseudoStackingContext(floatPaintInfo, childPoint); } }
void SVGImagePainter::paint(const PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground || m_layoutSVGImage.style()->visibility() == HIDDEN || !m_layoutSVGImage.imageResource()->hasImage()) return; FloatRect boundingBox = m_layoutSVGImage.paintInvalidationRectInLocalCoordinates(); if (!paintInfo.cullRect().intersectsCullRect(m_layoutSVGImage.localToParentTransform(), boundingBox)) return; PaintInfo paintInfoBeforeFiltering(paintInfo); // Images cannot have children so do not call updateCullRect. TransformRecorder transformRecorder(paintInfoBeforeFiltering.context, m_layoutSVGImage, m_layoutSVGImage.localToParentTransform()); { SVGPaintContext paintContext(m_layoutSVGImage, paintInfoBeforeFiltering); if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase, LayoutPoint())) { LayoutObjectDrawingRecorder recorder(paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase, boundingBox, LayoutPoint()); paintForeground(paintContext.paintInfo()); } } if (m_layoutSVGImage.style()->outlineWidth()) { PaintInfo outlinePaintInfo(paintInfoBeforeFiltering); outlinePaintInfo.phase = PaintPhaseSelfOutline; ObjectPainter(m_layoutSVGImage).paintOutline(outlinePaintInfo, LayoutPoint(boundingBox.location())); } }
void BlockFlowPainter::paintFloats(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!m_layoutBlockFlow.floatingObjects()) return; DCHECK(paintInfo.phase == PaintPhaseFloat || paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip); PaintInfo floatPaintInfo(paintInfo); if (paintInfo.phase == PaintPhaseFloat) floatPaintInfo.phase = PaintPhaseForeground; for (const auto& floatingObject : m_layoutBlockFlow.floatingObjects()->set()) { if (!floatingObject->shouldPaint()) continue; const LayoutBox* floatingLayoutObject = floatingObject->layoutObject(); // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make // this much cleaner. LayoutPoint childPoint = m_layoutBlockFlow.flipFloatForWritingModeForChild( *floatingObject, LayoutPoint(paintOffset.x() + m_layoutBlockFlow.xPositionForFloatIncludingMargin( *floatingObject) - floatingLayoutObject->location().x(), paintOffset.y() + m_layoutBlockFlow.yPositionForFloatIncludingMargin( *floatingObject) - floatingLayoutObject->location().y())); ObjectPainter(*floatingLayoutObject) .paintAllPhasesAtomically(floatPaintInfo, childPoint); } }
void TableSectionPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_layoutTableSection); ASSERT(!m_layoutTableSection.needsLayout()); // avoid crashing on bugs that cause us to paint with dirty layout if (m_layoutTableSection.needsLayout()) return; unsigned totalRows = m_layoutTableSection.numRows(); unsigned totalCols = m_layoutTableSection.table()->columns().size(); if (!totalRows || !totalCols) return; LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableSection.location(); { BoxClipper boxClipper(m_layoutTableSection, paintInfo, adjustedPaintOffset, ForceContentsClip); paintObject(paintInfo, adjustedPaintOffset); } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && m_layoutTableSection.style()->visibility() == VISIBLE) { LayoutRect visualOverflowRect(m_layoutTableSection.visualOverflowRect()); visualOverflowRect.moveBy(adjustedPaintOffset); ObjectPainter(m_layoutTableSection).paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, m_layoutTableSection.size()), visualOverflowRect); } }
void BlockPainter::paintInlineBox(const InlineBox& inlineBox, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; // Text clips are painted only for the direct inline children of the object // that has a text clip style on it, not block children. DCHECK(paintInfo.phase != PaintPhaseTextClip); LayoutPoint childPoint = paintOffset; if (inlineBox.parent() ->getLineLayoutItem() .style() ->isFlippedBlocksWritingMode()) { // Faster than calling containingBlock(). childPoint = LineLayoutAPIShim::layoutObjectFrom(inlineBox.getLineLayoutItem()) ->containingBlock() ->flipForWritingModeForChild( toLayoutBox(LineLayoutAPIShim::layoutObjectFrom( inlineBox.getLineLayoutItem())), childPoint); } ObjectPainter( *LineLayoutAPIShim::constLayoutObjectFrom(inlineBox.getLineLayoutItem())) .paintAllPhasesAtomically(paintInfo, childPoint); }
static void addPDFURLRectsForInlineChildrenRecursively(const LayoutObject& layoutObject, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { for (LayoutObject* child = layoutObject.slowFirstChild(); child; child = child->nextSibling()) { if (!child->isLayoutInline() || toLayoutBoxModelObject(child)->hasSelfPaintingLayer()) continue; ObjectPainter(*child).addPDFURLRectIfNeeded(paintInfo, paintOffset); addPDFURLRectsForInlineChildrenRecursively(*child, paintInfo, paintOffset); } }
void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872), // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase. if (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffset); LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(&m_layoutInline, paintInfo, paintOffset); }
void BlockPainter::paintAllChildPhasesAtomically( const LayoutBox& child, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint childPoint = m_layoutBlock.flipForWritingModeForChild(&child, paintOffset); if (!child.hasSelfPaintingLayer() && !child.isFloating()) ObjectPainter(child).paintAllPhasesAtomically(paintInfo, childPoint); }
void InlinePainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { const ComputedStyle& styleToUse = m_layoutInline.styleRef(); if (!styleToUse.hasOutline()) return; if (styleToUse.outlineStyleIsAuto()) { if (!LayoutTheme::theme().shouldDrawDefaultFocusRing(&m_layoutInline)) return; if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutInline, paintInfo.phase)) return; Vector<LayoutRect> focusRingRects; m_layoutInline.addOutlineRects(focusRingRects, paintOffset); LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutInline, paintInfo.phase, outlinePaintRect(focusRingRects, LayoutPoint())); // Only paint the focus ring by hand if the theme isn't able to draw the focus ring. ObjectPainter(m_layoutInline).paintFocusRing(paintInfo, styleToUse, focusRingRects); return; } if (styleToUse.outlineStyle() == BNONE) return; GraphicsContext* graphicsContext = paintInfo.context; if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*graphicsContext, m_layoutInline, paintInfo.phase)) return; Vector<LayoutRect> rects; rects.append(LayoutRect()); for (InlineFlowBox* curr = m_layoutInline.firstLineBox(); curr; curr = curr->nextLineBox()) { RootInlineBox& root = curr->root(); LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop()); LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom()); rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top)); } rects.append(LayoutRect()); Color outlineColor = m_layoutInline.resolveColor(styleToUse, CSSPropertyOutlineColor); bool useTransparencyLayer = outlineColor.hasAlpha(); LayoutObjectDrawingRecorder recorder(*graphicsContext, m_layoutInline, paintInfo.phase, outlinePaintRect(rects, paintOffset)); if (useTransparencyLayer) { graphicsContext->beginLayer(static_cast<float>(outlineColor.alpha()) / 255); outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue()); } for (unsigned i = 1; i < rects.size() - 1; i++) paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor); if (useTransparencyLayer) graphicsContext->endLayer(); }
void BlockPainter::paintInlineBox(const InlineBox& inlineBox, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!paintInfo.shouldPaintWithinRoot(&inlineBox.layoutObject()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) return; LayoutPoint childPoint = paintOffset; if (inlineBox.parent()->lineLayoutItem().style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock(). childPoint = inlineBox.layoutObject().containingBlock()->flipForWritingModeForChild(&toLayoutBox(inlineBox.layoutObject()), childPoint); ObjectPainter(inlineBox.layoutObject()).paintAsPseudoStackingContext(paintInfo, childPoint); }
void PartPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!m_layoutPart.shouldPaint(paintInfo, paintOffset)) return; LayoutPoint adjustedPaintOffset = paintOffset + m_layoutPart.location(); LayoutRect borderRect(adjustedPaintOffset, m_layoutPart.size()); if (m_layoutPart.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) BoxPainter(m_layoutPart).paintBoxDecorationBackground(paintInfo, adjustedPaintOffset); if (paintInfo.phase == PaintPhaseMask) { BoxPainter(m_layoutPart).paintMask(paintInfo, adjustedPaintOffset); return; } if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && m_layoutPart.style()->hasOutline()) ObjectPainter(m_layoutPart).paintOutline(paintInfo, adjustedPaintOffset); if (paintInfo.phase != PaintPhaseForeground) return; { Optional<RoundedInnerRectClipper> clipper; if (m_layoutPart.style()->hasBorderRadius()) { if (borderRect.isEmpty()) return; FloatRoundedRect roundedInnerRect = m_layoutPart.style()->getRoundedInnerBorderFor(borderRect, LayoutRectOutsets( -(m_layoutPart.paddingTop() + m_layoutPart.borderTop()), -(m_layoutPart.paddingRight() + m_layoutPart.borderRight()), -(m_layoutPart.paddingBottom() + m_layoutPart.borderBottom()), -(m_layoutPart.paddingLeft() + m_layoutPart.borderLeft())), true, true); clipper.emplace(m_layoutPart, paintInfo, borderRect, roundedInnerRect, ApplyToDisplayList); } if (m_layoutPart.widget()) m_layoutPart.paintContents(paintInfo, paintOffset); } // Paint a partially transparent wash over selected widgets. if (isSelected() && !paintInfo.isPrinting() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutPart, paintInfo.phase, adjustedPaintOffset)) { LayoutRect rect = m_layoutPart.localSelectionRect(); rect.moveBy(adjustedPaintOffset); IntRect selectionRect = pixelSnappedIntRect(rect); LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutPart, paintInfo.phase, selectionRect, adjustedPaintOffset); paintInfo.context->fillRect(selectionRect, m_layoutPart.selectionBackgroundColor()); } if (m_layoutPart.canResize()) ScrollableAreaPainter(*m_layoutPart.layer()->scrollableArea()).paintResizer(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.cullRect()); }
void TablePainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { PaintPhase paintPhase = paintInfo.phase; if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && m_layoutTable.hasBoxDecorationBackground() && m_layoutTable.style()->visibility() == VISIBLE) paintBoxDecorationBackground(paintInfo, paintOffset); if (paintPhase == PaintPhaseMask) { paintMask(paintInfo, paintOffset); return; } // We're done. We don't bother painting any children. if (paintPhase == PaintPhaseBlockBackground) return; // We don't paint our own background, but we do let the kids paint their backgrounds. if (paintPhase == PaintPhaseChildBlockBackgrounds) paintPhase = PaintPhaseChildBlockBackground; PaintInfo info(paintInfo); info.phase = paintPhase; info.updatePaintingRootForChildren(&m_layoutTable); for (LayoutObject* child = m_layoutTable.firstChild(); child; child = child->nextSibling()) { if (child->isBox() && !toLayoutBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) { LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild(toLayoutBox(child), paintOffset); child->paint(info, childPoint); } } if (m_layoutTable.collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && m_layoutTable.style()->visibility() == VISIBLE) { // Using our cached sorted styles, we then do individual passes, // painting each style of border from lowest precedence to highest precedence. info.phase = PaintPhaseCollapsedTableBorders; LayoutTable::CollapsedBorderValues collapsedBorders = m_layoutTable.collapsedBorders(); size_t count = collapsedBorders.size(); for (size_t i = 0; i < count; ++i) { // FIXME: pass this value into children rather than storing temporarily on the LayoutTable object. m_layoutTable.setCurrentBorderValue(&collapsedBorders[i]); for (LayoutTableSection* section = m_layoutTable.bottomSection(); section; section = m_layoutTable.sectionAbove(section)) { LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild(section, paintOffset); section->paint(info, childPoint); } } m_layoutTable.setCurrentBorderValue(0); } // Paint outline. if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutTable.style()->hasOutline() && m_layoutTable.style()->visibility() == VISIBLE) { LayoutRect overflowRect(m_layoutTable.visualOverflowRect()); overflowRect.moveBy(paintOffset); ObjectPainter(m_layoutTable).paintOutline(paintInfo, LayoutRect(paintOffset, m_layoutTable.size()), overflowRect); } }
void InlinePainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { RenderStyle* styleToUse = m_renderInline.style(); if (!styleToUse->hasOutline()) return; LayoutRect bounds; if (RuntimeEnabledFeatures::slimmingPaintEnabled()) { // FIXME: Use tighter bounds. RenderBlock* cb = m_renderInline.containingBlock(); bounds = cb->visualOverflowRect(); bounds.moveBy(paintOffset); } RenderDrawingRecorder recorder(paintInfo.context, m_renderInline, paintInfo.phase, bounds); if (recorder.canUseCachedDrawing()) return; if (styleToUse->outlineStyleIsAuto()) { if (RenderTheme::theme().shouldDrawDefaultFocusRing(&m_renderInline)) { // Only paint the focus ring by hand if the theme isn't able to draw the focus ring. ObjectPainter(m_renderInline).paintFocusRing(paintInfo, paintOffset, styleToUse); } return; } if (styleToUse->outlineStyle() == BNONE) return; Vector<LayoutRect> rects; rects.append(LayoutRect()); for (InlineFlowBox* curr = m_renderInline.firstLineBox(); curr; curr = curr->nextLineBox()) { RootInlineBox& root = curr->root(); LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop()); LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom()); rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top)); } rects.append(LayoutRect()); Color outlineColor = m_renderInline.resolveColor(styleToUse, CSSPropertyOutlineColor); bool useTransparencyLayer = outlineColor.hasAlpha(); GraphicsContext* graphicsContext = paintInfo.context; if (useTransparencyLayer) { graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255); outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue()); } for (unsigned i = 1; i < rects.size() - 1; i++) paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor); if (useTransparencyLayer) graphicsContext->endLayer(); }
void TablePainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { PaintPhase paintPhase = paintInfo.phase; if (shouldPaintSelfBlockBackground(paintPhase)) { paintBoxDecorationBackground(paintInfo, paintOffset); if (paintPhase == PaintPhaseSelfBlockBackgroundOnly) return; } if (paintPhase == PaintPhaseMask) { paintMask(paintInfo, paintOffset); return; } if (paintPhase != PaintPhaseSelfOutlineOnly) { PaintInfo paintInfoForDescendants = paintInfo.forDescendants(); for (LayoutObject* child = m_layoutTable.firstChild(); child; child = child->nextSibling()) { if (child->isBox() && !toLayoutBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) { LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild( toLayoutBox(child), paintOffset); child->paint(paintInfoForDescendants, childPoint); } } if (m_layoutTable.collapseBorders() && shouldPaintDescendantBlockBackgrounds(paintPhase) && m_layoutTable.style()->visibility() == EVisibility::Visible) { // Using our cached sorted styles, we then do individual passes, // painting each style of border from lowest precedence to highest // precedence. LayoutTable::CollapsedBorderValues collapsedBorders = m_layoutTable.collapsedBorders(); size_t count = collapsedBorders.size(); for (size_t i = 0; i < count; ++i) { for (LayoutTableSection* section = m_layoutTable.bottomSection(); section; section = m_layoutTable.sectionAbove(section)) { LayoutPoint childPoint = m_layoutTable.flipForWritingModeForChild(section, paintOffset); TableSectionPainter(*section).paintCollapsedBorders( paintInfoForDescendants, childPoint, collapsedBorders[i]); } } } } if (shouldPaintSelfOutline(paintPhase)) ObjectPainter(m_layoutTable).paintOutline(paintInfo, paintOffset); }
void SVGInlineFlowBoxPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection); { SVGPaintContext paintContext(m_svgInlineFlowBox.layoutObject(), paintInfo); if (paintContext.applyClipMaskAndFilterIfNecessary()) { for (InlineBox* child = m_svgInlineFlowBox.firstChild(); child; child = child->nextOnLine()) child->paint(paintContext.paintInfo(), paintOffset, 0, 0); } } if (m_svgInlineFlowBox.layoutObject().styleRef().hasOutline()) { PaintInfo outlinePaintInfo(paintInfo); outlinePaintInfo.phase = PaintPhaseSelfOutline; ObjectPainter(m_svgInlineFlowBox.layoutObject()).paintOutline(outlinePaintInfo, paintOffset); } }
void InlinePainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872), // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase. if (paintInfo.phase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutInline).addPDFURLRectIfNeeded(paintInfo, paintOffset); if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseChildOutlines) { ObjectPainter painter(m_layoutInline); if (paintInfo.phase != PaintPhaseSelfOutline) painter.paintInlineChildrenOutlines(paintInfo, paintOffset); if (paintInfo.phase != PaintPhaseChildOutlines && !m_layoutInline.isElementContinuation()) painter.paintOutline(paintInfo, paintOffset); return; } LineBoxListPainter(*m_layoutInline.lineBoxes()).paint(&m_layoutInline, paintInfo, paintOffset); }
void SVGImagePainter::paint(const PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground || m_layoutSVGImage.style()->visibility() == HIDDEN || !m_layoutSVGImage.imageResource()->hasImage()) return; FloatRect boundingBox = m_layoutSVGImage.paintInvalidationRectInLocalCoordinates(); if (!paintInfo.intersectsCullRect(m_layoutSVGImage.localToParentTransform(), boundingBox)) return; PaintInfo paintInfoBeforeFiltering(paintInfo); // Images cannot have children so do not call updateCullRectForSVGTransform. TransformRecorder transformRecorder(*paintInfoBeforeFiltering.context, m_layoutSVGImage, m_layoutSVGImage.localToParentTransform()); { SVGPaintContext paintContext(m_layoutSVGImage, paintInfoBeforeFiltering); if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase)) { LayoutObjectDrawingRecorder recorder(*paintContext.paintInfo().context, m_layoutSVGImage, paintContext.paintInfo().phase, boundingBox); // There's no need to cache a buffered SkPicture with slimming // paint because it's automatically done in the display list. if (m_layoutSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC || RuntimeEnabledFeatures::slimmingPaintEnabled()) { paintForeground(paintContext.paintInfo()); } else { RefPtr<const SkPicture>& bufferedForeground = m_layoutSVGImage.bufferedForeground(); if (!bufferedForeground) { paintContext.paintInfo().context->beginRecording(m_layoutSVGImage.objectBoundingBox()); paintForeground(paintContext.paintInfo()); bufferedForeground = paintContext.paintInfo().context->endRecording(); } paintContext.paintInfo().context->drawPicture(bufferedForeground.get()); } } } if (m_layoutSVGImage.style()->outlineWidth()) { PaintInfo outlinePaintInfo(paintInfoBeforeFiltering); outlinePaintInfo.phase = PaintPhaseSelfOutline; LayoutRect layoutBoundingBox(boundingBox); LayoutRect visualOverflowRect = ObjectPainter::outlineBounds(layoutBoundingBox, m_layoutSVGImage.styleRef()); ObjectPainter(m_layoutSVGImage).paintOutline(outlinePaintInfo, layoutBoundingBox, visualOverflowRect); } }
void BlockFlowPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // Avoid painting descendants of the root element when stylesheets haven't // loaded. This eliminates FOUC. It's ok not to draw, because later on, when // all the stylesheets do load, styleResolverMayHaveChanged() on Document will // trigger a full paint invalidation. if (m_layoutBlockFlow.document().didLayoutWithPendingStylesheets() && !m_layoutBlockFlow.isLayoutView()) return; if (!m_layoutBlockFlow.childrenInline()) { BlockPainter(m_layoutBlockFlow).paintContents(paintInfo, paintOffset); return; } if (shouldPaintDescendantOutlines(paintInfo.phase)) ObjectPainter(m_layoutBlockFlow) .paintInlineChildrenOutlines(paintInfo, paintOffset); else LineBoxListPainter(m_layoutBlockFlow.lineBoxes()) .paint(m_layoutBlockFlow, paintInfo, paintOffset); }
void SVGForeignObjectPainter::paint(const PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; PaintInfo paintInfoBeforeFiltering(paintInfo); paintInfoBeforeFiltering.updateCullRect( m_layoutSVGForeignObject.localSVGTransform()); SVGTransformContext transformContext( paintInfoBeforeFiltering.context, m_layoutSVGForeignObject, m_layoutSVGForeignObject.localSVGTransform()); Optional<FloatClipRecorder> clipRecorder; if (SVGLayoutSupport::isOverflowHidden(&m_layoutSVGForeignObject)) clipRecorder.emplace(paintInfoBeforeFiltering.context, m_layoutSVGForeignObject, paintInfoBeforeFiltering.phase, m_layoutSVGForeignObject.viewportRect()); SVGPaintContext paintContext(m_layoutSVGForeignObject, paintInfoBeforeFiltering); bool continueRendering = true; if (paintContext.paintInfo().phase == PaintPhaseForeground) continueRendering = paintContext.applyClipMaskAndFilterIfNecessary(); if (continueRendering) { // Paint all phases of FO elements atomically as though the FO element // established its own stacking context. The delegate forwards calls to // paint() in LayoutObject::paintAllPhasesAtomically() to // BlockPainter::paint(), instead of m_layoutSVGForeignObject.paint() (which // would call this method again). BlockPainterDelegate delegate(m_layoutSVGForeignObject); ObjectPainter(delegate).paintAllPhasesAtomically(paintContext.paintInfo(), LayoutPoint()); } }
void SVGImagePainter::paint(const PaintInfo& paintInfo) { ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGImage); if (paintInfo.phase != PaintPhaseForeground || m_renderSVGImage.style()->visibility() == HIDDEN || !m_renderSVGImage.imageResource()->hasImage()) return; FloatRect boundingBox = m_renderSVGImage.paintInvalidationRectInLocalCoordinates(); PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(*childPaintInfo.context); TransformRecorder transformRecorder(*childPaintInfo.context, m_renderSVGImage.displayItemClient(), m_renderSVGImage.localToParentTransform()); SVGRenderingContext renderingContext(&m_renderSVGImage, childPaintInfo); if (renderingContext.isRenderingPrepared()) { RenderDrawingRecorder recorder(childPaintInfo.context, m_renderSVGImage, childPaintInfo.phase, boundingBox); if (!recorder.canUseCachedDrawing()) { if (m_renderSVGImage.style()->svgStyle().bufferedRendering() != BR_STATIC) { paintForeground(childPaintInfo); } else { RefPtr<const SkPicture>& bufferedForeground = m_renderSVGImage.bufferedForeground(); if (!bufferedForeground) { childPaintInfo.context->beginRecording(m_renderSVGImage.objectBoundingBox()); paintForeground(childPaintInfo); bufferedForeground = childPaintInfo.context->endRecording(); } childPaintInfo.context->drawPicture(bufferedForeground.get()); } } } if (m_renderSVGImage.style()->outlineWidth()) ObjectPainter(m_renderSVGImage).paintOutline(childPaintInfo, IntRect(boundingBox)); }
void BlockPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // Avoid painting descendants of the root element when stylesheets haven't loaded. This eliminates FOUC. // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document // will do a full paint invalidation. if (m_layoutBlock.document().didLayoutWithPendingStylesheets() && !m_layoutBlock.isLayoutView()) return; if (m_layoutBlock.childrenInline()) { if (paintInfo.phase == PaintPhaseDescendantOutlines) ObjectPainter(m_layoutBlock).paintInlineChildrenOutlines(paintInfo, paintOffset); else LineBoxListPainter(m_layoutBlock.lineBoxes()).paint(m_layoutBlock, paintInfo, paintOffset); } else { PaintPhase newPhase = (paintInfo.phase == PaintPhaseDescendantOutlines) ? PaintPhaseOutline : paintInfo.phase; newPhase = (newPhase == PaintPhaseDescendantBlockBackgrounds) ? PaintPhaseBlockBackground : newPhase; // We don't paint our own background, but we do let the kids paint their backgrounds. PaintInfo paintInfoForChild(paintInfo); paintInfoForChild.phase = newPhase; paintInfoForChild.updatePaintingRootForChildren(&m_layoutBlock); m_layoutBlock.paintChildren(paintInfoForChild, paintOffset); } }
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && m_layoutBlock.childrenInline() && !paintInfo.context.paintController().skippingCache()) { if (m_layoutBlock.paintOffsetChanged(paintOffset)) { LineBoxListPainter(m_layoutBlock.lineBoxes()).invalidateLineBoxPaintOffsets(paintInfo); paintInfo.context.paintController().invalidatePaintOffset(m_layoutBlock); } // Set previousPaintOffset here in case that m_layoutBlock paints nothing and no // LayoutObjectDrawingRecorder updates its previousPaintOffset. // TODO(wangxianzhu): Integrate paint offset checking into new paint invalidation. m_layoutBlock.mutableForPainting().setPreviousPaintOffset(paintOffset); } const PaintPhase paintPhase = paintInfo.phase; if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhaseBlockBackground) && m_layoutBlock.style()->visibility() == VISIBLE && m_layoutBlock.hasBoxDecorationBackground()) m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset); if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == VISIBLE) { m_layoutBlock.paintMask(paintInfo, paintOffset); return; } if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == VISIBLE) { BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset); return; } // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872), // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase. if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset); { Optional<ScrollRecorder> scrollRecorder; Optional<PaintInfo> scrolledPaintInfo; if (m_layoutBlock.hasOverflowClip()) { IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) { scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase, scrollOffset); scrolledPaintInfo.emplace(paintInfo); AffineTransform transform; transform.translate(-scrollOffset.width(), -scrollOffset.height()); scrolledPaintInfo->updateCullRect(transform); } } // We're done. We don't bother painting any children. if (paintPhase == PaintPhaseSelfBlockBackground || paintInfo.paintRootBackgroundOnly()) return; const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo; if (paintPhase != PaintPhaseSelfOutline) paintContents(contentsPaintInfo, paintOffset); if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting()) m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fill in gaps in selection on lines and between blocks. if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset); } if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() == VISIBLE) ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset); // If the caret's node's layout object's containing block is this block, and the paint action is PaintPhaseForeground, // then paint the caret. if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutBlock, DisplayItem::Caret, paintOffset)) { LayoutRect bounds = m_layoutBlock.visualOverflowRect(); bounds.moveBy(paintOffset); LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutBlock, DisplayItem::Caret, bounds, paintOffset); paintCarets(paintInfo, paintOffset); } }
void ReplacedPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (!m_layoutReplaced.shouldPaint(paintInfo, paintOffset)) return; LayoutPoint adjustedPaintOffset = paintOffset + m_layoutReplaced.location(); LayoutRect borderRect(adjustedPaintOffset, m_layoutReplaced.size()); if (m_layoutReplaced.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) m_layoutReplaced.paintBoxDecorationBackground(paintInfo, adjustedPaintOffset); if (paintInfo.phase == PaintPhaseMask) { m_layoutReplaced.paintMask(paintInfo, adjustedPaintOffset); return; } if (paintInfo.phase == PaintPhaseClippingMask && (!m_layoutReplaced.hasLayer() || !m_layoutReplaced.layer()->hasCompositedClippingMask())) return; if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) { if (m_layoutReplaced.styleRef().outlineWidth()) ObjectPainter(m_layoutReplaced).paintOutline(paintInfo, adjustedPaintOffset); return; } if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && !m_layoutReplaced.canHaveChildren() && paintInfo.phase != PaintPhaseClippingMask) return; if (!paintInfo.shouldPaintWithinRoot(&m_layoutReplaced)) return; if (paintInfo.phase == PaintPhaseSelection) if (m_layoutReplaced.selectionState() == SelectionNone) return; { Optional<RoundedInnerRectClipper> clipper; bool completelyClippedOut = false; if (m_layoutReplaced.style()->hasBorderRadius()) { if (borderRect.isEmpty()) { completelyClippedOut = true; } else if (shouldApplyViewportClip(m_layoutReplaced)) { // Push a clip if we have a border radius, since we want to round the foreground content that gets painted. FloatRoundedRect roundedInnerRect = m_layoutReplaced.style()->getRoundedInnerBorderFor(borderRect, LayoutRectOutsets( -(m_layoutReplaced.paddingTop() + m_layoutReplaced.borderTop()), -(m_layoutReplaced.paddingRight() + m_layoutReplaced.borderRight()), -(m_layoutReplaced.paddingBottom() + m_layoutReplaced.borderBottom()), -(m_layoutReplaced.paddingLeft() + m_layoutReplaced.borderLeft())), true, true); clipper.emplace(m_layoutReplaced, paintInfo, borderRect, roundedInnerRect, ApplyToDisplayList); } } if (!completelyClippedOut) { if (paintInfo.phase == PaintPhaseClippingMask) { BoxPainter(m_layoutReplaced).paintClippingMask(paintInfo, adjustedPaintOffset); } else { m_layoutReplaced.paintReplaced(paintInfo, adjustedPaintOffset); } } } // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of // surrounding content. bool drawSelectionTint = paintInfo.phase == PaintPhaseForeground && m_layoutReplaced.selectionState() != SelectionNone && !paintInfo.isPrinting(); if (drawSelectionTint && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutReplaced, DisplayItem::SelectionTint, adjustedPaintOffset)) { LayoutRect selectionPaintingRect = m_layoutReplaced.localSelectionRect(); selectionPaintingRect.moveBy(adjustedPaintOffset); IntRect selectionPaintingIntRect = pixelSnappedIntRect(selectionPaintingRect); LayoutObjectDrawingRecorder drawingRecorder(paintInfo.context, m_layoutReplaced, DisplayItem::SelectionTint, selectionPaintingIntRect, adjustedPaintOffset); paintInfo.context.fillRect(selectionPaintingIntRect, m_layoutReplaced.selectionBackgroundColor()); } }
void TableRowPainter::paintOutline(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { DCHECK(shouldPaintSelfOutline(paintInfo.phase)); LayoutPoint adjustedPaintOffset = paintOffset + m_layoutTableRow.location(); ObjectPainter(m_layoutTableRow).paintOutline(paintInfo, adjustedPaintOffset); }
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { const PaintPhase paintPhase = paintInfo.phase; if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && m_layoutBlock.style()->visibility() == VISIBLE && m_layoutBlock.hasBoxDecorationBackground()) m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset); if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == VISIBLE) { m_layoutBlock.paintMask(paintInfo, paintOffset); return; } if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == VISIBLE) { BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset); return; } // FIXME: When Skia supports annotation rect covering (https://code.google.com/p/skia/issues/detail?id=3872), // this rect may be covered by foreground and descendant drawings. Then we may need a dedicated paint phase. if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset); { Optional<ScrollRecorder> scrollRecorder; Optional<PaintInfo> scrolledPaintInfo; if (m_layoutBlock.hasOverflowClip()) { IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) { scrollRecorder.emplace(*paintInfo.context, m_layoutBlock, paintPhase, scrollOffset); scrolledPaintInfo.emplace(paintInfo); scrolledPaintInfo->rect.move(scrollOffset); } } // We're done. We don't bother painting any children. if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgroundOnly()) return; const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo; if (paintPhase != PaintPhaseSelfOutline) paintContents(contentsPaintInfo, paintOffset); if (paintPhase == PaintPhaseForeground && !paintInfo.isPrinting()) m_layoutBlock.paintSelection(contentsPaintInfo, paintOffset); // Fill in gaps in selection on lines and between blocks. if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) m_layoutBlock.paintFloats(contentsPaintInfo, paintOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip); } if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && m_layoutBlock.style()->hasOutline() && m_layoutBlock.style()->visibility() == VISIBLE) { // Don't paint focus ring for anonymous block continuation because the // inline element having outline-style:auto paints the whole focus ring. if (!m_layoutBlock.style()->outlineStyleIsAuto() || !m_layoutBlock.isAnonymousBlockContinuation()) ObjectPainter(m_layoutBlock).paintOutline(paintInfo, LayoutRect(paintOffset, m_layoutBlock.size()), visualOverflowRectWithPaintOffset(m_layoutBlock, paintOffset)); } if (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines) paintContinuationOutlines(paintInfo, paintOffset); // If the caret's node's layout object's containing block is this block, and the paint action is PaintPhaseForeground, // then paint the caret. if (paintPhase == PaintPhaseForeground && hasCaret() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutBlock, DisplayItem::Caret)) { LayoutObjectDrawingRecorder recorder(*paintInfo.context, m_layoutBlock, DisplayItem::Caret, visualOverflowRectWithPaintOffset(m_layoutBlock, paintOffset)); paintCarets(paintInfo, paintOffset); } }
void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { const PaintPhase paintPhase = paintInfo.phase; if (shouldPaintSelfBlockBackground(paintPhase)) { if (m_layoutBlock.style()->visibility() == EVisibility::Visible && m_layoutBlock.hasBoxDecorationBackground()) m_layoutBlock.paintBoxDecorationBackground(paintInfo, paintOffset); // We're done. We don't bother painting any children. if (paintPhase == PaintPhaseSelfBlockBackgroundOnly) return; } if (paintInfo.paintRootBackgroundOnly()) return; if (paintPhase == PaintPhaseMask && m_layoutBlock.style()->visibility() == EVisibility::Visible) { m_layoutBlock.paintMask(paintInfo, paintOffset); return; } if (paintPhase == PaintPhaseClippingMask && m_layoutBlock.style()->visibility() == EVisibility::Visible) { BoxPainter(m_layoutBlock).paintClippingMask(paintInfo, paintOffset); return; } if (paintPhase == PaintPhaseForeground && paintInfo.isPrinting()) ObjectPainter(m_layoutBlock).addPDFURLRectIfNeeded(paintInfo, paintOffset); if (paintPhase != PaintPhaseSelfOutlineOnly) { Optional<ScopedPaintChunkProperties> m_scopedScrollProperty; Optional<ScrollRecorder> scrollRecorder; Optional<PaintInfo> scrolledPaintInfo; if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { const auto* objectProperties = m_layoutBlock.paintProperties(); if (auto* scroll = objectProperties ? objectProperties->scroll() : nullptr) { PaintChunkProperties properties(paintInfo.context.getPaintController() .currentPaintChunkProperties()); auto* scrollTranslation = objectProperties->scrollTranslation(); DCHECK(scrollTranslation); properties.transform = scrollTranslation; properties.scroll = scroll; m_scopedScrollProperty.emplace( paintInfo.context.getPaintController(), m_layoutBlock, DisplayItem::paintPhaseToDrawingType(paintPhase), properties); scrolledPaintInfo.emplace(paintInfo); scrolledPaintInfo->updateCullRect( scrollTranslation->matrix().toAffineTransform()); } } else if (m_layoutBlock.hasOverflowClip()) { IntSize scrollOffset = m_layoutBlock.scrolledContentOffset(); if (m_layoutBlock.layer()->scrollsOverflow() || !scrollOffset.isZero()) { scrollRecorder.emplace(paintInfo.context, m_layoutBlock, paintPhase, scrollOffset); scrolledPaintInfo.emplace(paintInfo); AffineTransform transform; transform.translate(-scrollOffset.width(), -scrollOffset.height()); scrolledPaintInfo->updateCullRect(transform); } } const PaintInfo& contentsPaintInfo = scrolledPaintInfo ? *scrolledPaintInfo : paintInfo; if (m_layoutBlock.isLayoutBlockFlow()) { BlockFlowPainter blockFlowPainter(toLayoutBlockFlow(m_layoutBlock)); blockFlowPainter.paintContents(contentsPaintInfo, paintOffset); if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) blockFlowPainter.paintFloats(contentsPaintInfo, paintOffset); } else { paintContents(contentsPaintInfo, paintOffset); } } if (shouldPaintSelfOutline(paintPhase)) ObjectPainter(m_layoutBlock).paintOutline(paintInfo, paintOffset); // If the caret's node's layout object's containing block is this block, and // the paint action is PaintPhaseForeground, then paint the caret. if (paintPhase == PaintPhaseForeground && m_layoutBlock.hasCaret()) paintCarets(paintInfo, paintOffset); }
void SVGShapePainter::paint(const PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground || m_layoutSVGShape.style()->visibility() == HIDDEN || m_layoutSVGShape.isShapeEmpty()) return; FloatRect boundingBox = m_layoutSVGShape.paintInvalidationRectInLocalCoordinates(); if (!paintInfo.cullRect().intersectsCullRect(m_layoutSVGShape.localTransform(), boundingBox)) return; PaintInfo paintInfoBeforeFiltering(paintInfo); // Shapes cannot have children so do not call updateCullRect. TransformRecorder transformRecorder(paintInfoBeforeFiltering.context, m_layoutSVGShape, m_layoutSVGShape.localTransform()); { SVGPaintContext paintContext(m_layoutSVGShape, paintInfoBeforeFiltering); if (paintContext.applyClipMaskAndFilterIfNecessary() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintContext.paintInfo().context, m_layoutSVGShape, paintContext.paintInfo().phase, LayoutPoint())) { LayoutObjectDrawingRecorder recorder(paintContext.paintInfo().context, m_layoutSVGShape, paintContext.paintInfo().phase, boundingBox, LayoutPoint()); const SVGComputedStyle& svgStyle = m_layoutSVGShape.style()->svgStyle(); bool shouldAntiAlias = svgStyle.shapeRendering() != SR_CRISPEDGES; for (int i = 0; i < 3; i++) { switch (svgStyle.paintOrderType(i)) { case PT_FILL: { SkPaint fillPaint; if (!SVGPaintContext::paintForLayoutObject(paintContext.paintInfo(), m_layoutSVGShape.styleRef(), m_layoutSVGShape, ApplyToFillMode, fillPaint)) break; fillPaint.setAntiAlias(shouldAntiAlias); fillShape(paintContext.paintInfo().context, fillPaint, fillRuleFromStyle(paintContext.paintInfo(), svgStyle)); break; } case PT_STROKE: if (svgStyle.hasVisibleStroke()) { GraphicsContextStateSaver stateSaver(paintContext.paintInfo().context, false); AffineTransform nonScalingTransform; const AffineTransform* additionalPaintServerTransform = 0; if (m_layoutSVGShape.hasNonScalingStroke()) { nonScalingTransform = m_layoutSVGShape.nonScalingStrokeTransform(); if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver)) return; // Non-scaling stroke needs to reset the transform back to the host transform. additionalPaintServerTransform = &nonScalingTransform; } SkPaint strokePaint; if (!SVGPaintContext::paintForLayoutObject(paintContext.paintInfo(), m_layoutSVGShape.styleRef(), m_layoutSVGShape, ApplyToStrokeMode, strokePaint, additionalPaintServerTransform)) break; strokePaint.setAntiAlias(shouldAntiAlias); StrokeData strokeData; SVGLayoutSupport::applyStrokeStyleToStrokeData(strokeData, m_layoutSVGShape.styleRef(), m_layoutSVGShape, m_layoutSVGShape.dashScaleFactor()); strokeData.setupPaint(&strokePaint); strokeShape(paintContext.paintInfo().context, strokePaint); } break; case PT_MARKERS: paintMarkers(paintContext.paintInfo(), boundingBox); break; default: ASSERT_NOT_REACHED(); break; } } } } if (m_layoutSVGShape.style()->outlineWidth()) { PaintInfo outlinePaintInfo(paintInfoBeforeFiltering); outlinePaintInfo.phase = PaintPhaseSelfOutlineOnly; ObjectPainter(m_layoutSVGShape).paintOutline(outlinePaintInfo, LayoutPoint(boundingBox.location())); } }
void BlockPainter::paintChildAsPseudoStackingContext(const LayoutBox& child, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint childPoint = m_layoutBlock.flipForWritingModeForChild(&child, paintOffset); if (!child.hasSelfPaintingLayer() && !child.isFloating()) ObjectPainter(child).paintAsPseudoStackingContext(paintInfo, childPoint); }