/src/skia/modules/svg/include/SkSVGRenderContext.h
Line | Count | Source (jump to first uncovered line) |
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) |
29 | 20.4k | : fViewport(viewport), fDPI(dpi) {} |
30 | | |
31 | | enum class LengthType { |
32 | | kHorizontal, |
33 | | kVertical, |
34 | | kOther, |
35 | | }; |
36 | | |
37 | 25.7k | const SkSize& viewPort() const { return fViewport; } |
38 | 1.71k | 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 | 45.2k | SkSVGPresentationContext(const SkSVGPresentationContext&) = default; |
52 | 0 | 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 | | |
76 | 180k | const SkSVGLengthContext& lengthContext() const { return *fLengthContext; } |
77 | 1.71k | SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); } |
78 | | |
79 | 925k | const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; } |
80 | | |
81 | 462k | 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: |
92 | | explicit BorrowedNode(sk_sp<SkSVGNode>* node) |
93 | 11.3k | : fOwner(node) { |
94 | 11.3k | if (fOwner) { |
95 | 10.0k | fBorrowed = std::move(*fOwner); |
96 | 10.0k | *fOwner = nullptr; |
97 | 10.0k | } |
98 | 11.3k | } |
99 | | |
100 | 11.3k | ~BorrowedNode() { |
101 | 11.3k | if (fOwner) { |
102 | 10.0k | *fOwner = std::move(fBorrowed); |
103 | 10.0k | } |
104 | 11.3k | } |
105 | | |
106 | 9.96k | const SkSVGNode* get() const { return fBorrowed.get(); } |
107 | 10.0k | const SkSVGNode* operator->() const { return fBorrowed.get(); } |
108 | 0 | const SkSVGNode& operator*() const { return *fBorrowed; } |
109 | | |
110 | 11.3k | 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). |
131 | 256k | const SkPath* clipPath() const { return fClipPath.getMaybeNull(); } |
132 | | |
133 | 0 | const sk_sp<skresources::ResourceProvider>& resourceProvider() const { |
134 | 0 | return fResourceProvider; |
135 | 0 | } |
136 | | |
137 | 37.1k | sk_sp<SkFontMgr> fontMgr() const { |
138 | 37.1k | return fFontMgr ? fFontMgr : SkFontMgr::RefDefault(); |
139 | 37.1k | } |
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 |