blob: bc7a7e68f1a8625ce37b352af93d2ff22766872e [file] [log] [blame]
Florin Malitab3418102020-10-15 18:10:29 -04001/*
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
Florin Malita7006e152020-11-10 15:24:59 -050011#include "include/core/SkFontMgr.h"
Florin Malita3010f3d2021-04-30 10:48:42 -040012#include "include/core/SkM44.h"
Florin Malitab3418102020-10-15 18:10:29 -040013#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"
Florin Malita24df67d2021-01-26 18:45:34 -050018#include "modules/skresources/include/SkResources.h"
Florin Malitab3418102020-10-15 18:10:29 -040019#include "modules/svg/include/SkSVGAttribute.h"
20#include "modules/svg/include/SkSVGIDMapper.h"
21#include "src/core/SkTLazy.h"
22
23class SkCanvas;
24class SkSVGLength;
25
26class SkSVGLengthContext {
27public:
28 SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
29 : fViewport(viewport), fDPI(dpi) {}
30
31 enum class LengthType {
32 kHorizontal,
33 kVertical,
34 kOther,
35 };
36
37 const SkSize& viewPort() const { return fViewport; }
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
44private:
45 SkSize fViewport;
46 SkScalar fDPI;
47};
48
49struct 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;
Florin Malitab3418102020-10-15 18:10:29 -040056};
57
58class SkSVGRenderContext {
59public:
Florin Malita48fb05b2021-04-30 14:22:33 -040060 // Captures data required for object bounding box resolution.
61 struct OBBScope {
62 const SkSVGNode* fNode;
63 const SkSVGRenderContext* fCtx;
64 };
65
Florin Malita24df67d2021-01-26 18:45:34 -050066 SkSVGRenderContext(SkCanvas*, const sk_sp<SkFontMgr>&,
67 const sk_sp<skresources::ResourceProvider>&, const SkSVGIDMapper&,
Florin Malita7006e152020-11-10 15:24:59 -050068 const SkSVGLengthContext&, const SkSVGPresentationContext&,
Florin Malita48fb05b2021-04-30 14:22:33 -040069 const OBBScope&);
Florin Malitab3418102020-10-15 18:10:29 -040070 SkSVGRenderContext(const SkSVGRenderContext&);
71 SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
Florin Malita48fb05b2021-04-30 14:22:33 -040072 // Establish a new OBB scope. Normally used when entering a node's render scope.
Tyler Denniston53281c72020-10-22 15:54:24 -040073 SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
Florin Malitab3418102020-10-15 18:10:29 -040074 ~SkSVGRenderContext();
75
76 const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
77 SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
78
79 const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
80
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:
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 ~BorrowedNode() {
101 if (fOwner) {
102 *fOwner = std::move(fBorrowed);
103 }
104 }
105
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).
Tyler Dennistone71f5472021-01-27 13:30:59 -0500123 BorrowedNode findNodeById(const SkSVGIRI&) const;
Florin Malitab3418102020-10-15 18:10:29 -0400124
Florin Malitabde06cc2021-01-19 10:12:37 -0500125 SkTLazy<SkPaint> fillPaint() const;
126 SkTLazy<SkPaint> strokePaint() const;
Florin Malitab3418102020-10-15 18:10:29 -0400127
Tyler Dennistonb2d1a3b2020-12-11 10:31:07 -0500128 SkSVGColorType resolveSvgColor(const SkSVGColor&) const;
129
Florin Malitab3418102020-10-15 18:10:29 -0400130 // The local computed clip path (not inherited).
131 const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
132
Tyler Denniston8ca46262021-02-02 16:16:21 -0500133 const sk_sp<skresources::ResourceProvider>& resourceProvider() const {
134 return fResourceProvider;
135 }
136
Florin Malita7006e152020-11-10 15:24:59 -0500137 sk_sp<SkFontMgr> fontMgr() const {
138 return fFontMgr ? fFontMgr : SkFontMgr::RefDefault();
139 }
140
Florin Malita3010f3d2021-04-30 10:48:42 -0400141 // 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
Florin Malita49191102021-01-14 11:58:09 -0500148 SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y,
149 const SkSVGLength& w, const SkSVGLength& h,
150 SkSVGObjectBoundingBoxUnits) const;
151
Florin Malitab3418102020-10-15 18:10:29 -0400152private:
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
Tyler Dennistona22d21e2021-01-15 12:12:35 -0500158 void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
Florin Malita836c2ca2021-01-13 11:48:02 -0500159 void applyFilter(const SkSVGFuncIRI&);
160 void applyClip(const SkSVGFuncIRI&);
Florin Malita49191102021-01-14 11:58:09 -0500161 void applyMask(const SkSVGFuncIRI&);
Florin Malitabde06cc2021-01-19 10:12:37 -0500162
163 SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
Florin Malitab3418102020-10-15 18:10:29 -0400164
Florin Malita7006e152020-11-10 15:24:59 -0500165 const sk_sp<SkFontMgr>& fFontMgr;
Florin Malita24df67d2021-01-26 18:45:34 -0500166 const sk_sp<skresources::ResourceProvider>& fResourceProvider;
Florin Malitab3418102020-10-15 18:10:29 -0400167 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;
Tyler Denniston53281c72020-10-22 15:54:24 -0400177
Florin Malitabde06cc2021-01-19 10:12:37 -0500178 // Deferred opacity optimization for leaf nodes.
179 float fDeferredPaintOpacity = 1;
180
Florin Malita48fb05b2021-04-30 14:22:33 -0400181 // Current object bounding box scope.
182 const OBBScope fOBBScope;
Florin Malitab3418102020-10-15 18:10:29 -0400183};
184
185#endif // SkSVGRenderContext_DEFINED