1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGDOM.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper_factory.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGAttribute.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGAttributeParser.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGCircle.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGClipPath.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGDefs.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGEllipse.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeBlend.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeColorMatrix.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeComponentTransfer.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeComposite.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeDisplacementMap.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeFlood.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeGaussianBlur.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeImage.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeLightSource.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeLighting.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeMerge.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeMorphology.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeOffset.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFeTurbulence.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGFilter.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGG.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGImage.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGLine.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGLinearGradient.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGMask.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGNode.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGPath.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGPattern.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGPoly.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGRadialGradient.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGRect.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGRenderContext.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGSVG.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGStop.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGText.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGTypes.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGUse.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGValue.h"
55*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTSearch.h"
56*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
57*c8dee2aaSAndroid Build Coastguard Worker #include "src/xml/SkDOM.h"
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker #include <stdint.h>
60*c8dee2aaSAndroid Build Coastguard Worker #include <array>
61*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
62*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
63*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker namespace {
66*c8dee2aaSAndroid Build Coastguard Worker
SetIRIAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)67*c8dee2aaSAndroid Build Coastguard Worker bool SetIRIAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
68*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
69*c8dee2aaSAndroid Build Coastguard Worker auto parseResult = SkSVGAttributeParser::parse<SkSVGIRI>(stringValue);
70*c8dee2aaSAndroid Build Coastguard Worker if (!parseResult.isValid()) {
71*c8dee2aaSAndroid Build Coastguard Worker return false;
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGStringValue(parseResult->iri()));
75*c8dee2aaSAndroid Build Coastguard Worker return true;
76*c8dee2aaSAndroid Build Coastguard Worker }
77*c8dee2aaSAndroid Build Coastguard Worker
SetStringAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)78*c8dee2aaSAndroid Build Coastguard Worker bool SetStringAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
79*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
80*c8dee2aaSAndroid Build Coastguard Worker SkString str(stringValue, strlen(stringValue));
81*c8dee2aaSAndroid Build Coastguard Worker SkSVGStringType strType = SkSVGStringType(str);
82*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGStringValue(strType));
83*c8dee2aaSAndroid Build Coastguard Worker return true;
84*c8dee2aaSAndroid Build Coastguard Worker }
85*c8dee2aaSAndroid Build Coastguard Worker
SetTransformAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)86*c8dee2aaSAndroid Build Coastguard Worker bool SetTransformAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
87*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
88*c8dee2aaSAndroid Build Coastguard Worker auto parseResult = SkSVGAttributeParser::parse<SkSVGTransformType>(stringValue);
89*c8dee2aaSAndroid Build Coastguard Worker if (!parseResult.isValid()) {
90*c8dee2aaSAndroid Build Coastguard Worker return false;
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker
93*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGTransformValue(*parseResult));
94*c8dee2aaSAndroid Build Coastguard Worker return true;
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker
SetLengthAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)97*c8dee2aaSAndroid Build Coastguard Worker bool SetLengthAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
98*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
99*c8dee2aaSAndroid Build Coastguard Worker auto parseResult = SkSVGAttributeParser::parse<SkSVGLength>(stringValue);
100*c8dee2aaSAndroid Build Coastguard Worker if (!parseResult.isValid()) {
101*c8dee2aaSAndroid Build Coastguard Worker return false;
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGLengthValue(*parseResult));
105*c8dee2aaSAndroid Build Coastguard Worker return true;
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker
SetViewBoxAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)108*c8dee2aaSAndroid Build Coastguard Worker bool SetViewBoxAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
109*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
110*c8dee2aaSAndroid Build Coastguard Worker SkSVGViewBoxType viewBox;
111*c8dee2aaSAndroid Build Coastguard Worker SkSVGAttributeParser parser(stringValue);
112*c8dee2aaSAndroid Build Coastguard Worker if (!parser.parseViewBox(&viewBox)) {
113*c8dee2aaSAndroid Build Coastguard Worker return false;
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGViewBoxValue(viewBox));
117*c8dee2aaSAndroid Build Coastguard Worker return true;
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker
SetObjectBoundingBoxUnitsAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)120*c8dee2aaSAndroid Build Coastguard Worker bool SetObjectBoundingBoxUnitsAttribute(const sk_sp<SkSVGNode>& node,
121*c8dee2aaSAndroid Build Coastguard Worker SkSVGAttribute attr,
122*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
123*c8dee2aaSAndroid Build Coastguard Worker auto parseResult = SkSVGAttributeParser::parse<SkSVGObjectBoundingBoxUnits>(stringValue);
124*c8dee2aaSAndroid Build Coastguard Worker if (!parseResult.isValid()) {
125*c8dee2aaSAndroid Build Coastguard Worker return false;
126*c8dee2aaSAndroid Build Coastguard Worker }
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGObjectBoundingBoxUnitsValue(*parseResult));
129*c8dee2aaSAndroid Build Coastguard Worker return true;
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker
SetPreserveAspectRatioAttribute(const sk_sp<SkSVGNode> & node,SkSVGAttribute attr,const char * stringValue)132*c8dee2aaSAndroid Build Coastguard Worker bool SetPreserveAspectRatioAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
133*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
134*c8dee2aaSAndroid Build Coastguard Worker SkSVGPreserveAspectRatio par;
135*c8dee2aaSAndroid Build Coastguard Worker SkSVGAttributeParser parser(stringValue);
136*c8dee2aaSAndroid Build Coastguard Worker if (!parser.parsePreserveAspectRatio(&par)) {
137*c8dee2aaSAndroid Build Coastguard Worker return false;
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker node->setAttribute(attr, SkSVGPreserveAspectRatioValue(par));
141*c8dee2aaSAndroid Build Coastguard Worker return true;
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker
TrimmedString(const char * first,const char * last)144*c8dee2aaSAndroid Build Coastguard Worker SkString TrimmedString(const char* first, const char* last) {
145*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(first);
146*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(last);
147*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(first <= last);
148*c8dee2aaSAndroid Build Coastguard Worker
149*c8dee2aaSAndroid Build Coastguard Worker while (first <= last && *first <= ' ') { first++; }
150*c8dee2aaSAndroid Build Coastguard Worker while (first <= last && *last <= ' ') { last--; }
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(last - first + 1 >= 0);
153*c8dee2aaSAndroid Build Coastguard Worker return SkString(first, SkTo<size_t>(last - first + 1));
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker // Breaks a "foo: bar; baz: ..." string into key:value pairs.
157*c8dee2aaSAndroid Build Coastguard Worker class StyleIterator {
158*c8dee2aaSAndroid Build Coastguard Worker public:
StyleIterator(const char * str)159*c8dee2aaSAndroid Build Coastguard Worker StyleIterator(const char* str) : fPos(str) { }
160*c8dee2aaSAndroid Build Coastguard Worker
next()161*c8dee2aaSAndroid Build Coastguard Worker std::tuple<SkString, SkString> next() {
162*c8dee2aaSAndroid Build Coastguard Worker SkString name, value;
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker if (fPos) {
165*c8dee2aaSAndroid Build Coastguard Worker const char* sep = this->nextSeparator();
166*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(*sep == ';' || *sep == '\0');
167*c8dee2aaSAndroid Build Coastguard Worker
168*c8dee2aaSAndroid Build Coastguard Worker const char* valueSep = strchr(fPos, ':');
169*c8dee2aaSAndroid Build Coastguard Worker if (valueSep && valueSep < sep) {
170*c8dee2aaSAndroid Build Coastguard Worker name = TrimmedString(fPos, valueSep - 1);
171*c8dee2aaSAndroid Build Coastguard Worker value = TrimmedString(valueSep + 1, sep - 1);
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker fPos = *sep ? sep + 1 : nullptr;
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker return std::make_tuple(name, value);
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker private:
nextSeparator() const181*c8dee2aaSAndroid Build Coastguard Worker const char* nextSeparator() const {
182*c8dee2aaSAndroid Build Coastguard Worker const char* sep = fPos;
183*c8dee2aaSAndroid Build Coastguard Worker while (*sep != ';' && *sep != '\0') {
184*c8dee2aaSAndroid Build Coastguard Worker sep++;
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker return sep;
187*c8dee2aaSAndroid Build Coastguard Worker }
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker const char* fPos;
190*c8dee2aaSAndroid Build Coastguard Worker };
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker bool set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value);
193*c8dee2aaSAndroid Build Coastguard Worker
SetStyleAttributes(const sk_sp<SkSVGNode> & node,SkSVGAttribute,const char * stringValue)194*c8dee2aaSAndroid Build Coastguard Worker bool SetStyleAttributes(const sk_sp<SkSVGNode>& node, SkSVGAttribute,
195*c8dee2aaSAndroid Build Coastguard Worker const char* stringValue) {
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker SkString name, value;
198*c8dee2aaSAndroid Build Coastguard Worker StyleIterator iter(stringValue);
199*c8dee2aaSAndroid Build Coastguard Worker for (;;) {
200*c8dee2aaSAndroid Build Coastguard Worker std::tie(name, value) = iter.next();
201*c8dee2aaSAndroid Build Coastguard Worker if (name.isEmpty()) {
202*c8dee2aaSAndroid Build Coastguard Worker break;
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker set_string_attribute(node, name.c_str(), value.c_str());
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker return true;
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker template<typename T>
211*c8dee2aaSAndroid Build Coastguard Worker struct SortedDictionaryEntry {
212*c8dee2aaSAndroid Build Coastguard Worker const char* fKey;
213*c8dee2aaSAndroid Build Coastguard Worker const T fValue;
214*c8dee2aaSAndroid Build Coastguard Worker };
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker struct AttrParseInfo {
217*c8dee2aaSAndroid Build Coastguard Worker SkSVGAttribute fAttr;
218*c8dee2aaSAndroid Build Coastguard Worker bool (*fSetter)(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, const char* stringValue);
219*c8dee2aaSAndroid Build Coastguard Worker };
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
222*c8dee2aaSAndroid Build Coastguard Worker { "cx" , { SkSVGAttribute::kCx , SetLengthAttribute }},
223*c8dee2aaSAndroid Build Coastguard Worker { "cy" , { SkSVGAttribute::kCy , SetLengthAttribute }},
224*c8dee2aaSAndroid Build Coastguard Worker { "filterUnits" , { SkSVGAttribute::kFilterUnits ,
225*c8dee2aaSAndroid Build Coastguard Worker SetObjectBoundingBoxUnitsAttribute }},
226*c8dee2aaSAndroid Build Coastguard Worker // focal point x & y
227*c8dee2aaSAndroid Build Coastguard Worker { "fx" , { SkSVGAttribute::kFx , SetLengthAttribute }},
228*c8dee2aaSAndroid Build Coastguard Worker { "fy" , { SkSVGAttribute::kFy , SetLengthAttribute }},
229*c8dee2aaSAndroid Build Coastguard Worker { "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }},
230*c8dee2aaSAndroid Build Coastguard Worker { "preserveAspectRatio", { SkSVGAttribute::kPreserveAspectRatio,
231*c8dee2aaSAndroid Build Coastguard Worker SetPreserveAspectRatioAttribute }},
232*c8dee2aaSAndroid Build Coastguard Worker { "r" , { SkSVGAttribute::kR , SetLengthAttribute }},
233*c8dee2aaSAndroid Build Coastguard Worker { "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
234*c8dee2aaSAndroid Build Coastguard Worker { "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
235*c8dee2aaSAndroid Build Coastguard Worker { "style" , { SkSVGAttribute::kUnknown , SetStyleAttributes }},
236*c8dee2aaSAndroid Build Coastguard Worker { "text" , { SkSVGAttribute::kText , SetStringAttribute }},
237*c8dee2aaSAndroid Build Coastguard Worker { "transform" , { SkSVGAttribute::kTransform , SetTransformAttribute }},
238*c8dee2aaSAndroid Build Coastguard Worker { "viewBox" , { SkSVGAttribute::kViewBox , SetViewBoxAttribute }},
239*c8dee2aaSAndroid Build Coastguard Worker { "width" , { SkSVGAttribute::kWidth , SetLengthAttribute }},
240*c8dee2aaSAndroid Build Coastguard Worker { "x" , { SkSVGAttribute::kX , SetLengthAttribute }},
241*c8dee2aaSAndroid Build Coastguard Worker { "x1" , { SkSVGAttribute::kX1 , SetLengthAttribute }},
242*c8dee2aaSAndroid Build Coastguard Worker { "x2" , { SkSVGAttribute::kX2 , SetLengthAttribute }},
243*c8dee2aaSAndroid Build Coastguard Worker { "xlink:href" , { SkSVGAttribute::kHref , SetIRIAttribute }},
244*c8dee2aaSAndroid Build Coastguard Worker { "y" , { SkSVGAttribute::kY , SetLengthAttribute }},
245*c8dee2aaSAndroid Build Coastguard Worker { "y1" , { SkSVGAttribute::kY1 , SetLengthAttribute }},
246*c8dee2aaSAndroid Build Coastguard Worker { "y2" , { SkSVGAttribute::kY2 , SetLengthAttribute }},
247*c8dee2aaSAndroid Build Coastguard Worker };
248*c8dee2aaSAndroid Build Coastguard Worker
249*c8dee2aaSAndroid Build Coastguard Worker SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = {
__anonfb798c1b0202() 250*c8dee2aaSAndroid Build Coastguard Worker { "a" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
__anonfb798c1b0302() 251*c8dee2aaSAndroid Build Coastguard Worker { "circle" , []() -> sk_sp<SkSVGNode> { return SkSVGCircle::Make(); }},
__anonfb798c1b0402() 252*c8dee2aaSAndroid Build Coastguard Worker { "clipPath" , []() -> sk_sp<SkSVGNode> { return SkSVGClipPath::Make(); }},
__anonfb798c1b0502() 253*c8dee2aaSAndroid Build Coastguard Worker { "defs" , []() -> sk_sp<SkSVGNode> { return SkSVGDefs::Make(); }},
__anonfb798c1b0602() 254*c8dee2aaSAndroid Build Coastguard Worker { "ellipse" , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make(); }},
__anonfb798c1b0702() 255*c8dee2aaSAndroid Build Coastguard Worker { "feBlend" , []() -> sk_sp<SkSVGNode> { return SkSVGFeBlend::Make(); }},
__anonfb798c1b0802() 256*c8dee2aaSAndroid Build Coastguard Worker { "feColorMatrix" , []() -> sk_sp<SkSVGNode> { return SkSVGFeColorMatrix::Make(); }},
__anonfb798c1b0902() 257*c8dee2aaSAndroid Build Coastguard Worker { "feComponentTransfer", []() -> sk_sp<SkSVGNode> { return SkSVGFeComponentTransfer::Make(); }},
__anonfb798c1b0a02() 258*c8dee2aaSAndroid Build Coastguard Worker { "feComposite" , []() -> sk_sp<SkSVGNode> { return SkSVGFeComposite::Make(); }},
__anonfb798c1b0b02() 259*c8dee2aaSAndroid Build Coastguard Worker { "feDiffuseLighting" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDiffuseLighting::Make(); }},
__anonfb798c1b0c02() 260*c8dee2aaSAndroid Build Coastguard Worker { "feDisplacementMap" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDisplacementMap::Make(); }},
__anonfb798c1b0d02() 261*c8dee2aaSAndroid Build Coastguard Worker { "feDistantLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDistantLight::Make(); }},
__anonfb798c1b0e02() 262*c8dee2aaSAndroid Build Coastguard Worker { "feFlood" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFlood::Make(); }},
__anonfb798c1b0f02() 263*c8dee2aaSAndroid Build Coastguard Worker { "feFuncA" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncA(); }},
__anonfb798c1b1002() 264*c8dee2aaSAndroid Build Coastguard Worker { "feFuncB" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncB(); }},
__anonfb798c1b1102() 265*c8dee2aaSAndroid Build Coastguard Worker { "feFuncG" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncG(); }},
__anonfb798c1b1202() 266*c8dee2aaSAndroid Build Coastguard Worker { "feFuncR" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncR(); }},
__anonfb798c1b1302() 267*c8dee2aaSAndroid Build Coastguard Worker { "feGaussianBlur" , []() -> sk_sp<SkSVGNode> { return SkSVGFeGaussianBlur::Make(); }},
__anonfb798c1b1402() 268*c8dee2aaSAndroid Build Coastguard Worker { "feImage" , []() -> sk_sp<SkSVGNode> { return SkSVGFeImage::Make(); }},
__anonfb798c1b1502() 269*c8dee2aaSAndroid Build Coastguard Worker { "feMerge" , []() -> sk_sp<SkSVGNode> { return SkSVGFeMerge::Make(); }},
__anonfb798c1b1602() 270*c8dee2aaSAndroid Build Coastguard Worker { "feMergeNode" , []() -> sk_sp<SkSVGNode> { return SkSVGFeMergeNode::Make(); }},
__anonfb798c1b1702() 271*c8dee2aaSAndroid Build Coastguard Worker { "feMorphology" , []() -> sk_sp<SkSVGNode> { return SkSVGFeMorphology::Make(); }},
__anonfb798c1b1802() 272*c8dee2aaSAndroid Build Coastguard Worker { "feOffset" , []() -> sk_sp<SkSVGNode> { return SkSVGFeOffset::Make(); }},
__anonfb798c1b1902() 273*c8dee2aaSAndroid Build Coastguard Worker { "fePointLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFePointLight::Make(); }},
__anonfb798c1b1a02() 274*c8dee2aaSAndroid Build Coastguard Worker { "feSpecularLighting" , []() -> sk_sp<SkSVGNode> { return SkSVGFeSpecularLighting::Make(); }},
__anonfb798c1b1b02() 275*c8dee2aaSAndroid Build Coastguard Worker { "feSpotLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFeSpotLight::Make(); }},
__anonfb798c1b1c02() 276*c8dee2aaSAndroid Build Coastguard Worker { "feTurbulence" , []() -> sk_sp<SkSVGNode> { return SkSVGFeTurbulence::Make(); }},
__anonfb798c1b1d02() 277*c8dee2aaSAndroid Build Coastguard Worker { "filter" , []() -> sk_sp<SkSVGNode> { return SkSVGFilter::Make(); }},
__anonfb798c1b1e02() 278*c8dee2aaSAndroid Build Coastguard Worker { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
__anonfb798c1b1f02() 279*c8dee2aaSAndroid Build Coastguard Worker { "image" , []() -> sk_sp<SkSVGNode> { return SkSVGImage::Make(); }},
__anonfb798c1b2002() 280*c8dee2aaSAndroid Build Coastguard Worker { "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); }},
__anonfb798c1b2102() 281*c8dee2aaSAndroid Build Coastguard Worker { "linearGradient" , []() -> sk_sp<SkSVGNode> { return SkSVGLinearGradient::Make(); }},
__anonfb798c1b2202() 282*c8dee2aaSAndroid Build Coastguard Worker { "mask" , []() -> sk_sp<SkSVGNode> { return SkSVGMask::Make(); }},
__anonfb798c1b2302() 283*c8dee2aaSAndroid Build Coastguard Worker { "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
__anonfb798c1b2402() 284*c8dee2aaSAndroid Build Coastguard Worker { "pattern" , []() -> sk_sp<SkSVGNode> { return SkSVGPattern::Make(); }},
__anonfb798c1b2502() 285*c8dee2aaSAndroid Build Coastguard Worker { "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon(); }},
__anonfb798c1b2602() 286*c8dee2aaSAndroid Build Coastguard Worker { "polyline" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolyline(); }},
__anonfb798c1b2702() 287*c8dee2aaSAndroid Build Coastguard Worker { "radialGradient" , []() -> sk_sp<SkSVGNode> { return SkSVGRadialGradient::Make(); }},
__anonfb798c1b2802() 288*c8dee2aaSAndroid Build Coastguard Worker { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }},
__anonfb798c1b2902() 289*c8dee2aaSAndroid Build Coastguard Worker { "stop" , []() -> sk_sp<SkSVGNode> { return SkSVGStop::Make(); }},
290*c8dee2aaSAndroid Build Coastguard Worker // "svg" handled explicitly
__anonfb798c1b2a02() 291*c8dee2aaSAndroid Build Coastguard Worker { "text" , []() -> sk_sp<SkSVGNode> { return SkSVGText::Make(); }},
__anonfb798c1b2b02() 292*c8dee2aaSAndroid Build Coastguard Worker { "textPath" , []() -> sk_sp<SkSVGNode> { return SkSVGTextPath::Make(); }},
__anonfb798c1b2c02() 293*c8dee2aaSAndroid Build Coastguard Worker { "tspan" , []() -> sk_sp<SkSVGNode> { return SkSVGTSpan::Make(); }},
__anonfb798c1b2d02() 294*c8dee2aaSAndroid Build Coastguard Worker { "use" , []() -> sk_sp<SkSVGNode> { return SkSVGUse::Make(); }},
295*c8dee2aaSAndroid Build Coastguard Worker };
296*c8dee2aaSAndroid Build Coastguard Worker
297*c8dee2aaSAndroid Build Coastguard Worker struct ConstructionContext {
ConstructionContext__anonfb798c1b0111::ConstructionContext298*c8dee2aaSAndroid Build Coastguard Worker ConstructionContext(SkSVGIDMapper* mapper) : fParent(nullptr), fIDMapper(mapper) {}
ConstructionContext__anonfb798c1b0111::ConstructionContext299*c8dee2aaSAndroid Build Coastguard Worker ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode>& newParent)
300*c8dee2aaSAndroid Build Coastguard Worker : fParent(newParent.get()), fIDMapper(other.fIDMapper) {}
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker SkSVGNode* fParent;
303*c8dee2aaSAndroid Build Coastguard Worker SkSVGIDMapper* fIDMapper;
304*c8dee2aaSAndroid Build Coastguard Worker };
305*c8dee2aaSAndroid Build Coastguard Worker
set_string_attribute(const sk_sp<SkSVGNode> & node,const char * name,const char * value)306*c8dee2aaSAndroid Build Coastguard Worker bool set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value) {
307*c8dee2aaSAndroid Build Coastguard Worker if (node->parseAndSetAttribute(name, value)) {
308*c8dee2aaSAndroid Build Coastguard Worker // Handled by new code path
309*c8dee2aaSAndroid Build Coastguard Worker return true;
310*c8dee2aaSAndroid Build Coastguard Worker }
311*c8dee2aaSAndroid Build Coastguard Worker
312*c8dee2aaSAndroid Build Coastguard Worker const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey,
313*c8dee2aaSAndroid Build Coastguard Worker SkTo<int>(std::size(gAttributeParseInfo)),
314*c8dee2aaSAndroid Build Coastguard Worker name, sizeof(gAttributeParseInfo[0]));
315*c8dee2aaSAndroid Build Coastguard Worker if (attrIndex < 0) {
316*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_VERBOSE_SVG_PARSING)
317*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("unhandled attribute: %s\n", name);
318*c8dee2aaSAndroid Build Coastguard Worker #endif
319*c8dee2aaSAndroid Build Coastguard Worker return false;
320*c8dee2aaSAndroid Build Coastguard Worker }
321*c8dee2aaSAndroid Build Coastguard Worker
322*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkTo<size_t>(attrIndex) < std::size(gAttributeParseInfo));
323*c8dee2aaSAndroid Build Coastguard Worker const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue;
324*c8dee2aaSAndroid Build Coastguard Worker if (!attrInfo.fSetter(node, attrInfo.fAttr, value)) {
325*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_VERBOSE_SVG_PARSING)
326*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value);
327*c8dee2aaSAndroid Build Coastguard Worker #endif
328*c8dee2aaSAndroid Build Coastguard Worker return false;
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker
331*c8dee2aaSAndroid Build Coastguard Worker return true;
332*c8dee2aaSAndroid Build Coastguard Worker }
333*c8dee2aaSAndroid Build Coastguard Worker
parse_node_attributes(const SkDOM & xmlDom,const SkDOM::Node * xmlNode,const sk_sp<SkSVGNode> & svgNode,SkSVGIDMapper * mapper)334*c8dee2aaSAndroid Build Coastguard Worker void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode,
335*c8dee2aaSAndroid Build Coastguard Worker const sk_sp<SkSVGNode>& svgNode, SkSVGIDMapper* mapper) {
336*c8dee2aaSAndroid Build Coastguard Worker const char* name, *value;
337*c8dee2aaSAndroid Build Coastguard Worker SkDOM::AttrIter attrIter(xmlDom, xmlNode);
338*c8dee2aaSAndroid Build Coastguard Worker while ((name = attrIter.next(&value))) {
339*c8dee2aaSAndroid Build Coastguard Worker // We're handling id attributes out of band for now.
340*c8dee2aaSAndroid Build Coastguard Worker if (!strcmp(name, "id")) {
341*c8dee2aaSAndroid Build Coastguard Worker mapper->set(SkString(value), svgNode);
342*c8dee2aaSAndroid Build Coastguard Worker continue;
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker set_string_attribute(svgNode, name, value);
345*c8dee2aaSAndroid Build Coastguard Worker }
346*c8dee2aaSAndroid Build Coastguard Worker }
347*c8dee2aaSAndroid Build Coastguard Worker
construct_svg_node(const SkDOM & dom,const ConstructionContext & ctx,const SkDOM::Node * xmlNode)348*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext& ctx,
349*c8dee2aaSAndroid Build Coastguard Worker const SkDOM::Node* xmlNode) {
350*c8dee2aaSAndroid Build Coastguard Worker const char* elem = dom.getName(xmlNode);
351*c8dee2aaSAndroid Build Coastguard Worker const SkDOM::Type elemType = dom.getType(xmlNode);
352*c8dee2aaSAndroid Build Coastguard Worker
353*c8dee2aaSAndroid Build Coastguard Worker if (elemType == SkDOM::kText_Type) {
354*c8dee2aaSAndroid Build Coastguard Worker // Text literals require special handling.
355*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dom.countChildren(xmlNode) == 0);
356*c8dee2aaSAndroid Build Coastguard Worker auto txt = SkSVGTextLiteral::Make();
357*c8dee2aaSAndroid Build Coastguard Worker txt->setText(SkString(dom.getName(xmlNode)));
358*c8dee2aaSAndroid Build Coastguard Worker ctx.fParent->appendChild(std::move(txt));
359*c8dee2aaSAndroid Build Coastguard Worker
360*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
361*c8dee2aaSAndroid Build Coastguard Worker }
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(elemType == SkDOM::kElement_Type);
364*c8dee2aaSAndroid Build Coastguard Worker
365*c8dee2aaSAndroid Build Coastguard Worker auto make_node = [](const ConstructionContext& ctx, const char* elem) -> sk_sp<SkSVGNode> {
366*c8dee2aaSAndroid Build Coastguard Worker if (strcmp(elem, "svg") == 0) {
367*c8dee2aaSAndroid Build Coastguard Worker // Outermost SVG element must be tagged as such.
368*c8dee2aaSAndroid Build Coastguard Worker return SkSVGSVG::Make(ctx.fParent ? SkSVGSVG::Type::kInner
369*c8dee2aaSAndroid Build Coastguard Worker : SkSVGSVG::Type::kRoot);
370*c8dee2aaSAndroid Build Coastguard Worker }
371*c8dee2aaSAndroid Build Coastguard Worker
372*c8dee2aaSAndroid Build Coastguard Worker const int tagIndex = SkStrSearch(&gTagFactories[0].fKey,
373*c8dee2aaSAndroid Build Coastguard Worker SkTo<int>(std::size(gTagFactories)),
374*c8dee2aaSAndroid Build Coastguard Worker elem, sizeof(gTagFactories[0]));
375*c8dee2aaSAndroid Build Coastguard Worker if (tagIndex < 0) {
376*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_VERBOSE_SVG_PARSING)
377*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("unhandled element: <%s>\n", elem);
378*c8dee2aaSAndroid Build Coastguard Worker #endif
379*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
380*c8dee2aaSAndroid Build Coastguard Worker }
381*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkTo<size_t>(tagIndex) < std::size(gTagFactories));
382*c8dee2aaSAndroid Build Coastguard Worker
383*c8dee2aaSAndroid Build Coastguard Worker return gTagFactories[tagIndex].fValue();
384*c8dee2aaSAndroid Build Coastguard Worker };
385*c8dee2aaSAndroid Build Coastguard Worker
386*c8dee2aaSAndroid Build Coastguard Worker auto node = make_node(ctx, elem);
387*c8dee2aaSAndroid Build Coastguard Worker if (!node) {
388*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
389*c8dee2aaSAndroid Build Coastguard Worker }
390*c8dee2aaSAndroid Build Coastguard Worker
391*c8dee2aaSAndroid Build Coastguard Worker parse_node_attributes(dom, xmlNode, node, ctx.fIDMapper);
392*c8dee2aaSAndroid Build Coastguard Worker
393*c8dee2aaSAndroid Build Coastguard Worker ConstructionContext localCtx(ctx, node);
394*c8dee2aaSAndroid Build Coastguard Worker for (auto* child = dom.getFirstChild(xmlNode, nullptr); child;
395*c8dee2aaSAndroid Build Coastguard Worker child = dom.getNextSibling(child)) {
396*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSVGNode> childNode = construct_svg_node(dom, localCtx, child);
397*c8dee2aaSAndroid Build Coastguard Worker if (childNode) {
398*c8dee2aaSAndroid Build Coastguard Worker node->appendChild(std::move(childNode));
399*c8dee2aaSAndroid Build Coastguard Worker }
400*c8dee2aaSAndroid Build Coastguard Worker }
401*c8dee2aaSAndroid Build Coastguard Worker
402*c8dee2aaSAndroid Build Coastguard Worker return node;
403*c8dee2aaSAndroid Build Coastguard Worker }
404*c8dee2aaSAndroid Build Coastguard Worker
405*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
406*c8dee2aaSAndroid Build Coastguard Worker
setFontManager(sk_sp<SkFontMgr> fmgr)407*c8dee2aaSAndroid Build Coastguard Worker SkSVGDOM::Builder& SkSVGDOM::Builder::setFontManager(sk_sp<SkFontMgr> fmgr) {
408*c8dee2aaSAndroid Build Coastguard Worker fFontMgr = std::move(fmgr);
409*c8dee2aaSAndroid Build Coastguard Worker return *this;
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker
setResourceProvider(sk_sp<skresources::ResourceProvider> rp)412*c8dee2aaSAndroid Build Coastguard Worker SkSVGDOM::Builder& SkSVGDOM::Builder::setResourceProvider(sk_sp<skresources::ResourceProvider> rp) {
413*c8dee2aaSAndroid Build Coastguard Worker fResourceProvider = std::move(rp);
414*c8dee2aaSAndroid Build Coastguard Worker return *this;
415*c8dee2aaSAndroid Build Coastguard Worker }
416*c8dee2aaSAndroid Build Coastguard Worker
setTextShapingFactory(sk_sp<SkShapers::Factory> f)417*c8dee2aaSAndroid Build Coastguard Worker SkSVGDOM::Builder& SkSVGDOM::Builder::setTextShapingFactory(sk_sp<SkShapers::Factory> f) {
418*c8dee2aaSAndroid Build Coastguard Worker fTextShapingFactory = f;
419*c8dee2aaSAndroid Build Coastguard Worker return *this;
420*c8dee2aaSAndroid Build Coastguard Worker }
421*c8dee2aaSAndroid Build Coastguard Worker
make(SkStream & str) const422*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSVGDOM> SkSVGDOM::Builder::make(SkStream& str) const {
423*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia", TRACE_FUNC);
424*c8dee2aaSAndroid Build Coastguard Worker SkDOM xmlDom;
425*c8dee2aaSAndroid Build Coastguard Worker if (!xmlDom.build(str)) {
426*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
427*c8dee2aaSAndroid Build Coastguard Worker }
428*c8dee2aaSAndroid Build Coastguard Worker
429*c8dee2aaSAndroid Build Coastguard Worker SkSVGIDMapper mapper;
430*c8dee2aaSAndroid Build Coastguard Worker ConstructionContext ctx(&mapper);
431*c8dee2aaSAndroid Build Coastguard Worker
432*c8dee2aaSAndroid Build Coastguard Worker auto root = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode());
433*c8dee2aaSAndroid Build Coastguard Worker if (!root || root->tag() != SkSVGTag::kSvg) {
434*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
435*c8dee2aaSAndroid Build Coastguard Worker }
436*c8dee2aaSAndroid Build Coastguard Worker
437*c8dee2aaSAndroid Build Coastguard Worker class NullResourceProvider final : public skresources::ResourceProvider {
438*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> load(const char[], const char[]) const override { return nullptr; }
439*c8dee2aaSAndroid Build Coastguard Worker };
440*c8dee2aaSAndroid Build Coastguard Worker
441*c8dee2aaSAndroid Build Coastguard Worker auto resource_provider = fResourceProvider ? fResourceProvider
442*c8dee2aaSAndroid Build Coastguard Worker : sk_make_sp<NullResourceProvider>();
443*c8dee2aaSAndroid Build Coastguard Worker
444*c8dee2aaSAndroid Build Coastguard Worker auto factory = fTextShapingFactory ? fTextShapingFactory : SkShapers::Primitive::Factory();
445*c8dee2aaSAndroid Build Coastguard Worker
446*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<SkSVGDOM>(new SkSVGDOM(sk_sp<SkSVGSVG>(static_cast<SkSVGSVG*>(root.release())),
447*c8dee2aaSAndroid Build Coastguard Worker std::move(fFontMgr),
448*c8dee2aaSAndroid Build Coastguard Worker std::move(resource_provider),
449*c8dee2aaSAndroid Build Coastguard Worker std::move(mapper),
450*c8dee2aaSAndroid Build Coastguard Worker std::move(factory)));
451*c8dee2aaSAndroid Build Coastguard Worker }
452*c8dee2aaSAndroid Build Coastguard Worker
SkSVGDOM(sk_sp<SkSVGSVG> root,sk_sp<SkFontMgr> fmgr,sk_sp<skresources::ResourceProvider> rp,SkSVGIDMapper && mapper,sk_sp<SkShapers::Factory> fact)453*c8dee2aaSAndroid Build Coastguard Worker SkSVGDOM::SkSVGDOM(sk_sp<SkSVGSVG> root,
454*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkFontMgr> fmgr,
455*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skresources::ResourceProvider> rp,
456*c8dee2aaSAndroid Build Coastguard Worker SkSVGIDMapper&& mapper,
457*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShapers::Factory> fact)
458*c8dee2aaSAndroid Build Coastguard Worker : fRoot(std::move(root))
459*c8dee2aaSAndroid Build Coastguard Worker , fFontMgr(std::move(fmgr))
460*c8dee2aaSAndroid Build Coastguard Worker , fTextShapingFactory(std::move(fact))
461*c8dee2aaSAndroid Build Coastguard Worker , fResourceProvider(std::move(rp))
462*c8dee2aaSAndroid Build Coastguard Worker , fIDMapper(std::move(mapper))
463*c8dee2aaSAndroid Build Coastguard Worker , fContainerSize(fRoot->intrinsicSize(SkSVGLengthContext(SkSize::Make(0, 0)))) {
464*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fResourceProvider);
465*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fTextShapingFactory);
466*c8dee2aaSAndroid Build Coastguard Worker }
467*c8dee2aaSAndroid Build Coastguard Worker
render(SkCanvas * canvas) const468*c8dee2aaSAndroid Build Coastguard Worker void SkSVGDOM::render(SkCanvas* canvas) const {
469*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia", TRACE_FUNC);
470*c8dee2aaSAndroid Build Coastguard Worker if (fRoot) {
471*c8dee2aaSAndroid Build Coastguard Worker SkSVGLengthContext lctx(fContainerSize);
472*c8dee2aaSAndroid Build Coastguard Worker SkSVGPresentationContext pctx;
473*c8dee2aaSAndroid Build Coastguard Worker fRoot->render(SkSVGRenderContext(canvas,
474*c8dee2aaSAndroid Build Coastguard Worker fFontMgr,
475*c8dee2aaSAndroid Build Coastguard Worker fResourceProvider,
476*c8dee2aaSAndroid Build Coastguard Worker fIDMapper,
477*c8dee2aaSAndroid Build Coastguard Worker lctx,
478*c8dee2aaSAndroid Build Coastguard Worker pctx,
479*c8dee2aaSAndroid Build Coastguard Worker {nullptr, nullptr},
480*c8dee2aaSAndroid Build Coastguard Worker fTextShapingFactory));
481*c8dee2aaSAndroid Build Coastguard Worker }
482*c8dee2aaSAndroid Build Coastguard Worker }
483*c8dee2aaSAndroid Build Coastguard Worker
renderNode(SkCanvas * canvas,SkSVGPresentationContext & pctx,const char * id) const484*c8dee2aaSAndroid Build Coastguard Worker void SkSVGDOM::renderNode(SkCanvas* canvas, SkSVGPresentationContext& pctx, const char* id) const {
485*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("skia", TRACE_FUNC);
486*c8dee2aaSAndroid Build Coastguard Worker
487*c8dee2aaSAndroid Build Coastguard Worker if (fRoot) {
488*c8dee2aaSAndroid Build Coastguard Worker SkSVGLengthContext lctx(fContainerSize);
489*c8dee2aaSAndroid Build Coastguard Worker fRoot->renderNode(SkSVGRenderContext(canvas,
490*c8dee2aaSAndroid Build Coastguard Worker fFontMgr,
491*c8dee2aaSAndroid Build Coastguard Worker fResourceProvider,
492*c8dee2aaSAndroid Build Coastguard Worker fIDMapper,
493*c8dee2aaSAndroid Build Coastguard Worker lctx,
494*c8dee2aaSAndroid Build Coastguard Worker pctx,
495*c8dee2aaSAndroid Build Coastguard Worker {nullptr, nullptr},
496*c8dee2aaSAndroid Build Coastguard Worker fTextShapingFactory),
497*c8dee2aaSAndroid Build Coastguard Worker SkSVGIRI(SkSVGIRI::Type::kLocal, SkSVGStringType(id)));
498*c8dee2aaSAndroid Build Coastguard Worker }
499*c8dee2aaSAndroid Build Coastguard Worker }
500*c8dee2aaSAndroid Build Coastguard Worker
containerSize() const501*c8dee2aaSAndroid Build Coastguard Worker const SkSize& SkSVGDOM::containerSize() const {
502*c8dee2aaSAndroid Build Coastguard Worker return fContainerSize;
503*c8dee2aaSAndroid Build Coastguard Worker }
504*c8dee2aaSAndroid Build Coastguard Worker
setContainerSize(const SkSize & containerSize)505*c8dee2aaSAndroid Build Coastguard Worker void SkSVGDOM::setContainerSize(const SkSize& containerSize) {
506*c8dee2aaSAndroid Build Coastguard Worker // TODO: inval
507*c8dee2aaSAndroid Build Coastguard Worker fContainerSize = containerSize;
508*c8dee2aaSAndroid Build Coastguard Worker }
509*c8dee2aaSAndroid Build Coastguard Worker
findNodeById(const char * id)510*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSVGNode>* SkSVGDOM::findNodeById(const char* id) {
511*c8dee2aaSAndroid Build Coastguard Worker SkString idStr(id);
512*c8dee2aaSAndroid Build Coastguard Worker return this->fIDMapper.find(idStr);
513*c8dee2aaSAndroid Build Coastguard Worker }
514*c8dee2aaSAndroid Build Coastguard Worker
515*c8dee2aaSAndroid Build Coastguard Worker // TODO(fuego): move this to SkSVGNode or its own CU.
setAttribute(const char * attributeName,const char * attributeValue)516*c8dee2aaSAndroid Build Coastguard Worker bool SkSVGNode::setAttribute(const char* attributeName, const char* attributeValue) {
517*c8dee2aaSAndroid Build Coastguard Worker return set_string_attribute(sk_ref_sp(this), attributeName, attributeValue);
518*c8dee2aaSAndroid Build Coastguard Worker }
519