• 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/base/SkTLazy.h"
22 #include "src/core/SkTHash.h"
23 
24 class SkCanvas;
25 class SkSVGLength;
26 
27 class SkSVGLengthContext {
28 public:
29     SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
fViewport(viewport)30         : fViewport(viewport), 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     SkScalar fDPI;
48 };
49 
50 struct SkSVGPresentationContext {
51     SkSVGPresentationContext();
52     SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
53     SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
54 
55     const SkTHashMap<SkString, SkSVGColorType>* fNamedColors = nullptr;
56 
57     // Inherited presentation attributes, computed for the current node.
58     SkSVGPresentationAttributes fInherited;
59 };
60 
61 class SkSVGRenderContext {
62 public:
63     // Captures data required for object bounding box resolution.
64     struct OBBScope {
65         const SkSVGNode*          fNode;
66         const SkSVGRenderContext* fCtx;
67     };
68 
69     SkSVGRenderContext(SkCanvas*, const sk_sp<SkFontMgr>&,
70                        const sk_sp<skresources::ResourceProvider>&, const SkSVGIDMapper&,
71                        const SkSVGLengthContext&, const SkSVGPresentationContext&,
72                        const OBBScope&);
73     SkSVGRenderContext(const SkSVGRenderContext&);
74     SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
75     // Establish a new OBB scope.  Normally used when entering a node's render scope.
76     SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
77     ~SkSVGRenderContext();
78 
lengthContext()79     const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
writableLengthContext()80     SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
81 
presentationContext()82     const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
83 
canvas()84     SkCanvas* canvas() const { return fCanvas; }
85     void saveOnce();
86 
87     enum ApplyFlags {
88         kLeaf = 1 << 0, // the target node doesn't have descendants
89     };
90     void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
91 
92     // Scoped wrapper that temporarily clears the original node reference.
93     class BorrowedNode {
94     public:
BorrowedNode(sk_sp<SkSVGNode> * node)95         explicit BorrowedNode(sk_sp<SkSVGNode>* node)
96             : fOwner(node) {
97             if (fOwner) {
98                 fBorrowed = std::move(*fOwner);
99                 *fOwner = nullptr;
100             }
101         }
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         explicit 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