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