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