Coverage Report

Created: 2024-05-20 07:14

/src/skia/modules/sksg/include/SkSGRenderNode.h
Line
Count
Source (jump to first uncovered line)
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 "include/core/SkBlender.h"
12
#include "include/core/SkColorFilter.h"
13
#include "include/core/SkMatrix.h"
14
#include "include/core/SkRefCnt.h"
15
#include "include/core/SkShader.h"
16
#include "modules/sksg/include/SkSGNode.h"
17
18
#include <cstddef>
19
#include <cstdint>
20
#include <utility>
21
#include <vector>
22
23
class SkCanvas;
24
class SkImageFilter;
25
class SkPaint;
26
struct SkPoint;
27
struct SkRect;
28
29
namespace sksg {
30
31
/**
32
 * Base class for nodes which can render to a canvas.
33
 */
34
class RenderNode : public Node {
35
protected:
36
    struct RenderContext;
37
38
public:
39
    // Render the node and its descendants to the canvas.
40
    void render(SkCanvas*, const RenderContext* = nullptr) const;
41
42
    // Perform a front-to-back hit-test, and return the RenderNode located at |point|.
43
    // Normally, hit-testing stops at leaf Draw nodes.
44
    const RenderNode* nodeAt(const SkPoint& point) const;
45
46
    // Controls the visibility of the render node.  Invisible nodes are not rendered,
47
    // but they still participate in revalidation.
48
    bool isVisible() const;
49
    void setVisible(bool);
50
51
protected:
52
    explicit RenderNode(uint32_t inval_traits = 0);
53
54
    virtual void onRender(SkCanvas*, const RenderContext*) const = 0;
55
    virtual const RenderNode* onNodeAt(const SkPoint& p)   const = 0;
56
57
    // Paint property overrides.
58
    // These are deferred until we can determine whether they can be applied to the individual
59
    // draw paints, or whether they require content isolation (applied to a layer).
60
    struct RenderContext {
61
        sk_sp<SkColorFilter> fColorFilter;
62
        sk_sp<SkShader>      fShader;
63
        sk_sp<SkShader>      fMaskShader;
64
        sk_sp<SkBlender>     fBlender;
65
        SkMatrix             fShaderCTM = SkMatrix::I(),
66
                             fMaskCTM   = SkMatrix::I();
67
        float                fOpacity   = 1;
68
69
        // Returns true if the paint overrides require a layer when applied to non-atomic draws.
70
        bool requiresIsolation() const;
71
72
        void modulatePaint(const SkMatrix& ctm, SkPaint*, bool is_layer_paint = false) const;
73
    };
74
75
    class ScopedRenderContext final {
76
    public:
77
        ScopedRenderContext(SkCanvas*, const RenderContext*);
78
        ~ScopedRenderContext();
79
80
10.3k
        ScopedRenderContext(ScopedRenderContext&& that) { *this = std::move(that); }
81
82
10.3k
        ScopedRenderContext& operator=(ScopedRenderContext&& that) {
83
10.3k
            fCanvas       = that.fCanvas;
84
10.3k
            fCtx          = std::move(that.fCtx);
85
10.3k
            fMaskShader   = std::move(that.fMaskShader);
86
10.3k
            fRestoreCount = that.fRestoreCount;
87
88
            // scope ownership is being transferred
89
10.3k
            that.fRestoreCount = -1;
90
91
10.3k
            return *this;
92
10.3k
        }
93
94
43.4k
        operator const RenderContext*  () const { return &fCtx; }
95
0
        const RenderContext* operator->() const { return &fCtx; }
96
97
        // Add (cumulative) paint overrides to a render node sub-DAG.
98
        ScopedRenderContext&& modulateOpacity(float opacity);
99
        ScopedRenderContext&& modulateColorFilter(sk_sp<SkColorFilter>);
100
        ScopedRenderContext&& modulateShader(sk_sp<SkShader>, const SkMatrix& shader_ctm);
101
        ScopedRenderContext&& modulateMaskShader(sk_sp<SkShader>, const SkMatrix& ms_ctm);
102
        ScopedRenderContext&& modulateBlender(sk_sp<SkBlender>);
103
104
        // Force content isolation for a node sub-DAG by applying the RenderContext
105
        // overrides via a layer.
106
        ScopedRenderContext&& setIsolation(const SkRect& bounds, const SkMatrix& ctm,
107
                                           bool do_isolate);
108
109
        // Similarly, force content isolation by applying the RenderContext overrides and
110
        // an image filter via a single layer.
111
        ScopedRenderContext&& setFilterIsolation(const SkRect& bounds, const SkMatrix& ctm,
112
                                                 sk_sp<SkImageFilter>);
113
114
    private:
115
        // stack-only
116
        void* operator new(size_t)        = delete;
117
        void* operator new(size_t, void*) = delete;
118
119
        // Scopes cannot be copied.
120
        ScopedRenderContext(const ScopedRenderContext&)            = delete;
121
        ScopedRenderContext& operator=(const ScopedRenderContext&) = delete;
122
123
        SkCanvas*       fCanvas;
124
        RenderContext   fCtx;
125
        sk_sp<SkShader> fMaskShader; // to be applied at isolation layer restore time
126
        int             fRestoreCount;
127
    };
128
129
private:
130
    friend class ImageFilterEffect;
131
132
    using INHERITED = Node;
133
};
134
135
/**
136
 * Clients outside SkSG looking to implement custom render nodes,
137
 * should derive from this class instead of RenderNode.  It handles
138
 * various book-keeping, and provides a controlled extension point.
139
 */
140
class CustomRenderNode : public RenderNode {
141
protected:
142
    explicit CustomRenderNode(std::vector<sk_sp<RenderNode>>&& children);
143
    ~CustomRenderNode() override;
144
145
17.5k
    const std::vector<sk_sp<RenderNode>>& children() const { return fChildren; }
146
147
    bool hasChildrenInval() const;
148
149
private:
150
    std::vector<sk_sp<RenderNode>> fChildren;
151
152
    using INHERITED = RenderNode;
153
};
154
155
} // namespace sksg
156
157
#endif // SkSGRenderNode_DEFINED