• 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/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/svg/include/SkSVGAttribute.h"
20 #include "modules/svg/include/SkSVGIDMapper.h"
21 #include "src/core/SkTLazy.h"
22 
23 static constexpr float DEFAULT_RESIZE_PERCENTAGE = 100;
24 class SkCanvas;
25 class SkSVGLength;
26 
27 class SkSVGLengthContext {
28 public:
29     SkSVGLengthContext(const SkSize& viewport, float resizePercentage = DEFAULT_RESIZE_PERCENTAGE, SkScalar dpi = 90)
fViewport(viewport)30         : fViewport(viewport), fResizePercentage(resizePercentage), fDPI(dpi) {}
31 
32     enum class LengthType {
33         kHorizontal,
34         kVertical,
35         kOther,
36     };
37 
getResizePercentage()38     const float& getResizePercentage() const { return fResizePercentage; }
viewPort()39     const SkSize& viewPort() const { return fViewport; }
setViewPort(const SkSize & viewport)40     void setViewPort(const SkSize& viewport) { fViewport = viewport; }
41 
42     SkScalar resolve(const SkSVGLength&, LengthType) const;
43     SkScalar resolveForSVG(const SkSVGLength&, LengthType) const;
44     SkRect   resolveRect(const SkSVGLength& x, const SkSVGLength& y,
45                          const SkSVGLength& w, const SkSVGLength& h) const;
46     SkRect   resolveRectForSVG(const SkSVGLength& x, const SkSVGLength& y,
47                          const SkSVGLength& w, const SkSVGLength& h) const;
48 
49 private:
50     SkSize   fViewport;
51     float  fResizePercentage;
52     SkScalar fDPI;
53 };
54 
55 struct SkSVGPresentationContext {
56     SkSVGPresentationContext();
57     SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
58     SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
59 
60     // Inherited presentation attributes, computed for the current node.
61     SkSVGPresentationAttributes fInherited;
62 };
63 
64 class SkSVGRenderContext {
65 public:
66     // Captures data required for object bounding box resolution.
67     struct OBBScope {
68         const SkSVGNode*          fNode;
69         const SkSVGRenderContext* fCtx;
70     };
71 
72     SkSVGRenderContext(SkCanvas*, const sk_sp<SkFontMgr>&,
73                        const sk_sp<skresources::ResourceProvider>&, const SkSVGIDMapper&,
74                        const SkSVGLengthContext&, const SkSVGPresentationContext&,
75                        const OBBScope&);
76     SkSVGRenderContext(const SkSVGRenderContext&);
77     SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
78     // Establish a new OBB scope.  Normally used when entering a node's render scope.
79     SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
80     ~SkSVGRenderContext();
81 
lengthContext()82     const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
writableLengthContext()83     SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
84 
presentationContext()85     const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
86 
canvas()87     SkCanvas* canvas() const { return fCanvas; }
88     void saveOnce();
89 
90     enum ApplyFlags {
91         kLeaf = 1 << 0, // the target node doesn't have descendants
92     };
93     void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
94 
95     // Scoped wrapper that temporarily clears the original node reference.
96     class BorrowedNode {
97     public:
BorrowedNode(sk_sp<SkSVGNode> * node)98         explicit BorrowedNode(sk_sp<SkSVGNode>* node)
99             : fOwner(node) {
100             if (fOwner) {
101                 fBorrowed = std::move(*fOwner);
102                 *fOwner = nullptr;
103             }
104         }
105 
106         // Required until C++17 copy elision
107         BorrowedNode(BorrowedNode&&) = default;
108 
~BorrowedNode()109         ~BorrowedNode() {
110             if (fOwner) {
111                 *fOwner = std::move(fBorrowed);
112             }
113         }
114 
get()115         const SkSVGNode* get() const { return fBorrowed.get(); }
116         const SkSVGNode* operator->() const { return fBorrowed.get(); }
117         const SkSVGNode& operator*() const { return *fBorrowed; }
118 
119         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).
clipPath()140     const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
141 
resourceProvider()142     const sk_sp<skresources::ResourceProvider>& resourceProvider() const {
143         return fResourceProvider;
144     }
145 
fontMgr()146     sk_sp<SkFontMgr> fontMgr() const {
147         return fFontMgr ? fFontMgr : SkFontMgr::RefDefault();
148     }
149 
150     // Returns the translate/scale transformation required to map into the current OBB scope,
151     // with the specified units.
152     struct OBBTransform {
153         SkV2 offset, scale;
154     };
155     OBBTransform transformForCurrentOBB(SkSVGObjectBoundingBoxUnits) const;
156 
157     SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y,
158                           const SkSVGLength& w, const SkSVGLength& h,
159                           SkSVGObjectBoundingBoxUnits) const;
160 
161 private:
162     // Stack-only
163     void* operator new(size_t)                               = delete;
164     void* operator new(size_t, void*)                        = delete;
165     SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
166 
167     void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
168     void applyFilter(const SkSVGFuncIRI&);
169     void applyClip(const SkSVGFuncIRI&);
170     void applyMask(const SkSVGFuncIRI&);
171 
172     SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
173 
174     const sk_sp<SkFontMgr>&                       fFontMgr;
175     const sk_sp<skresources::ResourceProvider>&   fResourceProvider;
176     const SkSVGIDMapper&                          fIDMapper;
177     SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
178     SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
179     SkCanvas*                                     fCanvas;
180     // The save count on 'fCanvas' at construction time.
181     // A restoreToCount() will be issued on destruction.
182     int                                           fCanvasSaveCount;
183 
184     // clipPath, if present for the current context (not inherited).
185     SkTLazy<SkPath>                               fClipPath;
186 
187     // Deferred opacity optimization for leaf nodes.
188     float                                         fDeferredPaintOpacity = 1;
189 
190     // Current object bounding box scope.
191     const OBBScope                                fOBBScope;
192 };
193 
194 #endif // SkSVGRenderContext_DEFINED
195