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/SkBlendMode.h" 14 #include "include/core/SkColorFilter.h" 15 #include "include/core/SkMaskFilter.h" 16 #include "include/core/SkShader.h" 17 18 class SkCanvas; 19 class SkImageFilter; 20 class SkPaint; 21 22 namespace sksg { 23 24 /** 25 * Base class for nodes which can render to a canvas. 26 */ 27 class RenderNode : public Node { 28 protected: 29 struct RenderContext; 30 31 public: 32 // Render the node and its descendants to the canvas. 33 void render(SkCanvas*, const RenderContext* = nullptr) const; 34 35 // Perform a front-to-back hit-test, and return the RenderNode located at |point|. 36 // Normally, hit-testing stops at leaf Draw nodes. 37 const RenderNode* nodeAt(const SkPoint& point) const; 38 39 // Controls the visibility of the render node. Invisible nodes are not rendered, 40 // but they still participate in revalidation. 41 bool isVisible() const; 42 void setVisible(bool); 43 44 protected: 45 explicit RenderNode(uint32_t inval_traits = 0); 46 47 virtual void onRender(SkCanvas*, const RenderContext*) const = 0; 48 virtual const RenderNode* onNodeAt(const SkPoint& p) const = 0; 49 50 // Paint property overrides. 51 // These are deferred until we can determine whether they can be applied to the individual 52 // draw paints, or whether they require content isolation (applied to a layer). 53 struct RenderContext { 54 sk_sp<SkColorFilter> fColorFilter; 55 sk_sp<SkShader> fShader; 56 sk_sp<SkMaskFilter> fMaskFilter; 57 SkMatrix fShaderCTM = SkMatrix::I(), 58 fMaskCTM = SkMatrix::I(); 59 float fOpacity = 1; 60 SkBlendMode fBlendMode = SkBlendMode::kSrcOver; 61 62 // Returns true if the paint overrides require a layer when applied to non-atomic draws. 63 bool requiresIsolation() const; 64 65 void modulatePaint(const SkMatrix& ctm, SkPaint*) const; 66 }; 67 68 class ScopedRenderContext final { 69 public: 70 ScopedRenderContext(SkCanvas*, const RenderContext*); 71 ~ScopedRenderContext(); 72 ScopedRenderContext(ScopedRenderContext && that)73 ScopedRenderContext(ScopedRenderContext&& that) { *this = std::move(that); } 74 75 ScopedRenderContext& operator=(ScopedRenderContext&& that) { 76 fCanvas = that.fCanvas; 77 fCtx = std::move(that.fCtx); 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&& modulateMaskFilter(sk_sp<SkMaskFilter>, const SkMatrix& mf_ctm); 94 ScopedRenderContext&& modulateBlendMode(SkBlendMode); 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 int fRestoreCount; 118 }; 119 120 private: 121 friend class ImageFilterEffect; 122 123 typedef Node INHERITED; 124 }; 125 126 /** 127 * Clients outside SkSG looking to implement custom render nodes, 128 * should derive from this class instead of RenderNode. It handles 129 * various book-keeping, and provides a controlled extension point. 130 */ 131 class CustomRenderNode : public RenderNode { 132 protected: 133 explicit CustomRenderNode(std::vector<sk_sp<RenderNode>>&& children); 134 ~CustomRenderNode() override; 135 children()136 const std::vector<sk_sp<RenderNode>>& children() const { return fChildren; } 137 138 bool hasChildrenInval() const; 139 140 private: 141 std::vector<sk_sp<RenderNode>> fChildren; 142 143 using INHERITED = RenderNode; 144 }; 145 146 } // namespace sksg 147 148 #endif // SkSGRenderNode_DEFINED 149