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