bool SVGPaintContext::applyClipMaskAndFilterIfNecessary() { #if ENABLE(ASSERT) DCHECK(!m_applyClipMaskAndFilterIfNecessaryCalled); m_applyClipMaskAndFilterIfNecessaryCalled = true; #endif // When rendering clip paths as masks, only geometric operations should be // included so skip non-geometric operations such as compositing, masking, and // filtering. if (paintInfo().isRenderingClipPathAsMaskImage()) { DCHECK(!m_object.isSVGRoot()); applyClipIfNecessary(); return true; } bool isSVGRoot = m_object.isSVGRoot(); // Layer takes care of root opacity and blend mode. if (isSVGRoot) { DCHECK(!(m_object.isTransparent() || m_object.styleRef().hasBlendMode()) || m_object.hasLayer()); } else { applyCompositingIfNecessary(); } if (isSVGRoot) { DCHECK(!m_object.styleRef().clipPath() || m_object.hasLayer()); } else { applyClipIfNecessary(); } SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(&m_object); if (!applyMaskIfNecessary(resources)) return false; if (isSVGRoot) { DCHECK(!m_object.styleRef().hasFilter() || m_object.hasLayer()); } else if (!applyFilterIfNecessary(resources)) { return false; } if (!isIsolationInstalled() && SVGLayoutSupport::isIsolationRequired(&m_object)) { m_compositingRecorder = WTF::wrapUnique(new CompositingRecorder( paintInfo().context, m_object, SkBlendMode::kSrcOver, 1)); } return true; }
void CPictureViewerGui::paint() { liststart = (selected/listmaxshow)*listmaxshow; paintHead(); for (unsigned int count=0; count<listmaxshow; count++) { paintItem(count); } int ypos = y+ theight; int sb = fheight* listmaxshow; frameBuffer->paintBoxRel(x+ width- 15,ypos, 15, sb, COL_MENUCONTENT_PLUS_1); int sbc= ((playlist.size()- 1)/ listmaxshow)+ 1; int sbs= (selected/listmaxshow); if (sbc < 1) sbc = 1; frameBuffer->paintBoxRel(x+ width- 13, ypos+ 2+ sbs * (sb-4)/sbc, 11, (sb-4)/sbc, COL_MENUCONTENT_PLUS_3); paintFoot(); paintInfo(); visible = true; }
TEST_F(PaintInfoTest, intersectsHorizontalRange) { PaintInfo paintInfo(nullptr, IntRect(0, 0, 50, 100), PaintPhaseBlockBackground, GlobalPaintNormalPhase, PaintLayerNoFlag); EXPECT_TRUE(paintInfo.cullRect().intersectsHorizontalRange(0, 1)); EXPECT_FALSE(paintInfo.cullRect().intersectsHorizontalRange(50, 51)); }
bool SVGPaintContext::applyFilterIfNecessary(SVGResources* resources) { if (!resources) return !hasReferenceFilterOnly(m_object.styleRef()); LayoutSVGResourceFilter* filter = resources->filter(); if (!filter) return true; m_filterRecordingContext = WTF::wrapUnique(new SVGFilterRecordingContext(paintInfo().context)); m_filter = filter; GraphicsContext* filterContext = SVGFilterPainter(*filter).prepareEffect( m_object, *m_filterRecordingContext); if (!filterContext) return false; // Because the filter needs to cache its contents we replace the context // during filtering with the filter's context. m_filterPaintInfo = WTF::wrapUnique(new PaintInfo(*filterContext, m_paintInfo)); // Because we cache the filter contents and do not invalidate on paint // invalidation rect changes, we need to paint the entire filter region // so elements outside the initial paint (due to scrolling, etc) paint. m_filterPaintInfo->m_cullRect.m_rect = LayoutRect::infiniteIntRect(); return true; }
void SVGPaintContext::applyClipIfNecessary() { ClipPathOperation* clipPathOperation = m_object.styleRef().clipPath(); if (!clipPathOperation) return; m_clipPathClipper.emplace(paintInfo().context, *clipPathOperation, m_object, m_object.objectBoundingBox(), FloatPoint()); }
TEST_F(PaintInfoTest, intersectsCullRectWithLayoutRect) { PaintInfo paintInfo(nullptr, IntRect(0, 0, 50, 50), PaintPhaseBlockBackground, GlobalPaintNormalPhase, PaintLayerNoFlag); EXPECT_TRUE(paintInfo.cullRect().intersectsCullRect(LayoutRect(0, 0, 1, 1))); EXPECT_TRUE(paintInfo.cullRect().intersectsCullRect(LayoutRect(0.1, 0.1, 0.1, 0.1))); }
TEST_F(PaintInfoTest, intersectsCullRect) { PaintInfo paintInfo(m_context, IntRect(0, 0, 50, 50), PaintPhaseSelfBlockBackgroundOnly, GlobalPaintNormalPhase, PaintLayerNoFlag); EXPECT_TRUE(paintInfo.cullRect().intersectsCullRect(IntRect(0, 0, 1, 1))); EXPECT_FALSE(paintInfo.cullRect().intersectsCullRect(IntRect(51, 51, 1, 1))); }
void SVGPaintContext::applyCompositingIfNecessary() { DCHECK(!paintInfo().isRenderingClipPathAsMaskImage()); const ComputedStyle& style = m_object.styleRef(); float opacity = style.opacity(); WebBlendMode blendMode = style.hasBlendMode() && m_object.isBlendingAllowed() ? style.blendMode() : WebBlendModeNormal; if (opacity < 1 || blendMode != WebBlendModeNormal) { const FloatRect compositingBounds = m_object.visualRectInLocalSVGCoordinates(); m_compositingRecorder = WTF::wrapUnique(new CompositingRecorder( paintInfo().context, m_object, WebCoreCompositeToSkiaComposite(CompositeSourceOver, blendMode), opacity, &compositingBounds)); } }
bool SVGPaintContext::applyMaskIfNecessary(SVGResources* resources) { if (LayoutSVGResourceMasker* masker = resources ? resources->masker() : nullptr) { if (!SVGMaskPainter(*masker).prepareEffect(m_object, paintInfo().context)) return false; m_masker = masker; } return true; }
TEST_F(PaintInfoTest, intersectsCullRectWithTransform) { PaintInfo paintInfo(nullptr, IntRect(0, 0, 50, 50), PaintPhaseBlockBackground, GlobalPaintNormalPhase, PaintLayerNoFlag); AffineTransform transform; transform.translate(-2, -2); EXPECT_TRUE(paintInfo.cullRect().intersectsCullRect(transform, IntRect(51, 51, 1, 1))); EXPECT_FALSE(paintInfo.cullRect().intersectsCullRect(IntRect(52, 52, 1, 1))); }
TEST_F(PaintInfoTest, intersectsHorizontalRange) { PaintInfo paintInfo(m_context, IntRect(0, 0, 50, 100), PaintPhaseSelfBlockBackgroundOnly, GlobalPaintNormalPhase, PaintLayerNoFlag); EXPECT_TRUE(paintInfo.cullRect().intersectsHorizontalRange(LayoutUnit(), LayoutUnit(1))); EXPECT_FALSE(paintInfo.cullRect().intersectsHorizontalRange(LayoutUnit(50), LayoutUnit(51))); }
TEST_F(PaintInfoTest, updateCullRect) { PaintInfo paintInfo(m_context, IntRect(1, 1, 50, 50), PaintPhaseSelfBlockBackgroundOnly, GlobalPaintNormalPhase, PaintLayerNoFlag); AffineTransform transform; transform.translate(1, 1); paintInfo.updateCullRect(transform); EXPECT_TRUE(paintInfo.cullRect().intersectsCullRect(IntRect(0, 0, 1, 1))); EXPECT_FALSE(paintInfo.cullRect().intersectsCullRect(IntRect(51, 51, 1, 1))); }
void Element::paint(Canvas* canvas) { if (!renderer() || !renderer()->isBox()) return; RenderBox* box = toRenderBox(renderer()); GraphicsContext context(canvas->skCanvas()); // Very simplified painting to allow painting an arbitrary (layer-less) subtree. Vector<RenderBox*> layers; PaintInfo paintInfo(&context, box->absoluteBoundingBoxRect(), box); box->paint(paintInfo, LayoutPoint(), layers); // Note we're ignoring any layers encountered. }
SVGPaintContext::~SVGPaintContext() { if (m_filter) { DCHECK(SVGResourcesCache::cachedResourcesForLayoutObject(&m_object)); DCHECK(SVGResourcesCache::cachedResourcesForLayoutObject(&m_object) ->filter() == m_filter); DCHECK(m_filterRecordingContext); SVGFilterPainter(*m_filter).finishEffect(m_object, *m_filterRecordingContext); // Reset the paint info after the filter effect has been completed. m_filterPaintInfo = nullptr; } if (m_masker) { DCHECK(SVGResourcesCache::cachedResourcesForLayoutObject(&m_object)); DCHECK(SVGResourcesCache::cachedResourcesForLayoutObject(&m_object) ->masker() == m_masker); SVGMaskPainter(*m_masker).finishEffect(m_object, paintInfo().context); } }
void CPictureViewerGui::paint() { liststart = (selected/listmaxshow)*listmaxshow; paintHead(); for (unsigned int count=0; count<listmaxshow; count++) { paintItem(count); } //scrollbar int total_pages; int current_page; getScrollBarData(&total_pages, ¤t_page, playlist.size(), listmaxshow, selected); paintScrollBar(x + width - SCROLLBAR_WIDTH, y + header_height, SCROLLBAR_WIDTH, item_height*listmaxshow, total_pages, current_page, CC_SHADOW_ON); paintFoot(); paintInfo(); visible = true; }
void PaintLayerPainter::paintFragmentWithPhase(PaintPhase phase, const PaintLayerFragment& fragment, GraphicsContext& context, const ClipRect& clipRect, const PaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, ClipState clipState) { ASSERT(m_paintLayer.isSelfPaintingLayer()); Optional<LayerClipRecorder> clipRecorder; if (clipState != HasClipped && paintingInfo.clipToDirtyRect && needsToClip(paintingInfo, clipRect)) { DisplayItem::Type clipType = DisplayItem::paintPhaseToClipLayerFragmentType(phase); LayerClipRecorder::BorderRadiusClippingRule clippingRule; switch (phase) { case PaintPhaseSelfBlockBackgroundOnly: // Background painting will handle clipping to self. case PaintPhaseSelfOutlineOnly: case PaintPhaseMask: // Mask painting will handle clipping to self. clippingRule = LayerClipRecorder::DoNotIncludeSelfForBorderRadius; break; default: clippingRule = LayerClipRecorder::IncludeSelfForBorderRadius; break; } clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, clipRect, &paintingInfo, fragment.paginationOffset, paintFlags, clippingRule); } LayoutRect newCullRect(clipRect.rect()); Optional<ScrollRecorder> scrollRecorder; LayoutPoint paintOffset = toPoint(fragment.layerBounds.location() - m_paintLayer.layoutBoxLocation()); if (!paintingInfo.scrollOffsetAccumulation.isZero()) { // As a descendant of the root layer, m_paintLayer's painting is not controlled by the ScrollRecorders // created by BlockPainter of the ancestor layers up to the root layer, so we need to issue ScrollRecorder // for this layer seperately, with the scroll offset accumulated from the root layer to the parent of this // layer, to get the same result as ScrollRecorder in BlockPainter. paintOffset += paintingInfo.scrollOffsetAccumulation; newCullRect.move(paintingInfo.scrollOffsetAccumulation); scrollRecorder.emplace(context, *m_paintLayer.layoutObject(), phase, paintingInfo.scrollOffsetAccumulation); } PaintInfo paintInfo(context, pixelSnappedIntRect(newCullRect), phase, paintingInfo.globalPaintFlags(), paintFlags, paintingInfo.rootLayer->layoutObject()); m_paintLayer.layoutObject()->paint(paintInfo, paintOffset); }
void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, int tx, int ty, const IntRect& rect) { // Make sure our dimensions match the rect. setLocation(rect.x() - tx, rect.y() - ty); setWidth(rect.width()); setHeight(rect.height()); if (graphicsContext->paintingDisabled()) return; // Now do the paint. RenderObject::PaintInfo paintInfo(graphicsContext, rect, PaintPhaseBlockBackground, false, 0, 0); paint(paintInfo, tx, ty); paintInfo.phase = PaintPhaseChildBlockBackgrounds; paint(paintInfo, tx, ty); paintInfo.phase = PaintPhaseFloat; paint(paintInfo, tx, ty); paintInfo.phase = PaintPhaseForeground; paint(paintInfo, tx, ty); paintInfo.phase = PaintPhaseOutline; paint(paintInfo, tx, ty); }
void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect) { // Make sure our dimensions match the rect. setLocation(rect.location() - toSize(paintOffset)); setWidth(rect.width()); setHeight(rect.height()); if (graphicsContext->paintingDisabled()) return; // Now do the paint. PaintInfo paintInfo(graphicsContext, rect, PaintPhaseBlockBackground, false, 0, 0, 0); paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseChildBlockBackgrounds; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseFloat; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseForeground; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseOutline; paint(paintInfo, paintOffset); }
void Paragraph::paint(Canvas* canvas, double x, double y) { SkCanvas* skCanvas = canvas->canvas(); if (!skCanvas) return; FontCachePurgePreventer fontCachePurgePreventer; // Very simplified painting to allow painting an arbitrary (layer-less) subtree. RenderBox* box = firstChildBox(); skCanvas->translate(x, y); GraphicsContext context(skCanvas); Vector<RenderBox*> layers; LayoutRect bounds = box->absoluteBoundingBoxRect(); DCHECK(bounds.x() == 0 && bounds.y() == 0); PaintInfo paintInfo(&context, enclosingIntRect(bounds), box); box->paint(paintInfo, LayoutPoint(), layers); // Note we're ignoring any layers encountered. // TODO(abarth): Remove the concept of RenderLayers. skCanvas->translate(-x, -y); }
void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect) { // Make sure our dimensions match the rect. setLocation(rect.location() - toLayoutSize(paintOffset)); setWidth(rect.width()); setHeight(rect.height()); if (graphicsContext->paintingDisabled() || !style().opacity()) return; // We don't use RenderLayers for scrollbar parts, so we need to handle opacity here. // Opacity for ScrollbarBGPart is handled by RenderScrollbarTheme::willPaintScrollbar(). bool needsTransparencyLayer = m_part != ScrollbarBGPart && style().opacity() < 1; if (needsTransparencyLayer) { graphicsContext->save(); graphicsContext->clip(rect); graphicsContext->beginTransparencyLayer(style().opacity()); } // Now do the paint. PaintInfo paintInfo(graphicsContext, snappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal); paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseChildBlockBackgrounds; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseFloat; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseForeground; paint(paintInfo, paintOffset); paintInfo.phase = PaintPhaseOutline; paint(paintInfo, paintOffset); if (needsTransparencyLayer) { graphicsContext->endTransparencyLayer(); graphicsContext->restore(); } }