Coverage Report

Created: 2025-06-24 08:20

/src/skia/modules/svg/include/SkSVGRenderContext.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2016 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 SkSVGRenderContext_DEFINED
9
#define SkSVGRenderContext_DEFINED
10
11
#include "include/core/SkFontMgr.h"
12
#include "include/core/SkFourByteTag.h"
13
#include "include/core/SkM44.h"
14
#include "include/core/SkPath.h"
15
#include "include/core/SkRect.h"
16
#include "include/core/SkRefCnt.h"
17
#include "include/core/SkScalar.h"
18
#include "include/core/SkSize.h"
19
#include "include/core/SkTypes.h"
20
#include "modules/skshaper/include/SkShaper.h"
21
#include "modules/skshaper/include/SkShaper_factory.h"
22
#include "modules/svg/include/SkSVGAttribute.h"
23
#include "modules/svg/include/SkSVGIDMapper.h"
24
#include "modules/svg/include/SkSVGNode.h"
25
#include "modules/svg/include/SkSVGTypes.h"
26
#include "src/base/SkTLazy.h"
27
#include "src/core/SkTHash.h"
28
29
#include <cstddef>
30
#include <cstdint>
31
#include <memory>
32
#include <utility>
33
34
class SkCanvas;
35
class SkPaint;
36
class SkString;
37
namespace skresources { class ResourceProvider; }
38
39
class SK_API SkSVGLengthContext {
40
public:
41
    SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
42
68.4k
        : fViewport(viewport), fDPI(dpi) {}
43
44
    enum class LengthType {
45
        kHorizontal,
46
        kVertical,
47
        kOther,
48
    };
49
50
54.0k
    const SkSize& viewPort() const { return fViewport; }
51
1.96k
    void setViewPort(const SkSize& viewport) { fViewport = viewport; }
52
53
    SkScalar resolve(const SkSVGLength&, LengthType) const;
54
    SkRect   resolveRect(const SkSVGLength& x, const SkSVGLength& y,
55
                         const SkSVGLength& w, const SkSVGLength& h) const;
56
57
private:
58
    SkSize   fViewport;
59
    SkScalar fDPI;
60
};
61
62
struct SK_API SkSVGPresentationContext {
63
    SkSVGPresentationContext();
64
44.8k
    SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
65
0
    SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
66
67
    const skia_private::THashMap<SkString, SkSVGColorType>* fNamedColors = nullptr;
68
69
    // Inherited presentation attributes, computed for the current node.
70
    SkSVGPresentationAttributes fInherited;
71
};
72
73
class SK_API SkSVGRenderContext {
74
public:
75
    // Captures data required for object bounding box resolution.
76
    struct OBBScope {
77
        const SkSVGNode*          fNode;
78
        const SkSVGRenderContext* fCtx;
79
    };
80
81
    SkSVGRenderContext(SkCanvas*,
82
                       const sk_sp<SkFontMgr>&,
83
                       const sk_sp<skresources::ResourceProvider>&,
84
                       const SkSVGIDMapper&,
85
                       const SkSVGLengthContext&,
86
                       const SkSVGPresentationContext&,
87
                       const OBBScope&,
88
                       const sk_sp<SkShapers::Factory>&);
89
    SkSVGRenderContext(const SkSVGRenderContext&);
90
    SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
91
    // Establish a new OBB scope.  Normally used when entering a node's render scope.
92
    SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
93
    ~SkSVGRenderContext();
94
95
414k
    const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
96
1.96k
    SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
97
98
1.64M
    const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
99
100
528k
    SkCanvas* canvas() const { return fCanvas; }
101
    void saveOnce();
102
103
    enum ApplyFlags {
104
        kLeaf = 1 << 0, // the target node doesn't have descendants
105
    };
106
    void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
107
108
    // Scoped wrapper that temporarily clears the original node reference.
109
    class BorrowedNode {
110
    public:
111
        explicit BorrowedNode(sk_sp<SkSVGNode>* node)
112
96.4k
            : fOwner(node) {
113
96.4k
            if (fOwner) {
114
86.8k
                fBorrowed = std::move(*fOwner);
115
86.8k
                *fOwner = nullptr;
116
86.8k
            }
117
96.4k
        }
118
119
96.4k
        ~BorrowedNode() {
120
96.4k
            if (fOwner) {
121
86.8k
                *fOwner = std::move(fBorrowed);
122
86.8k
            }
123
96.4k
        }
124
125
28.0k
        const SkSVGNode* get() const { return fBorrowed.get(); }
126
42.4k
        const SkSVGNode* operator->() const { return fBorrowed.get(); }
127
0
        const SkSVGNode& operator*() const { return *fBorrowed; }
128
129
96.4k
        explicit operator bool() const { return !!fBorrowed; }
130
131
    private:
132
        // noncopyable
133
        BorrowedNode(const BorrowedNode&)      = delete;
134
        BorrowedNode& operator=(BorrowedNode&) = delete;
135
136
        sk_sp<SkSVGNode>* fOwner;
137
        sk_sp<SkSVGNode>  fBorrowed;
138
    };
139
140
    // Note: the id->node association is cleared for the lifetime of the returned value
141
    // (effectively breaks reference cycles, assuming appropriate return value scoping).
142
    BorrowedNode findNodeById(const SkSVGIRI&) const;
143
144
    SkTLazy<SkPaint> fillPaint() const;
145
    SkTLazy<SkPaint> strokePaint() const;
146
147
    SkSVGColorType resolveSvgColor(const SkSVGColor&) const;
148
149
    // The local computed clip path (not inherited).
150
398k
    const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
151
152
0
    const sk_sp<skresources::ResourceProvider>& resourceProvider() const {
153
0
        return fResourceProvider;
154
0
    }
155
156
152k
    sk_sp<SkFontMgr> fontMgr() const {
157
        // It is probably an oversight to try to render <text> without having set the SkFontMgr.
158
        // We will assert this in debug mode, but fallback to an empty fontmgr in release builds.
159
152k
        SkASSERT(fFontMgr);
160
152k
        return fFontMgr ? fFontMgr : SkFontMgr::RefEmpty();
161
152k
    }
162
163
    // Returns the translate/scale transformation required to map into the current OBB scope,
164
    // with the specified units.
165
    struct OBBTransform {
166
        SkV2 offset, scale;
167
    };
168
    OBBTransform transformForCurrentOBB(SkSVGObjectBoundingBoxUnits) const;
169
170
    SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y,
171
                          const SkSVGLength& w, const SkSVGLength& h,
172
                          SkSVGObjectBoundingBoxUnits) const;
