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