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