blob: 5be4e37eba5e0064e7c6c6f0719647bb2c05b05a [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 Malitab3418102020-10-15 18:10:29 -040012#include "include/core/SkPaint.h"
13#include "include/core/SkPath.h"
14#include "include/core/SkRect.h"
15#include "include/core/SkSize.h"
16#include "include/core/SkTypes.h"
17#include "modules/svg/include/SkSVGAttribute.h"
18#include "modules/svg/include/SkSVGIDMapper.h"
19#include "src/core/SkTLazy.h"
20
21class SkCanvas;
22class SkSVGLength;
23
24class SkSVGLengthContext {
25public:
26 SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
27 : fViewport(viewport), fDPI(dpi) {}
28
29 enum class LengthType {
30 kHorizontal,
31 kVertical,
32 kOther,
33 };
34
35 const SkSize& viewPort() const { return fViewport; }
36 void setViewPort(const SkSize& viewport) { fViewport = viewport; }
37
38 SkScalar resolve(const SkSVGLength&, LengthType) const;
39 SkRect resolveRect(const SkSVGLength& x, const SkSVGLength& y,
40 const SkSVGLength& w, const SkSVGLength& h) const;
41
42private:
43 SkSize fViewport;
44 SkScalar fDPI;
45};
46
47struct SkSVGPresentationContext {
48 SkSVGPresentationContext();
49 SkSVGPresentationContext(const SkSVGPresentationContext&) = default;
50 SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
51
52 // Inherited presentation attributes, computed for the current node.
53 SkSVGPresentationAttributes fInherited;
Florin Malitab3418102020-10-15 18:10:29 -040054};
55
56class SkSVGRenderContext {
57public:
Florin Malita7006e152020-11-10 15:24:59 -050058 SkSVGRenderContext(SkCanvas*, const sk_sp<SkFontMgr>&, const SkSVGIDMapper&,
59 const SkSVGLengthContext&, const SkSVGPresentationContext&,
Florin Malitaadc68892020-12-15 10:52:26 -050060 const SkSVGNode*);
Florin Malitab3418102020-10-15 18:10:29 -040061 SkSVGRenderContext(const SkSVGRenderContext&);
62 SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
Tyler Denniston53281c72020-10-22 15:54:24 -040063 SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
Florin Malitab3418102020-10-15 18:10:29 -040064 ~SkSVGRenderContext();
65
66 const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
67 SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
68
69 const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
70
71 SkCanvas* canvas() const { return fCanvas; }
72 void saveOnce();
73
74 enum ApplyFlags {
75 kLeaf = 1 << 0, // the target node doesn't have descendants
76 };
77 void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
78
79 // Scoped wrapper that temporarily clears the original node reference.
80 class BorrowedNode {
81 public:
82 explicit BorrowedNode(sk_sp<SkSVGNode>* node)
83 : fOwner(node) {
84 if (fOwner) {
85 fBorrowed = std::move(*fOwner);
86 *fOwner = nullptr;
87 }
88 }
89
90 ~BorrowedNode() {
91 if (fOwner) {
92 *fOwner = std::move(fBorrowed);
93 }
94 }
95
96 const SkSVGNode* get() const { return fBorrowed.get(); }
97 const SkSVGNode* operator->() const { return fBorrowed.get(); }
98 const SkSVGNode& operator*() const { return *fBorrowed; }
99
100 operator bool() const { return !!fBorrowed; }
101
102 private:
103 // noncopyable
104 BorrowedNode(const BorrowedNode&) = delete;
105 BorrowedNode& operator=(BorrowedNode&) = delete;
106
107 sk_sp<SkSVGNode>* fOwner;
108 sk_sp<SkSVGNode> fBorrowed;
109 };
110
111 // Note: the id->node association is cleared for the lifetime of the returned value
112 // (effectively breaks reference cycles, assuming appropriate return value scoping).
113 BorrowedNode findNodeById(const SkString&) const;
114
Florin Malitabde06cc2021-01-19 10:12:37 -0500115 SkTLazy<SkPaint> fillPaint() const;
116 SkTLazy<SkPaint> strokePaint() const;
Florin Malitab3418102020-10-15 18:10:29 -0400117
Tyler Dennistonb2d1a3b2020-12-11 10:31:07 -0500118 SkSVGColorType resolveSvgColor(const SkSVGColor&) const;
119
Florin Malitab3418102020-10-15 18:10:29 -0400120 // The local computed clip path (not inherited).
121 const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
122
Tyler Denniston53281c72020-10-22 15:54:24 -0400123 // The node being rendered (may be null).
124 const SkSVGNode* node() const { return fNode; }
125
Florin Malita7006e152020-11-10 15:24:59 -0500126 sk_sp<SkFontMgr> fontMgr() const {
127 return fFontMgr ? fFontMgr : SkFontMgr::RefDefault();
128 }
129
Florin Malita49191102021-01-14 11:58:09 -0500130 SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y,
131 const SkSVGLength& w, const SkSVGLength& h,
132 SkSVGObjectBoundingBoxUnits) const;
133
Florin Malitab3418102020-10-15 18:10:29 -0400134private:
135 // Stack-only
136 void* operator new(size_t) = delete;
137 void* operator new(size_t, void*) = delete;
138 SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
139
Tyler Dennistona22d21e2021-01-15 12:12:35 -0500140 void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
Florin Malita836c2ca2021-01-13 11:48:02 -0500141 void applyFilter(const SkSVGFuncIRI&);
142 void applyClip(const SkSVGFuncIRI&);
Florin Malita49191102021-01-14 11:58:09 -0500143 void applyMask(const SkSVGFuncIRI&);
Florin Malitabde06cc2021-01-19 10:12:37 -0500144
145 SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
Florin Malitab3418102020-10-15 18:10:29 -0400146
Florin Malita7006e152020-11-10 15:24:59 -0500147 const sk_sp<SkFontMgr>& fFontMgr;
Florin Malitab3418102020-10-15 18:10:29 -0400148 const SkSVGIDMapper& fIDMapper;
149 SkTCopyOnFirstWrite<SkSVGLengthContext> fLengthContext;
150 SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
151 SkCanvas* fCanvas;
152 // The save count on 'fCanvas' at construction time.
153 // A restoreToCount() will be issued on destruction.
154 int fCanvasSaveCount;
155
156 // clipPath, if present for the current context (not inherited).
157 SkTLazy<SkPath> fClipPath;
Tyler Denniston53281c72020-10-22 15:54:24 -0400158
Florin Malitabde06cc2021-01-19 10:12:37 -0500159 // Deferred opacity optimization for leaf nodes.
160 float fDeferredPaintOpacity = 1;
161
Tyler Denniston53281c72020-10-22 15:54:24 -0400162 const SkSVGNode* fNode;
Florin Malitab3418102020-10-15 18:10:29 -0400163};
164
165#endif // SkSVGRenderContext_DEFINED