Flutter Engine
The Flutter Engine
SkSVGDOM.cpp
Go to the documentation of this file.
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
9
53#include "src/base/SkTSearch.h"
55#include "src/xml/SkDOM.h"
56
57namespace {
58
59bool SetIRIAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
60 const char* stringValue) {
61 auto parseResult = SkSVGAttributeParser::parse<SkSVGIRI>(stringValue);
62 if (!parseResult.isValid()) {
63 return false;
64 }
65
66 node->setAttribute(attr, SkSVGStringValue(parseResult->iri()));
67 return true;
68}
69
70bool SetStringAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
71 const char* stringValue) {
72 SkString str(stringValue, strlen(stringValue));
73 SkSVGStringType strType = SkSVGStringType(str);
74 node->setAttribute(attr, SkSVGStringValue(strType));
75 return true;
76}
77
78bool SetTransformAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
79 const char* stringValue) {
80 auto parseResult = SkSVGAttributeParser::parse<SkSVGTransformType>(stringValue);
81 if (!parseResult.isValid()) {
82 return false;
83 }
84
85 node->setAttribute(attr, SkSVGTransformValue(*parseResult));
86 return true;
87}
88
89bool SetLengthAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
90 const char* stringValue) {
91 auto parseResult = SkSVGAttributeParser::parse<SkSVGLength>(stringValue);
92 if (!parseResult.isValid()) {
93 return false;
94 }
95
96 node->setAttribute(attr, SkSVGLengthValue(*parseResult));
97 return true;
98}
99
100bool SetViewBoxAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
101 const char* stringValue) {
102 SkSVGViewBoxType viewBox;
103 SkSVGAttributeParser parser(stringValue);
104 if (!parser.parseViewBox(&viewBox)) {
105 return false;
106 }
107
108 node->setAttribute(attr, SkSVGViewBoxValue(viewBox));
109 return true;
110}
111
112bool SetObjectBoundingBoxUnitsAttribute(const sk_sp<SkSVGNode>& node,
113 SkSVGAttribute attr,
114 const char* stringValue) {
115 auto parseResult = SkSVGAttributeParser::parse<SkSVGObjectBoundingBoxUnits>(stringValue);
116 if (!parseResult.isValid()) {
117 return false;
118 }
119
120 node->setAttribute(attr, SkSVGObjectBoundingBoxUnitsValue(*parseResult));
121 return true;
122}
123
124bool SetPreserveAspectRatioAttribute(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr,
125 const char* stringValue) {
127 SkSVGAttributeParser parser(stringValue);
128 if (!parser.parsePreserveAspectRatio(&par)) {
129 return false;
130 }
131
133 return true;
134}
135
136SkString TrimmedString(const char* first, const char* last) {
137 SkASSERT(first);
138 SkASSERT(last);
139 SkASSERT(first <= last);
140
141 while (first <= last && *first <= ' ') { first++; }
142 while (first <= last && *last <= ' ') { last--; }
143
144 SkASSERT(last - first + 1 >= 0);
145 return SkString(first, SkTo<size_t>(last - first + 1));
146}
147
148// Breaks a "foo: bar; baz: ..." string into key:value pairs.
149class StyleIterator {
150public:
151 StyleIterator(const char* str) : fPos(str) { }
152
153 std::tuple<SkString, SkString> next() {
155
156 if (fPos) {
157 const char* sep = this->nextSeparator();
158 SkASSERT(*sep == ';' || *sep == '\0');
159
160 const char* valueSep = strchr(fPos, ':');
161 if (valueSep && valueSep < sep) {
162 name = TrimmedString(fPos, valueSep - 1);
163 value = TrimmedString(valueSep + 1, sep - 1);
164 }
165
166 fPos = *sep ? sep + 1 : nullptr;
167 }
168
169 return std::make_tuple(name, value);
170 }
171
172private:
173 const char* nextSeparator() const {
174 const char* sep = fPos;
175 while (*sep != ';' && *sep != '\0') {
176 sep++;
177 }
178 return sep;
179 }
180
181 const char* fPos;
182};
183
184bool set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value);
185
186bool SetStyleAttributes(const sk_sp<SkSVGNode>& node, SkSVGAttribute,
187 const char* stringValue) {
188
190 StyleIterator iter(stringValue);
191 for (;;) {
192 std::tie(name, value) = iter.next();
193 if (name.isEmpty()) {
194 break;
195 }
196 set_string_attribute(node, name.c_str(), value.c_str());
197 }
198
199 return true;
200}
201
202template<typename T>
203struct SortedDictionaryEntry {
204 const char* fKey;
205 const T fValue;
206};
207
208struct AttrParseInfo {
209 SkSVGAttribute fAttr;
210 bool (*fSetter)(const sk_sp<SkSVGNode>& node, SkSVGAttribute attr, const char* stringValue);
211};
212
213SortedDictionaryEntry<AttrParseInfo> gAttributeParseInfo[] = {
214 { "cx" , { SkSVGAttribute::kCx , SetLengthAttribute }},
215 { "cy" , { SkSVGAttribute::kCy , SetLengthAttribute }},
216 { "filterUnits" , { SkSVGAttribute::kFilterUnits ,
217 SetObjectBoundingBoxUnitsAttribute }},
218 // focal point x & y
219 { "fx" , { SkSVGAttribute::kFx , SetLengthAttribute }},
220 { "fy" , { SkSVGAttribute::kFy , SetLengthAttribute }},
221 { "height" , { SkSVGAttribute::kHeight , SetLengthAttribute }},
222 { "preserveAspectRatio", { SkSVGAttribute::kPreserveAspectRatio,
223 SetPreserveAspectRatioAttribute }},
224 { "r" , { SkSVGAttribute::kR , SetLengthAttribute }},
225 { "rx" , { SkSVGAttribute::kRx , SetLengthAttribute }},
226 { "ry" , { SkSVGAttribute::kRy , SetLengthAttribute }},
227 { "style" , { SkSVGAttribute::kUnknown , SetStyleAttributes }},
228 { "text" , { SkSVGAttribute::kText , SetStringAttribute }},
229 { "transform" , { SkSVGAttribute::kTransform , SetTransformAttribute }},
230 { "viewBox" , { SkSVGAttribute::kViewBox , SetViewBoxAttribute }},
231 { "width" , { SkSVGAttribute::kWidth , SetLengthAttribute }},
232 { "x" , { SkSVGAttribute::kX , SetLengthAttribute }},
233 { "x1" , { SkSVGAttribute::kX1 , SetLengthAttribute }},
234 { "x2" , { SkSVGAttribute::kX2 , SetLengthAttribute }},
235 { "xlink:href" , { SkSVGAttribute::kHref , SetIRIAttribute }},
236 { "y" , { SkSVGAttribute::kY , SetLengthAttribute }},
237 { "y1" , { SkSVGAttribute::kY1 , SetLengthAttribute }},
238 { "y2" , { SkSVGAttribute::kY2 , SetLengthAttribute }},
239};
240
241SortedDictionaryEntry<sk_sp<SkSVGNode>(*)()> gTagFactories[] = {
242 { "a" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
243 { "circle" , []() -> sk_sp<SkSVGNode> { return SkSVGCircle::Make(); }},
244 { "clipPath" , []() -> sk_sp<SkSVGNode> { return SkSVGClipPath::Make(); }},
245 { "defs" , []() -> sk_sp<SkSVGNode> { return SkSVGDefs::Make(); }},
246 { "ellipse" , []() -> sk_sp<SkSVGNode> { return SkSVGEllipse::Make(); }},
247 { "feBlend" , []() -> sk_sp<SkSVGNode> { return SkSVGFeBlend::Make(); }},
248 { "feColorMatrix" , []() -> sk_sp<SkSVGNode> { return SkSVGFeColorMatrix::Make(); }},
249 { "feComponentTransfer", []() -> sk_sp<SkSVGNode> { return SkSVGFeComponentTransfer::Make(); }},
250 { "feComposite" , []() -> sk_sp<SkSVGNode> { return SkSVGFeComposite::Make(); }},
251 { "feDiffuseLighting" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDiffuseLighting::Make(); }},
252 { "feDisplacementMap" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDisplacementMap::Make(); }},
253 { "feDistantLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFeDistantLight::Make(); }},
254 { "feFlood" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFlood::Make(); }},
255 { "feFuncA" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncA(); }},
256 { "feFuncB" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncB(); }},
257 { "feFuncG" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncG(); }},
258 { "feFuncR" , []() -> sk_sp<SkSVGNode> { return SkSVGFeFunc::MakeFuncR(); }},
259 { "feGaussianBlur" , []() -> sk_sp<SkSVGNode> { return SkSVGFeGaussianBlur::Make(); }},
260 { "feImage" , []() -> sk_sp<SkSVGNode> { return SkSVGFeImage::Make(); }},
261 { "feMerge" , []() -> sk_sp<SkSVGNode> { return SkSVGFeMerge::Make(); }},
262 { "feMergeNode" , []() -> sk_sp<SkSVGNode> { return SkSVGFeMergeNode::Make(); }},
263 { "feMorphology" , []() -> sk_sp<SkSVGNode> { return SkSVGFeMorphology::Make(); }},
264 { "feOffset" , []() -> sk_sp<SkSVGNode> { return SkSVGFeOffset::Make(); }},
265 { "fePointLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFePointLight::Make(); }},
266 { "feSpecularLighting" , []() -> sk_sp<SkSVGNode> { return SkSVGFeSpecularLighting::Make(); }},
267 { "feSpotLight" , []() -> sk_sp<SkSVGNode> { return SkSVGFeSpotLight::Make(); }},
268 { "feTurbulence" , []() -> sk_sp<SkSVGNode> { return SkSVGFeTurbulence::Make(); }},
269 { "filter" , []() -> sk_sp<SkSVGNode> { return SkSVGFilter::Make(); }},
270 { "g" , []() -> sk_sp<SkSVGNode> { return SkSVGG::Make(); }},
271 { "image" , []() -> sk_sp<SkSVGNode> { return SkSVGImage::Make(); }},
272 { "line" , []() -> sk_sp<SkSVGNode> { return SkSVGLine::Make(); }},
273 { "linearGradient" , []() -> sk_sp<SkSVGNode> { return SkSVGLinearGradient::Make(); }},
274 { "mask" , []() -> sk_sp<SkSVGNode> { return SkSVGMask::Make(); }},
275 { "path" , []() -> sk_sp<SkSVGNode> { return SkSVGPath::Make(); }},
276 { "pattern" , []() -> sk_sp<SkSVGNode> { return SkSVGPattern::Make(); }},
277 { "polygon" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolygon(); }},
278 { "polyline" , []() -> sk_sp<SkSVGNode> { return SkSVGPoly::MakePolyline(); }},
279 { "radialGradient" , []() -> sk_sp<SkSVGNode> { return SkSVGRadialGradient::Make(); }},
280 { "rect" , []() -> sk_sp<SkSVGNode> { return SkSVGRect::Make(); }},
281 { "stop" , []() -> sk_sp<SkSVGNode> { return SkSVGStop::Make(); }},
282// "svg" handled explicitly
283 { "text" , []() -> sk_sp<SkSVGNode> { return SkSVGText::Make(); }},
284 { "textPath" , []() -> sk_sp<SkSVGNode> { return SkSVGTextPath::Make(); }},
285 { "tspan" , []() -> sk_sp<SkSVGNode> { return SkSVGTSpan::Make(); }},
286 { "use" , []() -> sk_sp<SkSVGNode> { return SkSVGUse::Make(); }},
287};
288
289struct ConstructionContext {
290 ConstructionContext(SkSVGIDMapper* mapper) : fParent(nullptr), fIDMapper(mapper) {}
291 ConstructionContext(const ConstructionContext& other, const sk_sp<SkSVGNode>& newParent)
292 : fParent(newParent.get()), fIDMapper(other.fIDMapper) {}
293
294 SkSVGNode* fParent;
295 SkSVGIDMapper* fIDMapper;
296};
297
298bool set_string_attribute(const sk_sp<SkSVGNode>& node, const char* name, const char* value) {
299 if (node->parseAndSetAttribute(name, value)) {
300 // Handled by new code path
301 return true;
302 }
303
304 const int attrIndex = SkStrSearch(&gAttributeParseInfo[0].fKey,
305 SkTo<int>(std::size(gAttributeParseInfo)),
306 name, sizeof(gAttributeParseInfo[0]));
307 if (attrIndex < 0) {
308#if defined(SK_VERBOSE_SVG_PARSING)
309 SkDebugf("unhandled attribute: %s\n", name);
310#endif
311 return false;
312 }
313
314 SkASSERT(SkTo<size_t>(attrIndex) < std::size(gAttributeParseInfo));
315 const auto& attrInfo = gAttributeParseInfo[attrIndex].fValue;
316 if (!attrInfo.fSetter(node, attrInfo.fAttr, value)) {
317#if defined(SK_VERBOSE_SVG_PARSING)
318 SkDebugf("could not parse attribute: '%s=\"%s\"'\n", name, value);
319#endif
320 return false;
321 }
322
323 return true;
324}
325
326void parse_node_attributes(const SkDOM& xmlDom, const SkDOM::Node* xmlNode,
327 const sk_sp<SkSVGNode>& svgNode, SkSVGIDMapper* mapper) {
328 const char* name, *value;
329 SkDOM::AttrIter attrIter(xmlDom, xmlNode);
330 while ((name = attrIter.next(&value))) {
331 // We're handling id attributes out of band for now.
332 if (!strcmp(name, "id")) {
333 mapper->set(SkString(value), svgNode);
334 continue;
335 }
336 set_string_attribute(svgNode, name, value);
337 }
338}
339
340sk_sp<SkSVGNode> construct_svg_node(const SkDOM& dom, const ConstructionContext& ctx,
341 const SkDOM::Node* xmlNode) {
342 const char* elem = dom.getName(xmlNode);
343 const SkDOM::Type elemType = dom.getType(xmlNode);
344
345 if (elemType == SkDOM::kText_Type) {
346 // Text literals require special handling.
347 SkASSERT(dom.countChildren(xmlNode) == 0);
349 txt->setText(SkString(dom.getName(xmlNode)));
350 ctx.fParent->appendChild(std::move(txt));
351
352 return nullptr;
353 }
354
355 SkASSERT(elemType == SkDOM::kElement_Type);
356
357 auto make_node = [](const ConstructionContext& ctx, const char* elem) -> sk_sp<SkSVGNode> {
358 if (strcmp(elem, "svg") == 0) {
359 // Outermost SVG element must be tagged as such.
360 return SkSVGSVG::Make(ctx.fParent ? SkSVGSVG::Type::kInner
362 }
363
364 const int tagIndex = SkStrSearch(&gTagFactories[0].fKey,
365 SkTo<int>(std::size(gTagFactories)),
366 elem, sizeof(gTagFactories[0]));
367 if (tagIndex < 0) {
368#if defined(SK_VERBOSE_SVG_PARSING)
369 SkDebugf("unhandled element: <%s>\n", elem);
370#endif
371 return nullptr;
372 }
373 SkASSERT(SkTo<size_t>(tagIndex) < std::size(gTagFactories));
374
375 return gTagFactories[tagIndex].fValue();
376 };
377
378 auto node = make_node(ctx, elem);
379 if (!node) {
380 return nullptr;
381 }
382
383 parse_node_attributes(dom, xmlNode, node, ctx.fIDMapper);
384
385 ConstructionContext localCtx(ctx, node);
386 for (auto* child = dom.getFirstChild(xmlNode, nullptr); child;
387 child = dom.getNextSibling(child)) {
388 sk_sp<SkSVGNode> childNode = construct_svg_node(dom, localCtx, child);
389 if (childNode) {
390 node->appendChild(std::move(childNode));
391 }
392 }
393
394 return node;
395}
396
397} // anonymous namespace
398
400 fFontMgr = std::move(fmgr);
401 return *this;
402}
403
405 fResourceProvider = std::move(rp);
406 return *this;
407}
408
410 fTextShapingFactory = f;
411 return *this;
412}
413
415 TRACE_EVENT0("skia", TRACE_FUNC);
416 SkDOM xmlDom;
417 if (!xmlDom.build(str)) {
418 return nullptr;
419 }
420
421 SkSVGIDMapper mapper;
422 ConstructionContext ctx(&mapper);
423
424 auto root = construct_svg_node(xmlDom, ctx, xmlDom.getRootNode());
425 if (!root || root->tag() != SkSVGTag::kSvg) {
426 return nullptr;
427 }
428
429 class NullResourceProvider final : public skresources::ResourceProvider {
430 sk_sp<SkData> load(const char[], const char[]) const override { return nullptr; }
431 };
432
433 auto resource_provider = fResourceProvider ? fResourceProvider
434 : sk_make_sp<NullResourceProvider>();
435
436 auto factory = fTextShapingFactory ? fTextShapingFactory : SkShapers::Primitive::Factory();
437
438 return sk_sp<SkSVGDOM>(new SkSVGDOM(sk_sp<SkSVGSVG>(static_cast<SkSVGSVG*>(root.release())),
439 std::move(fFontMgr),
440 std::move(resource_provider),
441 std::move(mapper),
442 std::move(factory)));
443}
444
445SkSVGDOM::SkSVGDOM(sk_sp<SkSVGSVG> root,
446 sk_sp<SkFontMgr> fmgr,
448 SkSVGIDMapper&& mapper,
450 : fRoot(std::move(root))
451 , fFontMgr(std::move(fmgr))
452 , fTextShapingFactory(std::move(fact))
453 , fResourceProvider(std::move(rp))
454 , fIDMapper(std::move(mapper))
455 , fContainerSize(fRoot->intrinsicSize(SkSVGLengthContext(SkSize::Make(0, 0)))) {
456 SkASSERT(fResourceProvider);
457 SkASSERT(fTextShapingFactory);
458}
459
460void SkSVGDOM::render(SkCanvas* canvas) const {
461 TRACE_EVENT0("skia", TRACE_FUNC);
462 if (fRoot) {
463 SkSVGLengthContext lctx(fContainerSize);
465 fRoot->render(SkSVGRenderContext(canvas,
466 fFontMgr,
467 fResourceProvider,
468 fIDMapper,
469 lctx,
470 pctx,
471 {nullptr, nullptr},
472 fTextShapingFactory));
473 }
474}
475
476void SkSVGDOM::renderNode(SkCanvas* canvas, SkSVGPresentationContext& pctx, const char* id) const {
477 TRACE_EVENT0("skia", TRACE_FUNC);
478
479 if (fRoot) {
480 SkSVGLengthContext lctx(fContainerSize);
481 fRoot->renderNode(SkSVGRenderContext(canvas,
482 fFontMgr,
483 fResourceProvider,
484 fIDMapper,
485 lctx,
486 pctx,
487 {nullptr, nullptr},
488 fTextShapingFactory),
490 }
491}
492
494 return fContainerSize;
495}
496
498 // TODO: inval
499 fContainerSize = containerSize;
500}
501
503 SkString idStr(id);
504 return this->fIDMapper.find(idStr);
505}
506
507// TODO(fuego): move this to SkSVGNode or its own CU.
508bool SkSVGNode::setAttribute(const char* attributeName, const char* attributeValue) {
509 return set_string_attribute(sk_ref_sp(this), attributeName, attributeValue);
510}
static float next(float f)
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
SkSVGAttribute
SkString SkSVGStringType
Definition: SkSVGTypes.h:28
SkSVGWrapperValue< SkSVGPreserveAspectRatio, SkSVGValue::Type::kPreserveAspectRatio > SkSVGPreserveAspectRatioValue
Definition: SkSVGValue.h:80
SkSVGWrapperValue< SkSVGObjectBoundingBoxUnits, SkSVGValue::Type::kObjectBoundingBoxUnits > SkSVGObjectBoundingBoxUnitsValue
Definition: SkSVGValue.h:83
SkSVGWrapperValue< SkSVGViewBoxType, SkSVGValue::Type::kViewBox > SkSVGViewBoxValue
Definition: SkSVGValue.h:74
SkSVGWrapperValue< SkSVGStringType, SkSVGValue::Type::kString > SkSVGStringValue
Definition: SkSVGValue.h:76
SkSVGWrapperValue< SkSVGTransformType, SkSVGValue::Type::kTransform > SkSVGTransformValue
Definition: SkSVGValue.h:73
SkSVGWrapperValue< SkSVGLength, SkSVGValue::Type::kLength > SkSVGLengthValue
Definition: SkSVGValue.h:72
int SkStrSearch(const char *const *base, int count, const char target[], size_t target_len, size_t elemSize)
Definition: SkTSearch.cpp:22
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
SI T load(const P *ptr)
Definition: Transform_inl.h:98
Definition: SkDOM.h:24
Type
Definition: SkDOM.h:42
@ kText_Type
Definition: SkDOM.h:44
@ kElement_Type
Definition: SkDOM.h:43
const Node * getRootNode() const
Definition: SkDOM.cpp:76
const Node * build(SkStream &)
Definition: SkDOM.cpp:294
static sk_sp< SkSVGCircle > Make()
Definition: SkSVGCircle.h:18
static sk_sp< SkSVGClipPath > Make()
Definition: SkSVGClipPath.h:16
Builder & setTextShapingFactory(sk_sp< SkShapers::Factory >)
Definition: SkSVGDOM.cpp:409
sk_sp< SkSVGDOM > make(SkStream &) const
Definition: SkSVGDOM.cpp:414
Builder & setFontManager(sk_sp< SkFontMgr >)
Definition: SkSVGDOM.cpp:399
Builder & setResourceProvider(sk_sp< skresources::ResourceProvider >)
Definition: SkSVGDOM.cpp:404
void renderNode(SkCanvas *, SkSVGPresentationContext &, const char *id) const
Definition: SkSVGDOM.cpp:476
sk_sp< SkSVGNode > * findNodeById(const char *id)
Definition: SkSVGDOM.cpp:502
void render(SkCanvas *) const
Definition: SkSVGDOM.cpp:460
void setContainerSize(const SkSize &)
Definition: SkSVGDOM.cpp:497
const SkSize & containerSize() const
Definition: SkSVGDOM.cpp:493
static sk_sp< SkSVGDefs > Make()
Definition: SkSVGDefs.h:15
static sk_sp< SkSVGEllipse > Make()
Definition: SkSVGEllipse.h:18
static sk_sp< SkSVGFeBlend > Make()
Definition: SkSVGFeBlend.h:24
static sk_sp< SkSVGFeColorMatrix > Make()
static sk_sp< SkSVGFeComponentTransfer > Make()
static sk_sp< SkSVGFeComposite > Make()
static sk_sp< SkSVGFeDiffuseLighting > Make()
static sk_sp< SkSVGFeDisplacementMap > Make()
static sk_sp< SkSVGFeDistantLight > Make()
static sk_sp< SkSVGFeFlood > Make()
Definition: SkSVGFeFlood.h:16
static sk_sp< SkSVGFeFunc > MakeFuncG()
static sk_sp< SkSVGFeFunc > MakeFuncR()
static sk_sp< SkSVGFeFunc > MakeFuncB()
static sk_sp< SkSVGFeFunc > MakeFuncA()
static sk_sp< SkSVGFeGaussianBlur > Make()
static sk_sp< SkSVGFeImage > Make()
Definition: SkSVGFeImage.h:16
static sk_sp< SkSVGFeMergeNode > Make()
Definition: SkSVGFeMerge.h:21
static sk_sp< SkSVGFeMerge > Make()
Definition: SkSVGFeMerge.h:41
static sk_sp< SkSVGFeMorphology > Make()
static sk_sp< SkSVGFeOffset > Make()
Definition: SkSVGFeOffset.h:16
static sk_sp< SkSVGFePointLight > Make()
static sk_sp< SkSVGFeSpecularLighting > Make()
static sk_sp< SkSVGFeSpotLight > Make()
static sk_sp< SkSVGFeTurbulence > Make()
static sk_sp< SkSVGFilter > Make()
Definition: SkSVGFilter.h:16
static sk_sp< SkSVGG > Make()
Definition: SkSVGG.h:15
static sk_sp< SkSVGImage > Make()
Definition: SkSVGImage.h:20
static sk_sp< SkSVGLine > Make()
Definition: SkSVGLine.h:18
static sk_sp< SkSVGLinearGradient > Make()
static sk_sp< SkSVGMask > Make()
Definition: SkSVGMask.h:16
virtual bool parseAndSetAttribute(const char *name, const char *value)
Definition: SkSVGNode.cpp:90
void setAttribute(SkSVGAttribute, const SkSVGValue &)
Definition: SkSVGNode.cpp:75
virtual void appendChild(sk_sp< SkSVGNode >)=0
static sk_sp< SkSVGPath > Make()
Definition: SkSVGPath.h:16
static sk_sp< SkSVGPattern > Make()
Definition: SkSVGPattern.h:18
static sk_sp< SkSVGPoly > MakePolygon()
Definition: SkSVGPoly.h:17
static sk_sp< SkSVGPoly > MakePolyline()
Definition: SkSVGPoly.h:21
static sk_sp< SkSVGRadialGradient > Make()
static sk_sp< SkSVGRect > Make()
Definition: SkSVGRect.h:18
static sk_sp< SkSVGSVG > Make(Type t=Type::kInner)
Definition: SkSVGSVG.h:23
static sk_sp< SkSVGStop > Make()
Definition: SkSVGStop.h:20
static sk_sp< SkSVGTSpan > Make()
Definition: SkSVGText.h:80
static sk_sp< SkSVGTextLiteral > Make()
Definition: SkSVGText.h:90
static sk_sp< SkSVGTextPath > Make()
Definition: SkSVGText.h:108
static sk_sp< SkSVGText > Make()
Definition: SkSVGText.h:65
static sk_sp< SkSVGUse > Make()
Definition: SkSVGUse.h:20
V * find(const K &key) const
Definition: SkTHash.h:494
V * set(K key, V val)
Definition: SkTHash.h:487
uint8_t value
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
SKSHAPER_API sk_sp< Factory > Factory()
Definition: dom.py:1
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
const myers::Point & get(const myers::Segment &)
string root
Definition: scale_cpu.py:20
Definition: ref_ptr.h:256
parser
Definition: zip.py:78
#define T
Definition: precompiler.cc:65
Definition: SkSize.h:52
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131