• 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/skshaper/include/SkShaper.h"
20 #include "modules/skshaper/include/SkShaper_factory.h"
21 #include "modules/svg/include/SkSVGAttribute.h"
22 #include "modules/svg/include/SkSVGIDMapper.h"
23 #include "src/base/SkTLazy.h"
24 #include "src/core/SkTHash.h"
25 
26 class SkCanvas;
27 class SkSVGLength;
28 
29 class SK_API SkSVGLengthContext {
30 public:
31     SkSVGLengthContext(const SkSize& viewport, SkScalar dpi = 90)
fViewport(viewport)32         : fViewport(viewport), fDPI(dpi) {}
33 
34     enum class LengthType {
35         kHorizontal,
36         kVertical,
37         kOther,
38     };
39 
viewPort()40     const SkSize& viewPort() const { return fViewport; }
setViewPort(const SkSize & viewport)41     void setViewPort(const SkSize& viewport) { fViewport = viewport; }
42 
43     SkScalar resolve(const SkSVGLength&, LengthType) const;
44     SkRect   resolveRect(const SkSVGLength& x, const SkSVGLength& y,
45                          const SkSVGLength& w, const SkSVGLength& h) const;
46 
47 private:
48     SkSize   fViewport;
49     SkScalar fDPI;
50 };
51 
52 struct SK_API SkSVGPresentationContext {
53     SkSVGPresentationContext();
54     SkSVGPresentationContext(const SkSVGPresentationContext&)            = default;
55     SkSVGPresentationContext& operator=(const SkSVGPresentationContext&) = default;
56 
57     const skia_private::THashMap<SkString, SkSVGColorType>* fNamedColors = nullptr;
58 
59     // Inherited presentation attributes, computed for the current node.
60     SkSVGPresentationAttributes fInherited;
61 };
62 
63 class SK_API SkSVGRenderContext {
64 public:
65     // Captures data required for object bounding box resolution.
66     struct OBBScope {
67         const SkSVGNode*          fNode;
68         const SkSVGRenderContext* fCtx;
69     };
70 
71     SkSVGRenderContext(SkCanvas*,
72                        const sk_sp<SkFontMgr>&,
73                        const sk_sp<skresources::ResourceProvider>&,
74                        const SkSVGIDMapper&,
75                        const SkSVGLengthContext&,
76                        const SkSVGPresentationContext&,
77                        const OBBScope&,
78                        const sk_sp<SkShapers::Factory>&);
79     SkSVGRenderContext(const SkSVGRenderContext&);
80     SkSVGRenderContext(const SkSVGRenderContext&, SkCanvas*);
81     // Establish a new OBB scope.  Normally used when entering a node's render scope.
82     SkSVGRenderContext(const SkSVGRenderContext&, const SkSVGNode*);
83     ~SkSVGRenderContext();
84 
lengthContext()85     const SkSVGLengthContext& lengthContext() const { return *fLengthContext; }
writableLengthContext()86     SkSVGLengthContext* writableLengthContext() { return fLengthContext.writable(); }
87 
presentationContext()88     const SkSVGPresentationContext& presentationContext() const { return *fPresentationContext; }
89 
canvas()90     SkCanvas* canvas() const { return fCanvas; }
91     void saveOnce();
92 
93     enum ApplyFlags {
94         kLeaf = 1 << 0, // the target node doesn't have descendants
95     };
96     void applyPresentationAttributes(const SkSVGPresentationAttributes&, uint32_t flags);
97 
98     // Scoped wrapper that temporarily clears the original node reference.
99     class BorrowedNode {
100     public:
BorrowedNode(sk_sp<SkSVGNode> * node)101         explicit BorrowedNode(sk_sp<SkSVGNode>* node)
102             : fOwner(node) {
103             if (fOwner) {
104                 fBorrowed = std::move(*fOwner);
105                 *fOwner = nullptr;
106             }
107         }
108 
~BorrowedNode()109         ~BorrowedNode() {
110             if (fOwner) {
111                 *fOwner = std::move(fBorrowed);
112             }
113         }
114 
get()115         const SkSVGNode* get() const { return fBorrowed.get(); }
116         const SkSVGNode* operator->() const { return fBorrowed.get(); }
117         const SkSVGNode& operator*() const { return *fBorrowed; }
118 
119         explicit operator bool() const { return !!fBorrowed; }
120 
121     private:
122         // noncopyable
123         BorrowedNode(const BorrowedNode&)      = delete;
124         BorrowedNode& operator=(BorrowedNode&) = delete;
125 
126         sk_sp<SkSVGNode>* fOwner;
127         sk_sp<SkSVGNode>  fBorrowed;
128     };
129 
130     // Note: the id->node association is cleared for the lifetime of the returned value
131     // (effectively breaks reference cycles, assuming appropriate return value scoping).
132     BorrowedNode findNodeById(const SkSVGIRI&) const;
133 
134     SkTLazy<SkPaint> fillPaint() const;
135     SkTLazy<SkPaint> strokePaint() const;
136 
137     SkSVGColorType resolveSvgColor(const SkSVGColor&) const;
138 
139     // The local computed clip path (not inherited).
clipPath()140     const SkPath* clipPath() const { return fClipPath.getMaybeNull(); }
141 
resourceProvider()142     const sk_sp<skresources::ResourceProvider>& resourceProvider() const {
143         return fResourceProvider;
144     }
145 
fontMgr()146     sk_sp<SkFontMgr> fontMgr() const {
147         // It is probably an oversight to try to render <text> without having set the SkFontMgr.
148         // We will assert this in debug mode, but fallback to an empty fontmgr in release builds.
149         SkASSERT(fFontMgr);
150         return fFontMgr ? fFontMgr : SkFontMgr::RefEmpty();
151     }
152 
153     // Returns the translate/scale transformation required to map into the current OBB scope,
154     // with the specified units.
155     struct OBBTransform {
156         SkV2 offset, scale;
157     };
158     OBBTransform transformForCurrentOBB(SkSVGObjectBoundingBoxUnits) const;
159 
160     SkRect resolveOBBRect(const SkSVGLength& x, const SkSVGLength& y,
161                           const SkSVGLength& w, const SkSVGLength& h,
162                           SkSVGObjectBoundingBoxUnits) const;
163 
makeShaper()164     std::unique_ptr<SkShaper> makeShaper() const {
165         SkASSERT(fTextShapingFactory);
166         return fTextShapingFactory->makeShaper(this->fontMgr());
167     }
168 
makeBidiRunIterator(const char * utf8,size_t utf8Bytes,uint8_t bidiLevel)169     std::unique_ptr<SkShaper::BiDiRunIterator> makeBidiRunIterator(const char* utf8,
170                                                                    size_t utf8Bytes,
171                                                                    uint8_t bidiLevel) const {
172         SkASSERT(fTextShapingFactory);
173         return fTextShapingFactory->makeBidiRunIterator(utf8, utf8Bytes, bidiLevel);
174     }
175 
makeScriptRunIterator(const char * utf8,size_t utf8Bytes)176     std::unique_ptr<SkShaper::ScriptRunIterator> makeScriptRunIterator(const char* utf8,
177                                                                        size_t utf8Bytes) const {
178         SkASSERT(fTextShapingFactory);
179         constexpr SkFourByteTag unknownScript = SkSetFourByteTag('Z', 'z', 'z', 'z');
180         return fTextShapingFactory->makeScriptRunIterator(utf8, utf8Bytes, unknownScript);
181     }
182 
183 private:
184     // Stack-only
185     void* operator new(size_t)                               = delete;
186     void* operator new(size_t, void*)                        = delete;
187     SkSVGRenderContext& operator=(const SkSVGRenderContext&) = delete;
188 
189     void applyOpacity(SkScalar opacity, uint32_t flags, bool hasFilter);
190     void applyFilter(const SkSVGFuncIRI&);
191     void applyClip(const SkSVGFuncIRI&);
192     void applyMask(const SkSVGFuncIRI&);
193 
194     SkTLazy<SkPaint> commonPaint(const SkSVGPaint&, float opacity) const;
195 
196     const sk_sp<SkFontMgr>&                       fFontMgr;
197     const sk_sp<SkShapers::Factory>&              fTextShapingFactory;
198     const sk_sp<skresources::ResourceProvider>&   fResourceProvider;
199     const SkSVGIDMapper&                          fIDMapper;
200     SkTCopyOnFirstWrite<SkSVGLengthContext>       fLengthContext;
201     SkTCopyOnFirstWrite<SkSVGPresentationContext> fPresentationContext;
202     SkCanvas*                                     fCanvas;
203     // The save count on 'fCanvas' at construction time.
204     // A restoreToCount() will be issued on destruction.
205     int                                           fCanvasSaveCount;
206 
207     // clipPath, if present for the current context (not inherited).
208     SkTLazy<SkPath>                               fClipPath;
209 
210     // Deferred opacity optimization for leaf nodes.
211     float                                         fDeferredPaintOpacity = 1;
212 
213     // Current object bounding box scope.
214     const OBBScope                                fOBBScope;
215 };
216 
217 #endif // SkSVGRenderContext_DEFINED
218