• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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