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 "SkSGNode.h" 12 13 #include "SkBlendMode.h" 14 #include "SkColorFilter.h" 15 16 class SkCanvas; 17 class SkImageFilter; 18 class SkPaint; 19 20 namespace sksg { 21 22 /** 23 * Base class for nodes which can render to a canvas. 24 */ 25 class RenderNode : public Node { 26 protected: 27 struct RenderContext; 28 29 public: 30 // Render the node and its descendants to the canvas. 31 void render(SkCanvas*, const RenderContext* = nullptr) const; 32 33 // Perform a front-to-back hit-test, and return the RenderNode located at |point|. 34 // Normally, hit-testing stops at leaf Draw nodes. 35 const RenderNode* nodeAt(const SkPoint& point) const; 36 37 protected: 38 explicit RenderNode(uint32_t inval_traits = 0); 39 40 virtual void onRender(SkCanvas*, const RenderContext*) const = 0; 41 virtual const RenderNode* onNodeAt(const SkPoint& p) const = 0; 42 43 // Paint property overrides. 44 // These are deferred until we can determine whether they can be applied to the individual 45 // draw paints, or whether they require content isolation (applied to a layer). 46 struct RenderContext { 47 sk_sp<SkColorFilter> fColorFilter; 48 float fOpacity = 1; 49 SkBlendMode fBlendMode = SkBlendMode::kSrcOver; 50 51 // Returns true if the paint was modified. 52 bool modulatePaint(SkPaint*) const; 53 }; 54 55 class ScopedRenderContext final { 56 public: 57 ScopedRenderContext(SkCanvas*, const RenderContext*); 58 ~ScopedRenderContext(); 59 ScopedRenderContext(ScopedRenderContext && that)60 ScopedRenderContext(ScopedRenderContext&& that) { *this = std::move(that); } 61 62 ScopedRenderContext& operator=(ScopedRenderContext&& that) { 63 fCanvas = that.fCanvas; 64 fCtx = std::move(that.fCtx); 65 fRestoreCount = that.fRestoreCount; 66 67 // scope ownership is being transferred 68 that.fRestoreCount = -1; 69 70 return *this; 71 } 72 73 operator const RenderContext* () const { return &fCtx; } 74 75 // Add (cumulative) paint overrides to a render node sub-DAG. 76 ScopedRenderContext&& modulateOpacity(float opacity); 77 ScopedRenderContext&& modulateColorFilter(sk_sp<SkColorFilter>); 78 ScopedRenderContext&& modulateBlendMode(SkBlendMode); 79 80 // Force content isolation for a node sub-DAG by applying the RenderContext 81 // overrides via a layer. 82 ScopedRenderContext&& setIsolation(const SkRect& bounds, bool do_isolate); 83 84 // Similarly, force content isolation by applying the RenderContext overrides and 85 // an image filter via a single layer. 86 ScopedRenderContext&& setFilterIsolation(const SkRect& bounds, sk_sp<SkImageFilter>); 87 88 private: 89 // stack-only 90 void* operator new(size_t) = delete; 91 void* operator new(size_t, void*) = delete; 92 93 // Scopes cannot be copied. 94 ScopedRenderContext(const ScopedRenderContext&) = delete; 95 ScopedRenderContext& operator=(const ScopedRenderContext&) = delete; 96 97 SkCanvas* fCanvas; 98 RenderContext fCtx; 99 int fRestoreCount; 100 }; 101 102 private: 103 friend class ImageFilterEffect; 104 105 typedef Node INHERITED; 106 }; 107 108 } // namespace sksg 109 110 #endif // SkSGRenderNode_DEFINED 111