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