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