1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkSGRenderNode_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define SkSGRenderNode_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlender.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGNode.h" 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 19*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 20*c8dee2aaSAndroid Build Coastguard Worker #include <utility> 21*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker class SkCanvas; 24*c8dee2aaSAndroid Build Coastguard Worker class SkImageFilter; 25*c8dee2aaSAndroid Build Coastguard Worker class SkPaint; 26*c8dee2aaSAndroid Build Coastguard Worker struct SkPoint; 27*c8dee2aaSAndroid Build Coastguard Worker struct SkRect; 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker namespace sksg { 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Worker /** 32*c8dee2aaSAndroid Build Coastguard Worker * Base class for nodes which can render to a canvas. 33*c8dee2aaSAndroid Build Coastguard Worker */ 34*c8dee2aaSAndroid Build Coastguard Worker class RenderNode : public Node { 35*c8dee2aaSAndroid Build Coastguard Worker protected: 36*c8dee2aaSAndroid Build Coastguard Worker struct RenderContext; 37*c8dee2aaSAndroid Build Coastguard Worker 38*c8dee2aaSAndroid Build Coastguard Worker public: 39*c8dee2aaSAndroid Build Coastguard Worker // Render the node and its descendants to the canvas. 40*c8dee2aaSAndroid Build Coastguard Worker void render(SkCanvas*, const RenderContext* = nullptr) const; 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker // Perform a front-to-back hit-test, and return the RenderNode located at |point|. 43*c8dee2aaSAndroid Build Coastguard Worker // Normally, hit-testing stops at leaf Draw nodes. 44*c8dee2aaSAndroid Build Coastguard Worker const RenderNode* nodeAt(const SkPoint& point) const; 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker // Controls the visibility of the render node. Invisible nodes are not rendered, 47*c8dee2aaSAndroid Build Coastguard Worker // but they still participate in revalidation. 48*c8dee2aaSAndroid Build Coastguard Worker bool isVisible() const; 49*c8dee2aaSAndroid Build Coastguard Worker void setVisible(bool); 50*c8dee2aaSAndroid Build Coastguard Worker 51*c8dee2aaSAndroid Build Coastguard Worker protected: 52*c8dee2aaSAndroid Build Coastguard Worker explicit RenderNode(uint32_t inval_traits = 0); 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker virtual void onRender(SkCanvas*, const RenderContext*) const = 0; 55*c8dee2aaSAndroid Build Coastguard Worker virtual const RenderNode* onNodeAt(const SkPoint& p) const = 0; 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker // Paint property overrides. 58*c8dee2aaSAndroid Build Coastguard Worker // These are deferred until we can determine whether they can be applied to the individual 59*c8dee2aaSAndroid Build Coastguard Worker // draw paints, or whether they require content isolation (applied to a layer). 60*c8dee2aaSAndroid Build Coastguard Worker struct RenderContext { 61*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorFilter> fColorFilter; 62*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fShader; 63*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fMaskShader; 64*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkBlender> fBlender; 65*c8dee2aaSAndroid Build Coastguard Worker SkMatrix fShaderCTM = SkMatrix::I(), 66*c8dee2aaSAndroid Build Coastguard Worker fMaskCTM = SkMatrix::I(); 67*c8dee2aaSAndroid Build Coastguard Worker float fOpacity = 1; 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker // Returns true if the paint overrides require a layer when applied to non-atomic draws. 70*c8dee2aaSAndroid Build Coastguard Worker bool requiresIsolation() const; 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker void modulatePaint(const SkMatrix& ctm, SkPaint*, bool is_layer_paint = false) const; 73*c8dee2aaSAndroid Build Coastguard Worker }; 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard Worker class ScopedRenderContext final { 76*c8dee2aaSAndroid Build Coastguard Worker public: 77*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext(SkCanvas*, const RenderContext*); 78*c8dee2aaSAndroid Build Coastguard Worker ~ScopedRenderContext(); 79*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext(ScopedRenderContext && that)80*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext(ScopedRenderContext&& that) { *this = std::move(that); } 81*c8dee2aaSAndroid Build Coastguard Worker 82*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext& operator=(ScopedRenderContext&& that) { 83*c8dee2aaSAndroid Build Coastguard Worker fCanvas = that.fCanvas; 84*c8dee2aaSAndroid Build Coastguard Worker fCtx = std::move(that.fCtx); 85*c8dee2aaSAndroid Build Coastguard Worker fMaskShader = std::move(that.fMaskShader); 86*c8dee2aaSAndroid Build Coastguard Worker fRestoreCount = that.fRestoreCount; 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker // scope ownership is being transferred 89*c8dee2aaSAndroid Build Coastguard Worker that.fRestoreCount = -1; 90*c8dee2aaSAndroid Build Coastguard Worker 91*c8dee2aaSAndroid Build Coastguard Worker return *this; 92*c8dee2aaSAndroid Build Coastguard Worker } 93*c8dee2aaSAndroid Build Coastguard Worker 94*c8dee2aaSAndroid Build Coastguard Worker operator const RenderContext* () const { return &fCtx; } 95*c8dee2aaSAndroid Build Coastguard Worker const RenderContext* operator->() const { return &fCtx; } 96*c8dee2aaSAndroid Build Coastguard Worker 97*c8dee2aaSAndroid Build Coastguard Worker // Add (cumulative) paint overrides to a render node sub-DAG. 98*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& modulateOpacity(float opacity); 99*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& modulateColorFilter(sk_sp<SkColorFilter>); 100*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& modulateShader(sk_sp<SkShader>, const SkMatrix& shader_ctm); 101*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& modulateMaskShader(sk_sp<SkShader>, const SkMatrix& ms_ctm); 102*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& modulateBlender(sk_sp<SkBlender>); 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker // Force content isolation for a node sub-DAG by applying the RenderContext 105*c8dee2aaSAndroid Build Coastguard Worker // overrides via a layer. 106*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& setIsolation(const SkRect& bounds, const SkMatrix& ctm, 107*c8dee2aaSAndroid Build Coastguard Worker bool do_isolate); 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Worker // Similarly, force content isolation by applying the RenderContext overrides and 110*c8dee2aaSAndroid Build Coastguard Worker // an image filter via a single layer. 111*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext&& setFilterIsolation(const SkRect& bounds, const SkMatrix& ctm, 112*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImageFilter>); 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker private: 115*c8dee2aaSAndroid Build Coastguard Worker // stack-only 116*c8dee2aaSAndroid Build Coastguard Worker void* operator new(size_t) = delete; 117*c8dee2aaSAndroid Build Coastguard Worker void* operator new(size_t, void*) = delete; 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker // Scopes cannot be copied. 120*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext(const ScopedRenderContext&) = delete; 121*c8dee2aaSAndroid Build Coastguard Worker ScopedRenderContext& operator=(const ScopedRenderContext&) = delete; 122*c8dee2aaSAndroid Build Coastguard Worker 123*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* fCanvas; 124*c8dee2aaSAndroid Build Coastguard Worker RenderContext fCtx; 125*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fMaskShader; // to be applied at isolation layer restore time 126*c8dee2aaSAndroid Build Coastguard Worker int fRestoreCount; 127*c8dee2aaSAndroid Build Coastguard Worker }; 128*c8dee2aaSAndroid Build Coastguard Worker 129*c8dee2aaSAndroid Build Coastguard Worker private: 130*c8dee2aaSAndroid Build Coastguard Worker friend class ImageFilterEffect; 131*c8dee2aaSAndroid Build Coastguard Worker 132*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Node; 133*c8dee2aaSAndroid Build Coastguard Worker }; 134*c8dee2aaSAndroid Build Coastguard Worker 135*c8dee2aaSAndroid Build Coastguard Worker /** 136*c8dee2aaSAndroid Build Coastguard Worker * Clients outside SkSG looking to implement custom render nodes, 137*c8dee2aaSAndroid Build Coastguard Worker * should derive from this class instead of RenderNode. It handles 138*c8dee2aaSAndroid Build Coastguard Worker * various book-keeping, and provides a controlled extension point. 139*c8dee2aaSAndroid Build Coastguard Worker */ 140*c8dee2aaSAndroid Build Coastguard Worker class CustomRenderNode : public RenderNode { 141*c8dee2aaSAndroid Build Coastguard Worker protected: 142*c8dee2aaSAndroid Build Coastguard Worker explicit CustomRenderNode(std::vector<sk_sp<RenderNode>>&& children); 143*c8dee2aaSAndroid Build Coastguard Worker ~CustomRenderNode() override; 144*c8dee2aaSAndroid Build Coastguard Worker children()145*c8dee2aaSAndroid Build Coastguard Worker const std::vector<sk_sp<RenderNode>>& children() const { return fChildren; } 146*c8dee2aaSAndroid Build Coastguard Worker 147*c8dee2aaSAndroid Build Coastguard Worker bool hasChildrenInval() const; 148*c8dee2aaSAndroid Build Coastguard Worker 149*c8dee2aaSAndroid Build Coastguard Worker private: 150*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<RenderNode>> fChildren; 151*c8dee2aaSAndroid Build Coastguard Worker 152*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = RenderNode; 153*c8dee2aaSAndroid Build Coastguard Worker }; 154*c8dee2aaSAndroid Build Coastguard Worker 155*c8dee2aaSAndroid Build Coastguard Worker } // namespace sksg 156*c8dee2aaSAndroid Build Coastguard Worker 157*c8dee2aaSAndroid Build Coastguard Worker #endif // SkSGRenderNode_DEFINED 158