xref: /aosp_15_r20/external/skia/modules/svg/include/SkSVGRenderContext.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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)
fViewport(viewport)42         : fViewport(viewport), fDPI(dpi) {}
43 
44     enum class LengthType {
45         kHorizontal,
46         kVertical,
47         kOther,
48     };
49 
viewPort()50     const SkSize& viewPort() const { return fViewport; }
setViewPort(const SkSize & viewport)51     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     SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
65     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 
lengthContext()95     const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
writableLengthContext()96     SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
97 
presentationContext()98     const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
99 
canvas()100     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:
BorrowedNode(sk_sp<SkSVGNode> * node)111         explicit BorrowedNode(sk_sp<SkSVGNode>* node)
112             : fOwner(node) {
113             if (fOwner) {
114                 fBorrowed = std::move(*fOwner);
115                 *fOwner = nullptr;
116             }
117         }
118 
~BorrowedNode()119         ~BorrowedNode() {
120             if (fOwner) {
121                 *fOwner = std::move(fBorrowed);
122             }
123         }
124 
get()125         const SkSVGNode* get() const { return fBorrowed.get(); }
126         const SkSVGNode* operator->() const { return fBorrowed.get(); }
127         const SkSVGNode& operator*() const { return *fBorrowed; }
128 
129         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).
clipPath()150     const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
151 
resourceProvider()152     const sk_sp<skresources::ResourceProvider>& resourceProvider() const {
153         return fResourceProvider;
154     }
155 
fontMgr()156     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         SkASSERT(fFontMgr);
160         return fFontMgr ? fFontMgr : SkFontMgr::RefEmpty();
161     }
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 
makeShaper()174     std::unique_ptr<SkShaper> makeShaper() const {
175         SkASSERT(fTextShapingFactory);
176         return fTextShapingFactory->makeShaper(this->fontMgr());
177     }
178 
makeBidiRunIterator(const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)179     std::unique_ptr<SkShaper::BiDiRunIterator> makeBidiRunIterator(const char* utf8,
180                                                                    size_t utf8Bytes,
181                                                                    uint8_t bidiLevel) const {
182         SkASSERT(fTextShapingFactory);
183         return fTextShapingFactory->makeBidiRunIterator(utf8, utf8Bytes, bidiLevel);
184     }
185 
makeScriptRunIterator(const char * utf8,size_t utf8Bytes)186     std::unique_ptr<SkShaper::ScriptRunIterator> makeScriptRunIterator(const char* utf8,
187                                                                        size_t utf8Bytes) const {
188         SkASSERT(fTextShapingFactory);
189         constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z');
190         return fTextShapingFactory->makeScriptRunIterator(utf8, utf8Bytes, unknownScript);
191     }
192 
193 private:
194     // Stack-only
195     void* operator new(size_t)                               = delete;
196     void* operator new(size_t, void*)                        = delete;
197     SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
198 
199     void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
200     void applyFilter(const SkSVGFuncIRI&);
201     void applyClip(const SkSVGFuncIRI&);
202     void applyMask(const SkSVGFuncIRI&);
203 
204     SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
205 
206     const sk_sp<SkFontMgr>&                       fFontMgr;
207     const sk_sp<SkShapers::Factory>&              fTextShapingFactory;
208     const sk_sp<skresources::ResourceProvider>&   fResourceProvider;
209     const SkSVGIDMapper&                          fIDMapper;
210     SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
211     SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
212     SkCanvas*                                     fCanvas;
213     // The save count on 'fCanvas' at construction time.
214     // A restoreToCount() will be issued on destruction.
215     int                                           fCanvasSaveCount;
216 
217     // clipPath, if present for the current context (not inherited).
218     SkTLazy<SkPath>                               fClipPath;
219 
220     // Deferred opacity optimization for leaf nodes.
221     float                                         fDeferredPaintOpacity = 1;
222 
223     // Current object bounding box scope.
224     const OBBScope                                fOBBScope;
225 };
226 
227 #endif // SkSVGRenderContext_DEFINED
228