173
174
65.4k
    const OBBScope& currentOBBScope() const { return fOBBScope; }
175
176
33.9k
    std::unique_ptr<SkShaper> makeShaper() const {
177
33.9k
        SkASSERT(fTextShapingFactory);
178
33.9k
        return fTextShapingFactory->makeShaper(this->fontMgr());
179
33.9k
    }
180
181
    std::unique_ptr<SkShaper::BiDiRunIterator> makeBidiRunIterator(const char* utf8,
182
                                                                   size_t utf8Bytes,
183
61.8k
                                                                   uint8_t bidiLevel) const {
184
61.8k
        SkASSERT(fTextShapingFactory);
185
61.8k
        return fTextShapingFactory->makeBidiRunIterator(utf8, utf8Bytes, bidiLevel);
186
61.8k
    }
187
188
    std::unique_ptr<SkShaper::ScriptRunIterator> makeScriptRunIterator(const char* utf8,
189
61.8k
                                                                       size_t utf8Bytes) const {
190
61.8k
        SkASSERT(fTextShapingFactory);
191
61.8k
        constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z');
192
61.8k
        return fTextShapingFactory->makeScriptRunIterator(utf8, utf8Bytes, unknownScript);
193
61.8k
    }
194
195
private:
196
    // Stack-only
197
    void* operator new(size_t)                               = delete;
198
    void* operator new(size_t, void*)                        = delete;
199
    SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
200
201
    void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
202
    void applyFilter(const SkSVGFuncIRI&);
203
    void applyClip(const SkSVGFuncIRI&);
204
    void applyMask(const SkSVGFuncIRI&);
205
206
    SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
207
208
    const sk_sp<SkFontMgr>&                       fFontMgr;
209
    const sk_sp<SkShapers::Factory>&              fTextShapingFactory;
210
    const sk_sp<skresources::ResourceProvider>&   fResourceProvider;
211
    const SkSVGIDMapper&                          fIDMapper;
212
    SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
213
    SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
214
    SkCanvas*                                     fCanvas;
215
    // The save count on 'fCanvas' at construction time.
216
    // A restoreToCount() will be issued on destruction.
217
    int                                           fCanvasSaveCount;
218
219
    // clipPath, if present for the current context (not inherited).
220
    SkTLazy<SkPath>                               fClipPath;
221
222
    // Deferred opacity optimization for leaf nodes.
223
    float                                         fDeferredPaintOpacity = 1;
224
225
    // Current object bounding box scope.
226
    const OBBScope                                fOBBScope;
227
};
228
229
#endif // SkSVGRenderContext_DEFINED