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