• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
currentOBBScope()174     const OBBScope& currentOBBScope() const { return fOBBScope; }
175 
makeShaper()176     std::unique_ptr<SkShaper> makeShaper() const {
177         SkASSERT(fTextShapingFactory);
178         return fTextShapingFactory->makeShaper(this->fontMgr());
179     }
180 
makeBidiRunIterator(const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)181     std::unique_ptr<SkShaper::BiDiRunIterator> makeBidiRunIterator(const char* utf8,
182                                                                    size_t utf8Bytes,
183                                                                    uint8_t bidiLevel) const {
184         SkASSERT(fTextShapingFactory);
185         return fTextShapingFactory->makeBidiRunIterator(utf8, utf8Bytes, bidiLevel);
186     }
187 
makeScriptRunIterator(const char * utf8,size_t utf8Bytes)188     std::unique_ptr<SkShaper::ScriptRunIterator> makeScriptRunIterator(const char* utf8,
189                                                                        size_t utf8Bytes) const {
190         SkASSERT(fTextShapingFactory);
191         constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z');
192         return fTextShapingFactory->makeScriptRunIterator(utf8, utf8Bytes, unknownScript);
193     }
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
230