Coverage Report

Created: 2024-05-20 07:14

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