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/private/SkTPin.h" 9cb93a386Sopenharmony_ci#include "include/utils/SkParse.h" 10cb93a386Sopenharmony_ci#include "modules/svg/include/SkSVGAttributeParser.h" 11cb93a386Sopenharmony_ci#include "modules/svg/include/SkSVGTypes.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_cinamespace { 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci// TODO: these should be shared with SkParse.cpp 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ciinline bool is_between(char c, char min, char max) { 18cb93a386Sopenharmony_ci SkASSERT(min <= max); 19cb93a386Sopenharmony_ci return (unsigned)(c - min) <= (unsigned)(max - min); 20cb93a386Sopenharmony_ci} 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciinline bool is_eos(char c) { 23cb93a386Sopenharmony_ci return !c; 24cb93a386Sopenharmony_ci} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciinline bool is_ws(char c) { 27cb93a386Sopenharmony_ci return is_between(c, 1, 32); 28cb93a386Sopenharmony_ci} 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ciinline bool is_sep(char c) { 31cb93a386Sopenharmony_ci return is_ws(c) || c == ',' || c == ';'; 32cb93a386Sopenharmony_ci} 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci} // namespace 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciSkSVGAttributeParser::SkSVGAttributeParser(const char attributeString[]) 37cb93a386Sopenharmony_ci : fCurPos(attributeString) {} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_citemplate <typename F> 40cb93a386Sopenharmony_ciinline bool SkSVGAttributeParser::advanceWhile(F f) { 41cb93a386Sopenharmony_ci auto initial = fCurPos; 42cb93a386Sopenharmony_ci while (f(*fCurPos)) { 43cb93a386Sopenharmony_ci fCurPos++; 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci return fCurPos != initial; 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_cibool SkSVGAttributeParser::matchStringToken(const char* token, const char** newPos) const { 49cb93a386Sopenharmony_ci const char* c = fCurPos; 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci while (*c && *token && *c == *token) { 52cb93a386Sopenharmony_ci c++; 53cb93a386Sopenharmony_ci token++; 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci if (*token) { 57cb93a386Sopenharmony_ci return false; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci if (newPos) { 61cb93a386Sopenharmony_ci *newPos = c; 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci return true; 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseEOSToken() { 68cb93a386Sopenharmony_ci return is_eos(*fCurPos); 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseSepToken() { 72cb93a386Sopenharmony_ci return this->advanceWhile(is_sep); 73cb93a386Sopenharmony_ci} 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseWSToken() { 76cb93a386Sopenharmony_ci return this->advanceWhile(is_ws); 77cb93a386Sopenharmony_ci} 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseCommaWspToken() { 80cb93a386Sopenharmony_ci // comma-wsp: 81cb93a386Sopenharmony_ci // (wsp+ comma? wsp*) | (comma wsp*) 82cb93a386Sopenharmony_ci return this->parseWSToken() || this->parseExpectedStringToken(","); 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseExpectedStringToken(const char* expected) { 86cb93a386Sopenharmony_ci const char* newPos; 87cb93a386Sopenharmony_ci if (!matchStringToken(expected, &newPos)) { 88cb93a386Sopenharmony_ci return false; 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci fCurPos = newPos; 92cb93a386Sopenharmony_ci return true; 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseScalarToken(SkScalar* res) { 96cb93a386Sopenharmony_ci if (const char* next = SkParse::FindScalar(fCurPos, res)) { 97cb93a386Sopenharmony_ci fCurPos = next; 98cb93a386Sopenharmony_ci return true; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci return false; 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseInt32Token(int32_t* res) { 104cb93a386Sopenharmony_ci if (const char* next = SkParse::FindS32(fCurPos, res)) { 105cb93a386Sopenharmony_ci fCurPos = next; 106cb93a386Sopenharmony_ci return true; 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci return false; 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseHexToken(uint32_t* res) { 112cb93a386Sopenharmony_ci if (const char* next = SkParse::FindHex(fCurPos, res)) { 113cb93a386Sopenharmony_ci fCurPos = next; 114cb93a386Sopenharmony_ci return true; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci return false; 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseLengthUnitToken(SkSVGLength::Unit* unit) { 120cb93a386Sopenharmony_ci static const struct { 121cb93a386Sopenharmony_ci const char* fUnitName; 122cb93a386Sopenharmony_ci SkSVGLength::Unit fUnit; 123cb93a386Sopenharmony_ci } gUnitInfo[] = { 124cb93a386Sopenharmony_ci { "%" , SkSVGLength::Unit::kPercentage }, 125cb93a386Sopenharmony_ci { "em", SkSVGLength::Unit::kEMS }, 126cb93a386Sopenharmony_ci { "ex", SkSVGLength::Unit::kEXS }, 127cb93a386Sopenharmony_ci { "px", SkSVGLength::Unit::kPX }, 128cb93a386Sopenharmony_ci { "cm", SkSVGLength::Unit::kCM }, 129cb93a386Sopenharmony_ci { "mm", SkSVGLength::Unit::kMM }, 130cb93a386Sopenharmony_ci { "in", SkSVGLength::Unit::kIN }, 131cb93a386Sopenharmony_ci { "pt", SkSVGLength::Unit::kPT }, 132cb93a386Sopenharmony_ci { "pc", SkSVGLength::Unit::kPC }, 133cb93a386Sopenharmony_ci }; 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gUnitInfo); ++i) { 136cb93a386Sopenharmony_ci if (this->parseExpectedStringToken(gUnitInfo[i].fUnitName)) { 137cb93a386Sopenharmony_ci *unit = gUnitInfo[i].fUnit; 138cb93a386Sopenharmony_ci return true; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci } 141cb93a386Sopenharmony_ci return false; 142cb93a386Sopenharmony_ci} 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeColor 145cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseNamedColorToken(SkColor* c) { 146cb93a386Sopenharmony_ci if (const char* next = SkParse::FindNamedColor(fCurPos, strlen(fCurPos), c)) { 147cb93a386Sopenharmony_ci fCurPos = next; 148cb93a386Sopenharmony_ci return true; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci return false; 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseHexColorToken(SkColor* c) { 154cb93a386Sopenharmony_ci uint32_t v; 155cb93a386Sopenharmony_ci const char* initial = fCurPos; 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci if (!this->parseExpectedStringToken("#") || !this->parseHexToken(&v)) { 158cb93a386Sopenharmony_ci return false; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci switch (fCurPos - initial) { 162cb93a386Sopenharmony_ci case 7: 163cb93a386Sopenharmony_ci // matched #xxxxxxx 164cb93a386Sopenharmony_ci break; 165cb93a386Sopenharmony_ci case 4: 166cb93a386Sopenharmony_ci // matched '#xxx; 167cb93a386Sopenharmony_ci v = ((v << 12) & 0x00f00000) | 168cb93a386Sopenharmony_ci ((v << 8) & 0x000ff000) | 169cb93a386Sopenharmony_ci ((v << 4) & 0x00000ff0) | 170cb93a386Sopenharmony_ci ((v << 0) & 0x0000000f); 171cb93a386Sopenharmony_ci break; 172cb93a386Sopenharmony_ci default: 173cb93a386Sopenharmony_ci return false; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci *c = v | 0xff000000; 177cb93a386Sopenharmony_ci return true; 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseColorComponentToken(int32_t* c) { 181cb93a386Sopenharmony_ci const auto parseIntegral = [this](int32_t* c) -> bool { 182cb93a386Sopenharmony_ci const char* p = SkParse::FindS32(fCurPos, c); 183cb93a386Sopenharmony_ci if (!p || *p == '.') { 184cb93a386Sopenharmony_ci // No value parsed, or fractional value. 185cb93a386Sopenharmony_ci return false; 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci if (*p == '%') { 189cb93a386Sopenharmony_ci *c = SkScalarRoundToInt(*c * 255.0f / 100); 190cb93a386Sopenharmony_ci p++; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci fCurPos = p; 194cb93a386Sopenharmony_ci return true; 195cb93a386Sopenharmony_ci }; 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci const auto parseFractional = [this](int32_t* c) -> bool { 198cb93a386Sopenharmony_ci SkScalar s; 199cb93a386Sopenharmony_ci const char* p = SkParse::FindScalar(fCurPos, &s); 200cb93a386Sopenharmony_ci if (!p || *p != '%') { 201cb93a386Sopenharmony_ci // Floating point must be a percentage (CSS2 rgb-percent syntax). 202cb93a386Sopenharmony_ci return false; 203cb93a386Sopenharmony_ci } 204cb93a386Sopenharmony_ci p++; // Skip '%' 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci *c = SkScalarRoundToInt(s * 255.0f / 100); 207cb93a386Sopenharmony_ci fCurPos = p; 208cb93a386Sopenharmony_ci return true; 209cb93a386Sopenharmony_ci }; 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci if (!parseIntegral(c) && !parseFractional(c)) { 212cb93a386Sopenharmony_ci return false; 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci *c = SkTPin<int32_t>(*c, 0, 255); 216cb93a386Sopenharmony_ci return true; 217cb93a386Sopenharmony_ci} 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseRGBColorToken(SkColor* c) { 220cb93a386Sopenharmony_ci return this->parseParenthesized("rgb", [this](SkColor* c) -> bool { 221cb93a386Sopenharmony_ci int32_t r, g, b; 222cb93a386Sopenharmony_ci if (this->parseColorComponentToken(&r) && 223cb93a386Sopenharmony_ci this->parseSepToken() && 224cb93a386Sopenharmony_ci this->parseColorComponentToken(&g) && 225cb93a386Sopenharmony_ci this->parseSepToken() && 226cb93a386Sopenharmony_ci this->parseColorComponentToken(&b)) { 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci *c = SkColorSetRGB(static_cast<uint8_t>(r), 229cb93a386Sopenharmony_ci static_cast<uint8_t>(g), 230cb93a386Sopenharmony_ci static_cast<uint8_t>(b)); 231cb93a386Sopenharmony_ci return true; 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci return false; 234cb93a386Sopenharmony_ci }, c); 235cb93a386Sopenharmony_ci} 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeColor 238cb93a386Sopenharmony_ci// And https://www.w3.org/TR/CSS2/syndata.html#color-units for the alternative 239cb93a386Sopenharmony_ci// forms supported by SVG (e.g. RGB percentages). 240cb93a386Sopenharmony_citemplate <> 241cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGColorType* color) { 242cb93a386Sopenharmony_ci SkColor c; 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_ci // consume preceding whitespace 245cb93a386Sopenharmony_ci this->parseWSToken(); 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci bool parsedValue = false; 248cb93a386Sopenharmony_ci if (this->parseHexColorToken(&c) 249cb93a386Sopenharmony_ci || this->parseNamedColorToken(&c) 250cb93a386Sopenharmony_ci || this->parseRGBColorToken(&c)) { 251cb93a386Sopenharmony_ci *color = SkSVGColorType(c); 252cb93a386Sopenharmony_ci parsedValue = true; 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ci // consume trailing whitespace 255cb93a386Sopenharmony_ci this->parseWSToken(); 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 259cb93a386Sopenharmony_ci} 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#InterfaceSVGColor 262cb93a386Sopenharmony_citemplate <> 263cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGColor* color) { 264cb93a386Sopenharmony_ci SkSVGColorType c; 265cb93a386Sopenharmony_ci bool parsedValue = false; 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_ci if (this->parse(&c)) { 268cb93a386Sopenharmony_ci *color = SkSVGColor(c); 269cb93a386Sopenharmony_ci parsedValue = true; 270cb93a386Sopenharmony_ci } else if (this->parseExpectedStringToken("currentColor")) { 271cb93a386Sopenharmony_ci *color = SkSVGColor(SkSVGColor::Type::kCurrentColor); 272cb93a386Sopenharmony_ci parsedValue = true; 273cb93a386Sopenharmony_ci } 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 276cb93a386Sopenharmony_ci} 277cb93a386Sopenharmony_ci 278cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/linking.html#IRIReference 279cb93a386Sopenharmony_citemplate <> 280cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGIRI* iri) { 281cb93a386Sopenharmony_ci // consume preceding whitespace 282cb93a386Sopenharmony_ci this->parseWSToken(); 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci SkSVGIRI::Type iriType; 285cb93a386Sopenharmony_ci if (this->parseExpectedStringToken("#")) { 286cb93a386Sopenharmony_ci iriType = SkSVGIRI::Type::kLocal; 287cb93a386Sopenharmony_ci } else if (this->matchStringToken("data:")) { 288cb93a386Sopenharmony_ci iriType = SkSVGIRI::Type::kDataURI; 289cb93a386Sopenharmony_ci } else { 290cb93a386Sopenharmony_ci iriType = SkSVGIRI::Type::kNonlocal; 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci const auto* start = fCurPos; 294cb93a386Sopenharmony_ci this->advanceWhile([](char c) -> bool { return !is_eos(c) && c != ')'; }); 295cb93a386Sopenharmony_ci if (start == fCurPos) { 296cb93a386Sopenharmony_ci return false; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci *iri = SkSVGIRI(iriType, SkString(start, fCurPos - start)); 299cb93a386Sopenharmony_ci return true; 300cb93a386Sopenharmony_ci} 301cb93a386Sopenharmony_ci 302cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeFuncIRI 303cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseFuncIRI(SkSVGFuncIRI* iri) { 304cb93a386Sopenharmony_ci return this->parseParenthesized("url", [this](SkSVGFuncIRI* iriResult) -> bool { 305cb93a386Sopenharmony_ci SkSVGIRI iri; 306cb93a386Sopenharmony_ci if (this->parse(&iri)) { 307cb93a386Sopenharmony_ci *iriResult = SkSVGFuncIRI(std::move(iri)); 308cb93a386Sopenharmony_ci return true; 309cb93a386Sopenharmony_ci } 310cb93a386Sopenharmony_ci return false; 311cb93a386Sopenharmony_ci }, iri); 312cb93a386Sopenharmony_ci} 313cb93a386Sopenharmony_ci 314cb93a386Sopenharmony_citemplate <> 315cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGStringType* result) { 316cb93a386Sopenharmony_ci if (this->parseEOSToken()) { 317cb93a386Sopenharmony_ci return false; 318cb93a386Sopenharmony_ci } 319cb93a386Sopenharmony_ci *result = SkSVGStringType(fCurPos); 320cb93a386Sopenharmony_ci fCurPos += result->size(); 321cb93a386Sopenharmony_ci return this->parseEOSToken(); 322cb93a386Sopenharmony_ci} 323cb93a386Sopenharmony_ci 324cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeNumber 325cb93a386Sopenharmony_citemplate <> 326cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGNumberType* number) { 327cb93a386Sopenharmony_ci // consume WS 328cb93a386Sopenharmony_ci this->parseWSToken(); 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci SkScalar s; 331cb93a386Sopenharmony_ci if (this->parseScalarToken(&s)) { 332cb93a386Sopenharmony_ci *number = SkSVGNumberType(s); 333cb93a386Sopenharmony_ci // consume trailing separators 334cb93a386Sopenharmony_ci this->parseSepToken(); 335cb93a386Sopenharmony_ci return true; 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ci return false; 339cb93a386Sopenharmony_ci} 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeInteger 342cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseInteger(SkSVGIntegerType* number) { 343cb93a386Sopenharmony_ci // consume WS 344cb93a386Sopenharmony_ci this->parseWSToken(); 345cb93a386Sopenharmony_ci 346cb93a386Sopenharmony_ci // consume optional '+' 347cb93a386Sopenharmony_ci this->parseExpectedStringToken("+"); 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ci SkSVGIntegerType i; 350cb93a386Sopenharmony_ci if (this->parseInt32Token(&i)) { 351cb93a386Sopenharmony_ci *number = SkSVGNumberType(i); 352cb93a386Sopenharmony_ci // consume trailing separators 353cb93a386Sopenharmony_ci this->parseSepToken(); 354cb93a386Sopenharmony_ci return true; 355cb93a386Sopenharmony_ci } 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci return false; 358cb93a386Sopenharmony_ci} 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeLength 361cb93a386Sopenharmony_citemplate <> 362cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGLength* length) { 363cb93a386Sopenharmony_ci SkScalar s; 364cb93a386Sopenharmony_ci SkSVGLength::Unit u = SkSVGLength::Unit::kNumber; 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_ci if (this->parseScalarToken(&s) && 367cb93a386Sopenharmony_ci (this->parseLengthUnitToken(&u) || this->parseSepToken() || this->parseEOSToken())) { 368cb93a386Sopenharmony_ci *length = SkSVGLength(s, u); 369cb93a386Sopenharmony_ci // consume trailing separators 370cb93a386Sopenharmony_ci this->parseSepToken(); 371cb93a386Sopenharmony_ci return true; 372cb93a386Sopenharmony_ci } 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_ci return false; 375cb93a386Sopenharmony_ci} 376cb93a386Sopenharmony_ci 377cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute 378cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseViewBox(SkSVGViewBoxType* vb) { 379cb93a386Sopenharmony_ci SkScalar x, y, w, h; 380cb93a386Sopenharmony_ci this->parseWSToken(); 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ci bool parsedValue = false; 383cb93a386Sopenharmony_ci if (this->parseScalarToken(&x) && this->parseSepToken() && 384cb93a386Sopenharmony_ci this->parseScalarToken(&y) && this->parseSepToken() && 385cb93a386Sopenharmony_ci this->parseScalarToken(&w) && this->parseSepToken() && 386cb93a386Sopenharmony_ci this->parseScalarToken(&h)) { 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci *vb = SkSVGViewBoxType(SkRect::MakeXYWH(x, y, w, h)); 389cb93a386Sopenharmony_ci parsedValue = true; 390cb93a386Sopenharmony_ci // consume trailing whitespace 391cb93a386Sopenharmony_ci this->parseWSToken(); 392cb93a386Sopenharmony_ci } 393cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 394cb93a386Sopenharmony_ci} 395cb93a386Sopenharmony_ci 396cb93a386Sopenharmony_citemplate <typename Func, typename T> 397cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseParenthesized(const char* prefix, Func f, T* result) { 398cb93a386Sopenharmony_ci this->parseWSToken(); 399cb93a386Sopenharmony_ci if (prefix && !this->parseExpectedStringToken(prefix)) { 400cb93a386Sopenharmony_ci return false; 401cb93a386Sopenharmony_ci } 402cb93a386Sopenharmony_ci this->parseWSToken(); 403cb93a386Sopenharmony_ci if (!this->parseExpectedStringToken("(")) { 404cb93a386Sopenharmony_ci return false; 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci this->parseWSToken(); 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_ci if (!f(result)) { 409cb93a386Sopenharmony_ci return false; 410cb93a386Sopenharmony_ci } 411cb93a386Sopenharmony_ci this->parseWSToken(); 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ci return this->parseExpectedStringToken(")"); 414cb93a386Sopenharmony_ci} 415cb93a386Sopenharmony_ci 416cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseMatrixToken(SkMatrix* matrix) { 417cb93a386Sopenharmony_ci return this->parseParenthesized("matrix", [this](SkMatrix* m) -> bool { 418cb93a386Sopenharmony_ci SkScalar scalars[6]; 419cb93a386Sopenharmony_ci for (int i = 0; i < 6; ++i) { 420cb93a386Sopenharmony_ci if (!(this->parseScalarToken(scalars + i) && 421cb93a386Sopenharmony_ci (i > 4 || this->parseSepToken()))) { 422cb93a386Sopenharmony_ci return false; 423cb93a386Sopenharmony_ci } 424cb93a386Sopenharmony_ci } 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_ci m->setAll(scalars[0], scalars[2], scalars[4], scalars[1], scalars[3], scalars[5], 0, 0, 1); 427cb93a386Sopenharmony_ci return true; 428cb93a386Sopenharmony_ci }, matrix); 429cb93a386Sopenharmony_ci} 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseTranslateToken(SkMatrix* matrix) { 432cb93a386Sopenharmony_ci return this->parseParenthesized("translate", [this](SkMatrix* m) -> bool { 433cb93a386Sopenharmony_ci SkScalar tx = 0.0, ty = 0.0; 434cb93a386Sopenharmony_ci this->parseWSToken(); 435cb93a386Sopenharmony_ci if (!this->parseScalarToken(&tx)) { 436cb93a386Sopenharmony_ci return false; 437cb93a386Sopenharmony_ci } 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_ci if (!this->parseSepToken() || !this->parseScalarToken(&ty)) { 440cb93a386Sopenharmony_ci ty = 0.0; 441cb93a386Sopenharmony_ci } 442cb93a386Sopenharmony_ci 443cb93a386Sopenharmony_ci m->setTranslate(tx, ty); 444cb93a386Sopenharmony_ci return true; 445cb93a386Sopenharmony_ci }, matrix); 446cb93a386Sopenharmony_ci} 447cb93a386Sopenharmony_ci 448cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseScaleToken(SkMatrix* matrix) { 449cb93a386Sopenharmony_ci return this->parseParenthesized("scale", [this](SkMatrix* m) -> bool { 450cb93a386Sopenharmony_ci SkScalar sx = 0.0, sy = 0.0; 451cb93a386Sopenharmony_ci if (!this->parseScalarToken(&sx)) { 452cb93a386Sopenharmony_ci return false; 453cb93a386Sopenharmony_ci } 454cb93a386Sopenharmony_ci 455cb93a386Sopenharmony_ci if (!(this->parseSepToken() && this->parseScalarToken(&sy))) { 456cb93a386Sopenharmony_ci sy = sx; 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci 459cb93a386Sopenharmony_ci m->setScale(sx, sy); 460cb93a386Sopenharmony_ci return true; 461cb93a386Sopenharmony_ci }, matrix); 462cb93a386Sopenharmony_ci} 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseRotateToken(SkMatrix* matrix) { 465cb93a386Sopenharmony_ci return this->parseParenthesized("rotate", [this](SkMatrix* m) -> bool { 466cb93a386Sopenharmony_ci SkScalar angle; 467cb93a386Sopenharmony_ci if (!this->parseScalarToken(&angle)) { 468cb93a386Sopenharmony_ci return false; 469cb93a386Sopenharmony_ci } 470cb93a386Sopenharmony_ci 471cb93a386Sopenharmony_ci SkScalar cx = 0; 472cb93a386Sopenharmony_ci SkScalar cy = 0; 473cb93a386Sopenharmony_ci // optional [<cx> <cy>] 474cb93a386Sopenharmony_ci if (this->parseSepToken() && this->parseScalarToken(&cx)) { 475cb93a386Sopenharmony_ci if (!(this->parseSepToken() && this->parseScalarToken(&cy))) { 476cb93a386Sopenharmony_ci return false; 477cb93a386Sopenharmony_ci } 478cb93a386Sopenharmony_ci } 479cb93a386Sopenharmony_ci 480cb93a386Sopenharmony_ci m->setRotate(angle, cx, cy); 481cb93a386Sopenharmony_ci return true; 482cb93a386Sopenharmony_ci }, matrix); 483cb93a386Sopenharmony_ci} 484cb93a386Sopenharmony_ci 485cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseSkewXToken(SkMatrix* matrix) { 486cb93a386Sopenharmony_ci return this->parseParenthesized("skewX", [this](SkMatrix* m) -> bool { 487cb93a386Sopenharmony_ci SkScalar angle; 488cb93a386Sopenharmony_ci if (!this->parseScalarToken(&angle)) { 489cb93a386Sopenharmony_ci return false; 490cb93a386Sopenharmony_ci } 491cb93a386Sopenharmony_ci m->setSkewX(tanf(SkDegreesToRadians(angle))); 492cb93a386Sopenharmony_ci return true; 493cb93a386Sopenharmony_ci }, matrix); 494cb93a386Sopenharmony_ci} 495cb93a386Sopenharmony_ci 496cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseSkewYToken(SkMatrix* matrix) { 497cb93a386Sopenharmony_ci return this->parseParenthesized("skewY", [this](SkMatrix* m) -> bool { 498cb93a386Sopenharmony_ci SkScalar angle; 499cb93a386Sopenharmony_ci if (!this->parseScalarToken(&angle)) { 500cb93a386Sopenharmony_ci return false; 501cb93a386Sopenharmony_ci } 502cb93a386Sopenharmony_ci m->setSkewY(tanf(SkDegreesToRadians(angle))); 503cb93a386Sopenharmony_ci return true; 504cb93a386Sopenharmony_ci }, matrix); 505cb93a386Sopenharmony_ci} 506cb93a386Sopenharmony_ci 507cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/coords.html#TransformAttribute 508cb93a386Sopenharmony_citemplate <> 509cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGTransformType* t) { 510cb93a386Sopenharmony_ci SkMatrix matrix = SkMatrix::I(); 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_ci bool parsed = false; 513cb93a386Sopenharmony_ci while (true) { 514cb93a386Sopenharmony_ci SkMatrix m; 515cb93a386Sopenharmony_ci 516cb93a386Sopenharmony_ci if (!( this->parseMatrixToken(&m) 517cb93a386Sopenharmony_ci || this->parseTranslateToken(&m) 518cb93a386Sopenharmony_ci || this->parseScaleToken(&m) 519cb93a386Sopenharmony_ci || this->parseRotateToken(&m) 520cb93a386Sopenharmony_ci || this->parseSkewXToken(&m) 521cb93a386Sopenharmony_ci || this->parseSkewYToken(&m))) { 522cb93a386Sopenharmony_ci break; 523cb93a386Sopenharmony_ci } 524cb93a386Sopenharmony_ci 525cb93a386Sopenharmony_ci matrix.preConcat(m); 526cb93a386Sopenharmony_ci parsed = true; 527cb93a386Sopenharmony_ci 528cb93a386Sopenharmony_ci this->parseCommaWspToken(); 529cb93a386Sopenharmony_ci } 530cb93a386Sopenharmony_ci 531cb93a386Sopenharmony_ci this->parseWSToken(); 532cb93a386Sopenharmony_ci if (!parsed || !this->parseEOSToken()) { 533cb93a386Sopenharmony_ci return false; 534cb93a386Sopenharmony_ci } 535cb93a386Sopenharmony_ci 536cb93a386Sopenharmony_ci *t = SkSVGTransformType(matrix); 537cb93a386Sopenharmony_ci return true; 538cb93a386Sopenharmony_ci} 539cb93a386Sopenharmony_ci 540cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#SpecifyingPaint 541cb93a386Sopenharmony_citemplate <> 542cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGPaint* paint) { 543cb93a386Sopenharmony_ci SkSVGColor c; 544cb93a386Sopenharmony_ci SkSVGFuncIRI iri; 545cb93a386Sopenharmony_ci bool parsedValue = false; 546cb93a386Sopenharmony_ci if (this->parse(&c)) { 547cb93a386Sopenharmony_ci *paint = SkSVGPaint(c); 548cb93a386Sopenharmony_ci parsedValue = true; 549cb93a386Sopenharmony_ci } else if (this->parseExpectedStringToken("none")) { 550cb93a386Sopenharmony_ci *paint = SkSVGPaint(SkSVGPaint::Type::kNone); 551cb93a386Sopenharmony_ci parsedValue = true; 552cb93a386Sopenharmony_ci } else if (this->parseFuncIRI(&iri)) { 553cb93a386Sopenharmony_ci // optional fallback color 554cb93a386Sopenharmony_ci this->parse(&c); 555cb93a386Sopenharmony_ci *paint = SkSVGPaint(iri.iri(), c); 556cb93a386Sopenharmony_ci parsedValue = true; 557cb93a386Sopenharmony_ci } 558cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 559cb93a386Sopenharmony_ci} 560cb93a386Sopenharmony_ci 561cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/masking.html#ClipPathProperty 562cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/masking.html#MaskProperty 563cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/filters.html#FilterProperty 564cb93a386Sopenharmony_citemplate <> 565cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGFuncIRI* firi) { 566cb93a386Sopenharmony_ci SkSVGStringType iri; 567cb93a386Sopenharmony_ci bool parsedValue = false; 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci if (this->parseExpectedStringToken("none")) { 570cb93a386Sopenharmony_ci *firi = SkSVGFuncIRI(); 571cb93a386Sopenharmony_ci parsedValue = true; 572cb93a386Sopenharmony_ci } else if (this->parseFuncIRI(firi)) { 573cb93a386Sopenharmony_ci parsedValue = true; 574cb93a386Sopenharmony_ci } 575cb93a386Sopenharmony_ci 576cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 577cb93a386Sopenharmony_ci} 578cb93a386Sopenharmony_ci 579cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty 580cb93a386Sopenharmony_citemplate <> 581cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGLineCap* cap) { 582cb93a386Sopenharmony_ci static const struct { 583cb93a386Sopenharmony_ci SkSVGLineCap fType; 584cb93a386Sopenharmony_ci const char* fName; 585cb93a386Sopenharmony_ci } gCapInfo[] = { 586cb93a386Sopenharmony_ci { SkSVGLineCap::kButt , "butt" }, 587cb93a386Sopenharmony_ci { SkSVGLineCap::kRound , "round" }, 588cb93a386Sopenharmony_ci { SkSVGLineCap::kSquare , "square" }, 589cb93a386Sopenharmony_ci }; 590cb93a386Sopenharmony_ci 591cb93a386Sopenharmony_ci bool parsedValue = false; 592cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gCapInfo); ++i) { 593cb93a386Sopenharmony_ci if (this->parseExpectedStringToken(gCapInfo[i].fName)) { 594cb93a386Sopenharmony_ci *cap = SkSVGLineCap(gCapInfo[i].fType); 595cb93a386Sopenharmony_ci parsedValue = true; 596cb93a386Sopenharmony_ci break; 597cb93a386Sopenharmony_ci } 598cb93a386Sopenharmony_ci } 599cb93a386Sopenharmony_ci 600cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 601cb93a386Sopenharmony_ci} 602cb93a386Sopenharmony_ci 603cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty 604cb93a386Sopenharmony_citemplate <> 605cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGLineJoin* join) { 606cb93a386Sopenharmony_ci static const struct { 607cb93a386Sopenharmony_ci SkSVGLineJoin::Type fType; 608cb93a386Sopenharmony_ci const char* fName; 609cb93a386Sopenharmony_ci } gJoinInfo[] = { 610cb93a386Sopenharmony_ci { SkSVGLineJoin::Type::kMiter , "miter" }, 611cb93a386Sopenharmony_ci { SkSVGLineJoin::Type::kRound , "round" }, 612cb93a386Sopenharmony_ci { SkSVGLineJoin::Type::kBevel , "bevel" }, 613cb93a386Sopenharmony_ci { SkSVGLineJoin::Type::kInherit, "inherit" }, 614cb93a386Sopenharmony_ci }; 615cb93a386Sopenharmony_ci 616cb93a386Sopenharmony_ci bool parsedValue = false; 617cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gJoinInfo); ++i) { 618cb93a386Sopenharmony_ci if (this->parseExpectedStringToken(gJoinInfo[i].fName)) { 619cb93a386Sopenharmony_ci *join = SkSVGLineJoin(gJoinInfo[i].fType); 620cb93a386Sopenharmony_ci parsedValue = true; 621cb93a386Sopenharmony_ci break; 622cb93a386Sopenharmony_ci } 623cb93a386Sopenharmony_ci } 624cb93a386Sopenharmony_ci 625cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 626cb93a386Sopenharmony_ci} 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBoxUnits 629cb93a386Sopenharmony_citemplate <> 630cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGObjectBoundingBoxUnits* objectBoundingBoxUnits) { 631cb93a386Sopenharmony_ci bool parsedValue = false; 632cb93a386Sopenharmony_ci if (this->parseExpectedStringToken("userSpaceOnUse")) { 633cb93a386Sopenharmony_ci *objectBoundingBoxUnits = 634cb93a386Sopenharmony_ci SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kUserSpaceOnUse); 635cb93a386Sopenharmony_ci parsedValue = true; 636cb93a386Sopenharmony_ci } else if (this->parseExpectedStringToken("objectBoundingBox")) { 637cb93a386Sopenharmony_ci *objectBoundingBoxUnits = 638cb93a386Sopenharmony_ci SkSVGObjectBoundingBoxUnits(SkSVGObjectBoundingBoxUnits::Type::kObjectBoundingBox); 639cb93a386Sopenharmony_ci parsedValue = true; 640cb93a386Sopenharmony_ci } 641cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 642cb93a386Sopenharmony_ci} 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/shapes.html#PolygonElementPointsAttribute 645cb93a386Sopenharmony_citemplate <> 646cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGPointsType* points) { 647cb93a386Sopenharmony_ci SkTDArray<SkPoint> pts; 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_ci // Skip initial wsp. 650cb93a386Sopenharmony_ci // list-of-points: 651cb93a386Sopenharmony_ci // wsp* coordinate-pairs? wsp* 652cb93a386Sopenharmony_ci this->advanceWhile(is_ws); 653cb93a386Sopenharmony_ci 654cb93a386Sopenharmony_ci bool parsedValue = false; 655cb93a386Sopenharmony_ci for (;;) { 656cb93a386Sopenharmony_ci // Adjacent coordinate-pairs separated by comma-wsp. 657cb93a386Sopenharmony_ci // coordinate-pairs: 658cb93a386Sopenharmony_ci // coordinate-pair 659cb93a386Sopenharmony_ci // | coordinate-pair comma-wsp coordinate-pairs 660cb93a386Sopenharmony_ci if (parsedValue && !this->parseCommaWspToken()) { 661cb93a386Sopenharmony_ci break; 662cb93a386Sopenharmony_ci } 663cb93a386Sopenharmony_ci 664cb93a386Sopenharmony_ci SkScalar x, y; 665cb93a386Sopenharmony_ci if (!this->parseScalarToken(&x)) { 666cb93a386Sopenharmony_ci break; 667cb93a386Sopenharmony_ci } 668cb93a386Sopenharmony_ci 669cb93a386Sopenharmony_ci // Coordinate values separated by comma-wsp or '-'. 670cb93a386Sopenharmony_ci // coordinate-pair: 671cb93a386Sopenharmony_ci // coordinate comma-wsp coordinate 672cb93a386Sopenharmony_ci // | coordinate negative-coordinate 673cb93a386Sopenharmony_ci if (!this->parseCommaWspToken() && !this->parseEOSToken() && *fCurPos != '-') { 674cb93a386Sopenharmony_ci break; 675cb93a386Sopenharmony_ci } 676cb93a386Sopenharmony_ci 677cb93a386Sopenharmony_ci if (!this->parseScalarToken(&y)) { 678cb93a386Sopenharmony_ci break; 679cb93a386Sopenharmony_ci } 680cb93a386Sopenharmony_ci 681cb93a386Sopenharmony_ci pts.push_back(SkPoint::Make(x, y)); 682cb93a386Sopenharmony_ci parsedValue = true; 683cb93a386Sopenharmony_ci } 684cb93a386Sopenharmony_ci 685cb93a386Sopenharmony_ci if (parsedValue && this->parseEOSToken()) { 686cb93a386Sopenharmony_ci *points = pts; 687cb93a386Sopenharmony_ci return true; 688cb93a386Sopenharmony_ci } 689cb93a386Sopenharmony_ci 690cb93a386Sopenharmony_ci return false; 691cb93a386Sopenharmony_ci} 692cb93a386Sopenharmony_ci 693cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#FillRuleProperty 694cb93a386Sopenharmony_citemplate <> 695cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGFillRule* fillRule) { 696cb93a386Sopenharmony_ci static const struct { 697cb93a386Sopenharmony_ci SkSVGFillRule::Type fType; 698cb93a386Sopenharmony_ci const char* fName; 699cb93a386Sopenharmony_ci } gFillRuleInfo[] = { 700cb93a386Sopenharmony_ci { SkSVGFillRule::Type::kNonZero, "nonzero" }, 701cb93a386Sopenharmony_ci { SkSVGFillRule::Type::kEvenOdd, "evenodd" }, 702cb93a386Sopenharmony_ci { SkSVGFillRule::Type::kInherit, "inherit" }, 703cb93a386Sopenharmony_ci }; 704cb93a386Sopenharmony_ci 705cb93a386Sopenharmony_ci bool parsedValue = false; 706cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(gFillRuleInfo); ++i) { 707cb93a386Sopenharmony_ci if (this->parseExpectedStringToken(gFillRuleInfo[i].fName)) { 708cb93a386Sopenharmony_ci *fillRule = SkSVGFillRule(gFillRuleInfo[i].fType); 709cb93a386Sopenharmony_ci parsedValue = true; 710cb93a386Sopenharmony_ci break; 711cb93a386Sopenharmony_ci } 712cb93a386Sopenharmony_ci } 713cb93a386Sopenharmony_ci 714cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 715cb93a386Sopenharmony_ci} 716cb93a386Sopenharmony_ci 717cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#VisibilityProperty 718cb93a386Sopenharmony_citemplate <> 719cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGVisibility* visibility) { 720cb93a386Sopenharmony_ci static const struct { 721cb93a386Sopenharmony_ci SkSVGVisibility::Type fType; 722cb93a386Sopenharmony_ci const char* fName; 723cb93a386Sopenharmony_ci } gVisibilityInfo[] = { 724cb93a386Sopenharmony_ci { SkSVGVisibility::Type::kVisible , "visible" }, 725cb93a386Sopenharmony_ci { SkSVGVisibility::Type::kHidden , "hidden" }, 726cb93a386Sopenharmony_ci { SkSVGVisibility::Type::kCollapse, "collapse" }, 727cb93a386Sopenharmony_ci { SkSVGVisibility::Type::kInherit , "inherit" }, 728cb93a386Sopenharmony_ci }; 729cb93a386Sopenharmony_ci 730cb93a386Sopenharmony_ci bool parsedValue = false; 731cb93a386Sopenharmony_ci for (const auto& parseInfo : gVisibilityInfo) { 732cb93a386Sopenharmony_ci if (this->parseExpectedStringToken(parseInfo.fName)) { 733cb93a386Sopenharmony_ci *visibility = SkSVGVisibility(parseInfo.fType); 734cb93a386Sopenharmony_ci parsedValue = true; 735cb93a386Sopenharmony_ci break; 736cb93a386Sopenharmony_ci } 737cb93a386Sopenharmony_ci } 738cb93a386Sopenharmony_ci 739cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 740cb93a386Sopenharmony_ci} 741cb93a386Sopenharmony_ci 742cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty 743cb93a386Sopenharmony_citemplate <> 744cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGDashArray* dashArray) { 745cb93a386Sopenharmony_ci bool parsedValue = false; 746cb93a386Sopenharmony_ci if (this->parseExpectedStringToken("none")) { 747cb93a386Sopenharmony_ci *dashArray = SkSVGDashArray(SkSVGDashArray::Type::kNone); 748cb93a386Sopenharmony_ci parsedValue = true; 749cb93a386Sopenharmony_ci } else if (this->parseExpectedStringToken("inherit")) { 750cb93a386Sopenharmony_ci *dashArray = SkSVGDashArray(SkSVGDashArray::Type::kInherit); 751cb93a386Sopenharmony_ci parsedValue = true; 752cb93a386Sopenharmony_ci } else { 753cb93a386Sopenharmony_ci SkTDArray<SkSVGLength> dashes; 754cb93a386Sopenharmony_ci for (;;) { 755cb93a386Sopenharmony_ci SkSVGLength dash; 756cb93a386Sopenharmony_ci // parseLength() also consumes trailing separators. 757cb93a386Sopenharmony_ci if (!this->parse(&dash)) { 758cb93a386Sopenharmony_ci break; 759cb93a386Sopenharmony_ci } 760cb93a386Sopenharmony_ci 761cb93a386Sopenharmony_ci dashes.push_back(dash); 762cb93a386Sopenharmony_ci parsedValue = true; 763cb93a386Sopenharmony_ci } 764cb93a386Sopenharmony_ci 765cb93a386Sopenharmony_ci if (parsedValue) { 766cb93a386Sopenharmony_ci *dashArray = SkSVGDashArray(std::move(dashes)); 767cb93a386Sopenharmony_ci } 768cb93a386Sopenharmony_ci } 769cb93a386Sopenharmony_ci 770cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 771cb93a386Sopenharmony_ci} 772cb93a386Sopenharmony_ci 773cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/text.html#FontFamilyProperty 774cb93a386Sopenharmony_citemplate <> 775cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGFontFamily* family) { 776cb93a386Sopenharmony_ci bool parsedValue = false; 777cb93a386Sopenharmony_ci if (this->parseExpectedStringToken("inherit")) { 778cb93a386Sopenharmony_ci *family = SkSVGFontFamily(); 779cb93a386Sopenharmony_ci parsedValue = true; 780cb93a386Sopenharmony_ci } else { 781cb93a386Sopenharmony_ci // The spec allows specifying a comma-separated list for explicit fallback order. 782cb93a386Sopenharmony_ci // For now, we only use the first entry and rely on the font manager to handle fallback. 783cb93a386Sopenharmony_ci const auto* comma = strchr(fCurPos, ','); 784cb93a386Sopenharmony_ci auto family_name = comma ? SkString(fCurPos, comma - fCurPos) 785cb93a386Sopenharmony_ci : SkString(fCurPos); 786cb93a386Sopenharmony_ci *family = SkSVGFontFamily(family_name.c_str()); 787cb93a386Sopenharmony_ci fCurPos += strlen(fCurPos); 788cb93a386Sopenharmony_ci parsedValue = true; 789cb93a386Sopenharmony_ci } 790cb93a386Sopenharmony_ci 791cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 792cb93a386Sopenharmony_ci} 793cb93a386Sopenharmony_ci 794cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/text.html#FontSizeProperty 795cb93a386Sopenharmony_citemplate <> 796cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGFontSize* size) { 797cb93a386Sopenharmony_ci bool parsedValue = false; 798cb93a386Sopenharmony_ci if (this->parseExpectedStringToken("inherit")) { 799cb93a386Sopenharmony_ci *size = SkSVGFontSize(); 800cb93a386Sopenharmony_ci parsedValue = true; 801cb93a386Sopenharmony_ci } else { 802cb93a386Sopenharmony_ci SkSVGLength length; 803cb93a386Sopenharmony_ci if (this->parse(&length)) { 804cb93a386Sopenharmony_ci *size = SkSVGFontSize(length); 805cb93a386Sopenharmony_ci parsedValue = true; 806cb93a386Sopenharmony_ci } 807cb93a386Sopenharmony_ci } 808cb93a386Sopenharmony_ci 809cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 810cb93a386Sopenharmony_ci} 811cb93a386Sopenharmony_ci 812cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/text.html#FontStyleProperty 813cb93a386Sopenharmony_citemplate <> 814cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGFontStyle* style) { 815cb93a386Sopenharmony_ci static constexpr std::tuple<const char*, SkSVGFontStyle::Type> gStyleMap[] = { 816cb93a386Sopenharmony_ci { "normal" , SkSVGFontStyle::Type::kNormal }, 817cb93a386Sopenharmony_ci { "italic" , SkSVGFontStyle::Type::kItalic }, 818cb93a386Sopenharmony_ci { "oblique", SkSVGFontStyle::Type::kOblique }, 819cb93a386Sopenharmony_ci { "inherit", SkSVGFontStyle::Type::kInherit }, 820cb93a386Sopenharmony_ci }; 821cb93a386Sopenharmony_ci 822cb93a386Sopenharmony_ci bool parsedValue = false; 823cb93a386Sopenharmony_ci SkSVGFontStyle::Type type; 824cb93a386Sopenharmony_ci 825cb93a386Sopenharmony_ci if (this->parseEnumMap(gStyleMap, &type)) { 826cb93a386Sopenharmony_ci *style = SkSVGFontStyle(type); 827cb93a386Sopenharmony_ci parsedValue = true; 828cb93a386Sopenharmony_ci } 829cb93a386Sopenharmony_ci 830cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 831cb93a386Sopenharmony_ci} 832cb93a386Sopenharmony_ci 833cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/text.html#FontWeightProperty 834cb93a386Sopenharmony_citemplate <> 835cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGFontWeight* weight) { 836cb93a386Sopenharmony_ci static constexpr std::tuple<const char*, SkSVGFontWeight::Type> gWeightMap[] = { 837cb93a386Sopenharmony_ci { "normal" , SkSVGFontWeight::Type::kNormal }, 838cb93a386Sopenharmony_ci { "bold" , SkSVGFontWeight::Type::kBold }, 839cb93a386Sopenharmony_ci { "bolder" , SkSVGFontWeight::Type::kBolder }, 840cb93a386Sopenharmony_ci { "lighter", SkSVGFontWeight::Type::kLighter }, 841cb93a386Sopenharmony_ci { "100" , SkSVGFontWeight::Type::k100 }, 842cb93a386Sopenharmony_ci { "200" , SkSVGFontWeight::Type::k200 }, 843cb93a386Sopenharmony_ci { "300" , SkSVGFontWeight::Type::k300 }, 844cb93a386Sopenharmony_ci { "400" , SkSVGFontWeight::Type::k400 }, 845cb93a386Sopenharmony_ci { "500" , SkSVGFontWeight::Type::k500 }, 846cb93a386Sopenharmony_ci { "600" , SkSVGFontWeight::Type::k600 }, 847cb93a386Sopenharmony_ci { "700" , SkSVGFontWeight::Type::k700 }, 848cb93a386Sopenharmony_ci { "800" , SkSVGFontWeight::Type::k800 }, 849cb93a386Sopenharmony_ci { "900" , SkSVGFontWeight::Type::k900 }, 850cb93a386Sopenharmony_ci { "inherit", SkSVGFontWeight::Type::kInherit }, 851cb93a386Sopenharmony_ci }; 852cb93a386Sopenharmony_ci 853cb93a386Sopenharmony_ci bool parsedValue = false; 854cb93a386Sopenharmony_ci SkSVGFontWeight::Type type; 855cb93a386Sopenharmony_ci 856cb93a386Sopenharmony_ci if (this->parseEnumMap(gWeightMap, &type)) { 857cb93a386Sopenharmony_ci *weight = SkSVGFontWeight(type); 858cb93a386Sopenharmony_ci parsedValue = true; 859cb93a386Sopenharmony_ci } 860cb93a386Sopenharmony_ci 861cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 862cb93a386Sopenharmony_ci} 863cb93a386Sopenharmony_ci 864cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/text.html#TextAnchorProperty 865cb93a386Sopenharmony_citemplate <> 866cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGTextAnchor* anchor) { 867cb93a386Sopenharmony_ci static constexpr std::tuple<const char*, SkSVGTextAnchor::Type> gAnchorMap[] = { 868cb93a386Sopenharmony_ci { "start" , SkSVGTextAnchor::Type::kStart }, 869cb93a386Sopenharmony_ci { "middle" , SkSVGTextAnchor::Type::kMiddle }, 870cb93a386Sopenharmony_ci { "end" , SkSVGTextAnchor::Type::kEnd }, 871cb93a386Sopenharmony_ci { "inherit", SkSVGTextAnchor::Type::kInherit}, 872cb93a386Sopenharmony_ci }; 873cb93a386Sopenharmony_ci 874cb93a386Sopenharmony_ci bool parsedValue = false; 875cb93a386Sopenharmony_ci SkSVGTextAnchor::Type type; 876cb93a386Sopenharmony_ci 877cb93a386Sopenharmony_ci if (this->parseEnumMap(gAnchorMap, &type)) { 878cb93a386Sopenharmony_ci *anchor = SkSVGTextAnchor(type); 879cb93a386Sopenharmony_ci parsedValue = true; 880cb93a386Sopenharmony_ci } 881cb93a386Sopenharmony_ci 882cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 883cb93a386Sopenharmony_ci} 884cb93a386Sopenharmony_ci 885cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/coords.html#PreserveAspectRatioAttribute 886cb93a386Sopenharmony_cibool SkSVGAttributeParser::parsePreserveAspectRatio(SkSVGPreserveAspectRatio* par) { 887cb93a386Sopenharmony_ci static constexpr std::tuple<const char*, SkSVGPreserveAspectRatio::Align> gAlignMap[] = { 888cb93a386Sopenharmony_ci { "none" , SkSVGPreserveAspectRatio::kNone }, 889cb93a386Sopenharmony_ci { "xMinYMin", SkSVGPreserveAspectRatio::kXMinYMin }, 890cb93a386Sopenharmony_ci { "xMidYMin", SkSVGPreserveAspectRatio::kXMidYMin }, 891cb93a386Sopenharmony_ci { "xMaxYMin", SkSVGPreserveAspectRatio::kXMaxYMin }, 892cb93a386Sopenharmony_ci { "xMinYMid", SkSVGPreserveAspectRatio::kXMinYMid }, 893cb93a386Sopenharmony_ci { "xMidYMid", SkSVGPreserveAspectRatio::kXMidYMid }, 894cb93a386Sopenharmony_ci { "xMaxYMid", SkSVGPreserveAspectRatio::kXMaxYMid }, 895cb93a386Sopenharmony_ci { "xMinYMax", SkSVGPreserveAspectRatio::kXMinYMax }, 896cb93a386Sopenharmony_ci { "xMidYMax", SkSVGPreserveAspectRatio::kXMidYMax }, 897cb93a386Sopenharmony_ci { "xMaxYMax", SkSVGPreserveAspectRatio::kXMaxYMax }, 898cb93a386Sopenharmony_ci }; 899cb93a386Sopenharmony_ci 900cb93a386Sopenharmony_ci static constexpr std::tuple<const char*, SkSVGPreserveAspectRatio::Scale> gScaleMap[] = { 901cb93a386Sopenharmony_ci { "meet" , SkSVGPreserveAspectRatio::kMeet }, 902cb93a386Sopenharmony_ci { "slice", SkSVGPreserveAspectRatio::kSlice }, 903cb93a386Sopenharmony_ci }; 904cb93a386Sopenharmony_ci 905cb93a386Sopenharmony_ci bool parsedValue = false; 906cb93a386Sopenharmony_ci 907cb93a386Sopenharmony_ci // ignoring optional 'defer' 908cb93a386Sopenharmony_ci this->parseExpectedStringToken("defer"); 909cb93a386Sopenharmony_ci this->parseWSToken(); 910cb93a386Sopenharmony_ci 911cb93a386Sopenharmony_ci if (this->parseEnumMap(gAlignMap, &par->fAlign)) { 912cb93a386Sopenharmony_ci parsedValue = true; 913cb93a386Sopenharmony_ci 914cb93a386Sopenharmony_ci // optional scaling selector 915cb93a386Sopenharmony_ci this->parseWSToken(); 916cb93a386Sopenharmony_ci this->parseEnumMap(gScaleMap, &par->fScale); 917cb93a386Sopenharmony_ci } 918cb93a386Sopenharmony_ci 919cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 920cb93a386Sopenharmony_ci} 921cb93a386Sopenharmony_ci 922cb93a386Sopenharmony_citemplate <> 923cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGPreserveAspectRatio* par) { 924cb93a386Sopenharmony_ci return this->parsePreserveAspectRatio(par); 925cb93a386Sopenharmony_ci} 926cb93a386Sopenharmony_ci 927cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/types.html#DataTypeCoordinates 928cb93a386Sopenharmony_citemplate <typename T> 929cb93a386Sopenharmony_cibool SkSVGAttributeParser::parseList(std::vector<T>* vals) { 930cb93a386Sopenharmony_ci SkASSERT(vals->empty()); 931cb93a386Sopenharmony_ci 932cb93a386Sopenharmony_ci T v; 933cb93a386Sopenharmony_ci for (;;) { 934cb93a386Sopenharmony_ci if (!this->parse(&v)) { 935cb93a386Sopenharmony_ci break; 936cb93a386Sopenharmony_ci } 937cb93a386Sopenharmony_ci 938cb93a386Sopenharmony_ci vals->push_back(v); 939cb93a386Sopenharmony_ci 940cb93a386Sopenharmony_ci this->parseCommaWspToken(); 941cb93a386Sopenharmony_ci } 942cb93a386Sopenharmony_ci 943cb93a386Sopenharmony_ci return !vals->empty() && this->parseEOSToken(); 944cb93a386Sopenharmony_ci} 945cb93a386Sopenharmony_ci 946cb93a386Sopenharmony_citemplate <> 947cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(std::vector<SkSVGLength>* lengths) { 948cb93a386Sopenharmony_ci return this->parseList(lengths); 949cb93a386Sopenharmony_ci} 950cb93a386Sopenharmony_ci 951cb93a386Sopenharmony_citemplate <> 952cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(std::vector<SkSVGNumberType>* numbers) { 953cb93a386Sopenharmony_ci return this->parseList(numbers); 954cb93a386Sopenharmony_ci} 955cb93a386Sopenharmony_ci 956cb93a386Sopenharmony_citemplate <> 957cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGColorspace* colorspace) { 958cb93a386Sopenharmony_ci static constexpr std::tuple<const char*, SkSVGColorspace> gColorspaceMap[] = { 959cb93a386Sopenharmony_ci { "auto" , SkSVGColorspace::kAuto }, 960cb93a386Sopenharmony_ci { "sRGB" , SkSVGColorspace::kSRGB }, 961cb93a386Sopenharmony_ci { "linearRGB", SkSVGColorspace::kLinearRGB }, 962cb93a386Sopenharmony_ci }; 963cb93a386Sopenharmony_ci 964cb93a386Sopenharmony_ci return this->parseEnumMap(gColorspaceMap, colorspace) && this->parseEOSToken(); 965cb93a386Sopenharmony_ci} 966cb93a386Sopenharmony_ci 967cb93a386Sopenharmony_ci// https://www.w3.org/TR/SVG11/painting.html#DisplayProperty 968cb93a386Sopenharmony_citemplate <> 969cb93a386Sopenharmony_cibool SkSVGAttributeParser::parse(SkSVGDisplay* display) { 970cb93a386Sopenharmony_ci static const struct { 971cb93a386Sopenharmony_ci SkSVGDisplay fType; 972cb93a386Sopenharmony_ci const char* fName; 973cb93a386Sopenharmony_ci } gDisplayInfo[] = { 974cb93a386Sopenharmony_ci { SkSVGDisplay::kInline, "inline" }, 975cb93a386Sopenharmony_ci { SkSVGDisplay::kNone , "none" }, 976cb93a386Sopenharmony_ci }; 977cb93a386Sopenharmony_ci 978cb93a386Sopenharmony_ci bool parsedValue = false; 979cb93a386Sopenharmony_ci for (const auto& parseInfo : gDisplayInfo) { 980cb93a386Sopenharmony_ci if (this->parseExpectedStringToken(parseInfo.fName)) { 981cb93a386Sopenharmony_ci *display = SkSVGDisplay(parseInfo.fType); 982cb93a386Sopenharmony_ci parsedValue = true; 983cb93a386Sopenharmony_ci break; 984cb93a386Sopenharmony_ci } 985cb93a386Sopenharmony_ci } 986cb93a386Sopenharmony_ci 987cb93a386Sopenharmony_ci return parsedValue && this->parseEOSToken(); 988cb93a386Sopenharmony_ci} 989