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 
~BorrowedNode()100         ~BorrowedNode() {
101             if (fOwner) {
102                 *fOwner = std::move(fBorrowed);
103             }
104         }
105 
get()106         const SkSVGNode* get() const { return fBorrowed.get(); }
107         const SkSVGNode* operator->() const { return fBorrowed.get(); }
108         const SkSVGNode& operator*() const { return *fBorrowed; }
109 
110         operator bool() const { return !!fBorrowed; }
111 
112     private:
113         // noncopyable
114         BorrowedNode(const BorrowedNode&)      = delete;
115         BorrowedNode& operator=(BorrowedNode&) = delete;
116 
117         sk_sp<SkSVGNode>* fOwner;
118         sk_sp<SkSVGNode>  fBorrowed;
119     };
120 
121     // Note: the id->node association is cleared for the lifetime of the returned value
122     // (effectively breaks reference cycles, assuming appropriate return value scoping).
123     BorrowedNode findNodeById(const SkSVGIRI&) const;
124 
125     SkTLazy<SkPaint> fillPaint() const;
126     SkTLazy<SkPaint> strokePaint() const;
127 
128     SkSVGColorType resolveSvgColor(const SkSVGColor&) const;
129 
130     // The local computed clip path (not inherited).
clipPath()131     const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
132 
resourceProvider()133     const sk_sp<skresources::ResourceProvider>& resourceProvider() const {
134         return fResourceProvider;
135     }
136 
fontMgr()137     sk_sp<SkFontMgr> fontMgr() const {
138         return fFontMgr ? fFontMgr : SkFontMgr::RefDefault();
139     }
140 
141     // Returns the translate/scale transformation required to map into the current OBB scope,
142     // with the specified units.
143     struct OBBTransform {
144         SkV2 offset, scale;
145     };
146     OBBTransform transformForCurrentOBB(SkSVGObjectBoundingBoxUnits) const;
147 
148     SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y,
149                           const SkSVGLength& w, const SkSVGLength& h,
150                           SkSVGObjectBoundingBoxUnits) const;
151 
152 private:
153     // Stack-only
154     void* operator new(size_t)                               = delete;
155     void* operator new(size_t, void*)                        = delete;
156     SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
157 
158     void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
159     void applyFilter(const SkSVGFuncIRI&);
160     void applyClip(const SkSVGFuncIRI&);
161     void applyMask(const SkSVGFuncIRI&);
162 
163     SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
164 
165     const sk_sp<SkFontMgr>&                       fFontMgr;
166     const sk_sp<skresources::ResourceProvider>&   fResourceProvider;
167     const SkSVGIDMapper&                          fIDMapper;
168     SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
169     SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
170     SkCanvas*                                     fCanvas;
171     // The save count on 'fCanvas' at construction time.
172     // A restoreToCount() will be issued on destruction.
173     int                                           fCanvasSaveCount;
174 
175     // clipPath, if present for the current context (not inherited).
176     SkTLazy<SkPath>                               fClipPath;
177 
178     // Deferred opacity optimization for leaf nodes.
179     float                                         fDeferredPaintOpacity = 1;
180 
181     // Current object bounding box scope.
182     const OBBScope                                fOBBScope;
183 };
184 
185 #endif // SkSVGRenderContext_DEFINED
186