• 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 
88         // Add (cumulative) paint overrides to a render node sub-DAG.
89         ScopedRenderContext&& modulateOpacity(float opacity);
90         ScopedRenderContext&& modulateColorFilter(sk_sp<SkColorFilter>);
91         ScopedRenderContext&& modulateShader(sk_sp<SkShader>, const SkMatrix& shader_ctm);
92         ScopedRenderContext&& modulateMaskFilter(sk_sp<SkMaskFilter>, const SkMatrix& mf_ctm);
93         ScopedRenderContext&& modulateBlendMode(SkBlendMode);
94 
95         // Force content isolation for a node sub-DAG by applying the RenderContext
96         // overrides via a layer.
97         ScopedRenderContext&& setIsolation(const SkRect& bounds, const SkMatrix& ctm,
98                                            bool do_isolate);
99 
100         // Similarly, force content isolation by applying the RenderContext overrides and
101         // an image filter via a single layer.
102         ScopedRenderContext&& setFilterIsolation(const SkRect& bounds, const SkMatrix& ctm,
103                                                  sk_sp<SkImageFilter>);
104 
105     private:
106         // stack-only
107         void* operator new(size_t)        = delete;
108         void* operator new(size_t, void*) = delete;
109 
110         // Scopes cannot be copied.
111         ScopedRenderContext(const ScopedRenderContext&)            = delete;
112         ScopedRenderContext& operator=(const ScopedRenderContext&) = delete;
113 
114         SkCanvas*     fCanvas;
115         RenderContext fCtx;
116         int           fRestoreCount;
117     };
118 
119 private:
120     friend class ImageFilterEffect;
121 
122     typedef Node INHERITED;
123 };
124 
125 /**
126  * Clients outside SkSG looking to implement custom render nodes,
127  * should derive from this class instead of RenderNode.  It handles
128  * various book-keeping, and provides a controlled extension point.
129  */
130 class CustomRenderNode : public RenderNode {
131 protected:
132     explicit CustomRenderNode(std::vector<sk_sp<RenderNode>>&& children);
133     ~CustomRenderNode() override;
134 
children()135     const std::vector<sk_sp<RenderNode>>& children() const { return fChildren; }
136 
137     bool hasChildrenInval() const;
138 
139 private:
140     std::vector<sk_sp<RenderNode>> fChildren;
141 
142     using INHERITED = RenderNode;
143 };
144 
145 } // namespace sksg
146 
147 #endif // SkSGRenderNode_DEFINED
148