20 return (
unsigned)(c -
min) <= (
unsigned)(
max -
min);
23inline bool is_ws(
char c) {
27inline bool is_sep(
char c) {
28 return is_ws(c) || c ==
',' || c ==
';';
31inline bool is_nl(
char c) {
32 return c ==
'\n' || c ==
'\r' || c ==
'\f';
35inline bool is_hex(
char c) {
45 : fCurPos(attributeString), fEndPos(fCurPos + strlen(attributeString)) {}
48inline bool SkSVGAttributeParser::advanceWhile(
F f) {
49 auto initial = fCurPos;
50 while (fCurPos < fEndPos && f(*fCurPos)) {
53 return fCurPos != initial;
56bool SkSVGAttributeParser::matchStringToken(
const char* token,
const char** newPos)
const {
57 const char* c = fCurPos;
59 while (c < fEndPos && *token && *c == *token) {
75bool SkSVGAttributeParser::parseEOSToken() {
76 return fCurPos == fEndPos;
79bool SkSVGAttributeParser::parseSepToken() {
80 return this->advanceWhile(
is_sep);
83bool SkSVGAttributeParser::parseWSToken() {
84 return this->advanceWhile(
is_ws);
87bool SkSVGAttributeParser::parseCommaWspToken() {
90 return this->parseWSToken() || this->parseExpectedStringToken(
",");
93bool SkSVGAttributeParser::parseExpectedStringToken(
const char* expected) {
95 if (!matchStringToken(expected, &newPos)) {
103bool SkSVGAttributeParser::parseScalarToken(
SkScalar* res) {
111bool SkSVGAttributeParser::parseInt32Token(int32_t* res) {
119bool SkSVGAttributeParser::matchHexToken(
const char** newPos)
const {
121 while (*newPos < fEndPos &&
is_hex(**newPos)) { ++*newPos; }
122 return *newPos != fCurPos;
125bool SkSVGAttributeParser::parseEscape(
SkUnichar* c) {
127 RestoreCurPos restoreCurPos(
this);
129 if (!this->parseExpectedStringToken(
"\\")) {
133 if (this->matchHexToken(&hexEnd)) {
134 if (hexEnd - fCurPos > 6) {
135 hexEnd = fCurPos + 6;
138 size_t hexSize = hexEnd - fCurPos;
139 memcpy(hexString, fCurPos, hexSize);
140 hexString[hexSize] =
'\0';
143 if (!hexFound || cp < 1 || (0xD800 <= cp && cp <= 0xDFFF) || 0x10FFFF < cp) {
148 this->parseWSToken();
149 }
else if (this->parseEOSToken() || is_nl(*fCurPos)) {
158 restoreCurPos.clear();
162bool SkSVGAttributeParser::parseIdentToken(
SkString* ident) {
165 RestoreCurPos restoreCurPos(
this);
168 if (this->parseExpectedStringToken(
"--")) {
171 if (this->parseExpectedStringToken(
"-")) {
174 if (this->parseEscape(&c)) {
180 if ((c <
'a' ||
'z' < c) &&
181 (c <
'A' ||
'Z' < c) &&
183 (c < 0x80 || 0x10FFFF < c))
190 while (fCurPos < fEndPos) {
191 if (this->parseEscape(&c)) {
195 const char*
next = fCurPos;
199 if ((c <
'a' ||
'z' < c) &&
200 (c <
'A' ||
'Z' < c) &&
201 (c <
'0' ||
'9' < c) &&
204 (c < 0x80 || 0x10FFFF < c))
212 restoreCurPos.clear();
217 static const struct {
218 const char* fUnitName;
232 for (
size_t i = 0; i < std::size(gUnitInfo); ++i) {
233 if (this->parseExpectedStringToken(gUnitInfo[i].fUnitName)) {
234 *unit = gUnitInfo[i].fUnit;
242bool SkSVGAttributeParser::parseNamedColorToken(
SkColor* c) {
243 RestoreCurPos restoreCurPos(
this);
246 if (!this->parseIdentToken(&ident)) {
253 restoreCurPos.clear();
257bool SkSVGAttributeParser::parseHexColorToken(
SkColor* c) {
258 RestoreCurPos restoreCurPos(
this);
261 if (!this->parseExpectedStringToken(
"#") || !this->matchHexToken(&hexEnd)) {
266 SkString hexString(fCurPos, hexEnd - fCurPos);
269 switch (hexString.size()) {
275 v = ((v << 12) & 0x00f00000) |
276 ((v << 8) & 0x000ff000) |
277 ((v << 4) & 0x00000ff0) |
278 ((v << 0) & 0x0000000f);
287 restoreCurPos.clear();
291bool SkSVGAttributeParser::parseColorComponentIntegralToken(int32_t* c) {
293 if (!p || *p ==
'.') {
300 *c = SkTPin<int32_t>(*c, 0, 255);
308bool SkSVGAttributeParser::parseColorComponentFractionalToken(int32_t* c) {
311 if (!p || *p !=
'%') {
318 *c = SkTPin<int32_t>(*c, 0, 255);
323bool SkSVGAttributeParser::parseColorComponentScalarToken(int32_t* c) {
327 *c = SkTPin<int32_t>(*c, 0, 255);
334bool SkSVGAttributeParser::parseColorComponentToken(int32_t* c) {
335 return parseColorComponentIntegralToken(c) ||
336 parseColorComponentFractionalToken(c);
339bool SkSVGAttributeParser::parseRGBColorToken(
SkColor* c) {
340 return this->parseParenthesized(
"rgb", [
this](
SkColor* c) ->
bool {
342 if (this->parseColorComponentToken(&r) &&
343 this->parseSepToken() &&
344 this->parseColorComponentToken(&g) &&
345 this->parseSepToken() &&
346 this->parseColorComponentToken(&
b)) {
349 static_cast<uint8_t
>(g),
350 static_cast<uint8_t
>(
b));
357bool SkSVGAttributeParser::parseRGBAColorToken(
SkColor* c) {
358 return this->parseParenthesized(
"rgba", [
this](
SkColor* c) ->
bool {
360 if (this->parseColorComponentToken(&r) &&
361 this->parseSepToken() &&
362 this->parseColorComponentToken(&g) &&
363 this->parseSepToken() &&
364 this->parseColorComponentToken(&
b) &&
365 this->parseSepToken() &&
366 this->parseColorComponentScalarToken(&
a)) {
369 static_cast<uint8_t
>(r),
370 static_cast<uint8_t
>(g),
371 static_cast<uint8_t
>(
b));
378bool SkSVGAttributeParser::parseColorToken(
SkColor* c) {
379 return this->parseHexColorToken(c) ||
380 this->parseNamedColorToken(c) ||
381 this->parseRGBAColorToken(c) ||
382 this->parseRGBColorToken(c);
387 if (!this->parseColorToken(&c)) {
399 this->parseWSToken();
400 if (!this->parseSVGColorType(
color)) {
403 this->parseWSToken();
404 return this->parseEOSToken();
408 static const constexpr int kVarsLimit = 32;
414 if (this->parseExpectedStringToken(
"currentColor")) {
419 if (this->parseParenthesized(
"var", [
this, &
vars](
SkSVGColor* colorResult) ->
bool {
421 if (!this->parseIdentToken(&ident) || ident.
size() < 2 || !ident.
startsWith(
"--")) {
425 vars.push_back(std::move(ident));
426 this->parseWSToken();
427 if (!this->parseExpectedStringToken(
",")) {
431 this->parseWSToken();
432 if (this->matchStringToken(
")")) {
436 return vars.size() < kVarsLimit && this->parseSVGColor(colorResult, std::move(
vars));
447 this->parseWSToken();
451 this->parseWSToken();
452 return this->parseEOSToken();
459 this->parseWSToken();
462 if (this->parseExpectedStringToken(
"#")) {
464 }
else if (this->matchStringToken(
"data:")) {
470 const auto*
start = fCurPos;
471 if (!this->advanceWhile([](
char c) ->
bool {
return c !=
')'; })) {
479bool SkSVGAttributeParser::parseFuncIRI(
SkSVGFuncIRI* iri) {
480 return this->parseParenthesized(
"url", [
this](
SkSVGFuncIRI* iriResult) ->
bool {
482 if (this->parse(&iri)) {
492 if (this->parseEOSToken()) {
496 fCurPos +=
result->size();
497 return this->parseEOSToken();
504 this->parseWSToken();
507 if (this->parseScalarToken(&
s)) {
510 this->parseSepToken();
520 this->parseWSToken();
523 this->parseExpectedStringToken(
"+");
526 if (this->parseInt32Token(&i)) {
529 this->parseSepToken();
542 if (this->parseScalarToken(&
s) &&
543 (this->parseLengthUnitToken(&u) || this->parseSepToken() || this->parseEOSToken())) {
546 this->parseSepToken();
556 this->parseWSToken();
558 bool parsedValue =
false;
559 if (this->parseScalarToken(&
x) && this->parseSepToken() &&
560 this->parseScalarToken(&
y) && this->parseSepToken() &&
561 this->parseScalarToken(&
w) && this->parseSepToken() &&
562 this->parseScalarToken(&
h)) {
567 this->parseWSToken();
569 return parsedValue && this->parseEOSToken();
572template <
typename Func,
typename T>
573bool SkSVGAttributeParser::parseParenthesized(
const char* prefix, Func f,
T*
result) {
574 RestoreCurPos restoreCurPos(
this);
576 this->parseWSToken();
577 if (prefix && !this->parseExpectedStringToken(prefix)) {
580 this->parseWSToken();
581 if (!this->parseExpectedStringToken(
"(")) {
584 this->parseWSToken();
590 this->parseWSToken();
591 if (!this->parseExpectedStringToken(
")")) {
595 restoreCurPos.clear();
599bool SkSVGAttributeParser::parseMatrixToken(
SkMatrix* matrix) {
600 return this->parseParenthesized(
"matrix", [
this](
SkMatrix* m) ->
bool {
602 for (
int i = 0; i < 6; ++i) {
603 if (!(this->parseScalarToken(scalars + i) &&
604 (i > 4 || this->parseSepToken()))) {
609 m->setAll(scalars[0], scalars[2], scalars[4], scalars[1], scalars[3], scalars[5], 0, 0, 1);
614bool SkSVGAttributeParser::parseTranslateToken(
SkMatrix* matrix) {
615 return this->parseParenthesized(
"translate", [
this](
SkMatrix* m) ->
bool {
617 this->parseWSToken();
618 if (!this->parseScalarToken(&tx)) {
622 if (!this->parseSepToken() || !this->parseScalarToken(&ty)) {
626 m->setTranslate(tx, ty);
631bool SkSVGAttributeParser::parseScaleToken(
SkMatrix* matrix) {
632 return this->parseParenthesized(
"scale", [
this](
SkMatrix* m) ->
bool {
634 if (!this->parseScalarToken(&sx)) {
638 if (!(this->parseSepToken() && this->parseScalarToken(&sy))) {
647bool SkSVGAttributeParser::parseRotateToken(
SkMatrix* matrix) {
648 return this->parseParenthesized(
"rotate", [
this](
SkMatrix* m) ->
bool {
650 if (!this->parseScalarToken(&angle)) {
657 if (this->parseSepToken() && this->parseScalarToken(&cx)) {
658 if (!(this->parseSepToken() && this->parseScalarToken(&cy))) {
663 m->setRotate(angle, cx, cy);
668bool SkSVGAttributeParser::parseSkewXToken(
SkMatrix* matrix) {
669 return this->parseParenthesized(
"skewX", [
this](
SkMatrix* m) ->
bool {
671 if (!this->parseScalarToken(&angle)) {
679bool SkSVGAttributeParser::parseSkewYToken(
SkMatrix* matrix) {
680 return this->parseParenthesized(
"skewY", [
this](
SkMatrix* m) ->
bool {
682 if (!this->parseScalarToken(&angle)) {
699 if (!( this->parseMatrixToken(&m)
700 || this->parseTranslateToken(&m)
701 || this->parseScaleToken(&m)
702 || this->parseRotateToken(&m)
703 || this->parseSkewXToken(&m)
704 || this->parseSkewYToken(&m))) {
711 this->parseCommaWspToken();
714 this->parseWSToken();
715 if (!parsed || !this->parseEOSToken()) {
728 bool parsedValue =
false;
730 this->parseWSToken();
734 }
else if (this->parseExpectedStringToken(
"none")) {
737 }
else if (this->parseFuncIRI(&iri)) {
739 this->parseWSToken();
744 this->parseWSToken();
745 return parsedValue && this->parseEOSToken();
754 bool parsedValue =
false;
756 if (this->parseExpectedStringToken(
"none")) {
759 }
else if (this->parseFuncIRI(firi)) {
763 return parsedValue && this->parseEOSToken();
769 static const struct {
778 bool parsedValue =
false;
779 for (
size_t i = 0; i < std::size(gCapInfo); ++i) {
780 if (this->parseExpectedStringToken(gCapInfo[i].
fName)) {
787 return parsedValue && this->parseEOSToken();
793 static const struct {
803 bool parsedValue =
false;
804 for (
size_t i = 0; i < std::size(gJoinInfo); ++i) {
805 if (this->parseExpectedStringToken(gJoinInfo[i].
fName)) {
812 return parsedValue && this->parseEOSToken();
818 bool parsedValue =
false;
819 if (this->parseExpectedStringToken(
"userSpaceOnUse")) {
820 *objectBoundingBoxUnits =
823 }
else if (this->parseExpectedStringToken(
"objectBoundingBox")) {
824 *objectBoundingBoxUnits =
828 return parsedValue && this->parseEOSToken();
839 this->advanceWhile(
is_ws);
841 bool parsedValue =
false;
847 if (parsedValue && !this->parseCommaWspToken()) {
852 if (!this->parseScalarToken(&
x)) {
860 if (!this->parseCommaWspToken() && !this->parseEOSToken() && *fCurPos !=
'-') {
864 if (!this->parseScalarToken(&
y)) {
872 if (parsedValue && this->parseEOSToken()) {
883 static const struct {
886 } gFillRuleInfo[] = {
892 bool parsedValue =
false;
893 for (
size_t i = 0; i < std::size(gFillRuleInfo); ++i) {
894 if (this->parseExpectedStringToken(gFillRuleInfo[i].
fName)) {
901 return parsedValue && this->parseEOSToken();
907 static const struct {
910 } gVisibilityInfo[] = {
917 bool parsedValue =
false;
918 for (
const auto& parseInfo : gVisibilityInfo) {
919 if (this->parseExpectedStringToken(parseInfo.fName)) {
926 return parsedValue && this->parseEOSToken();
932 bool parsedValue =
false;
933 if (this->parseExpectedStringToken(
"none")) {
936 }
else if (this->parseExpectedStringToken(
"inherit")) {
940 std::vector<SkSVGLength> dashes;
944 if (!this->
parse(&dash)) {
948 dashes.push_back(dash);
957 return parsedValue && this->parseEOSToken();
963 bool parsedValue =
false;
964 if (this->parseExpectedStringToken(
"inherit")) {
970 const auto* comma = strchr(fCurPos,
',');
971 auto family_name = comma ?
SkString(fCurPos, comma - fCurPos)
974 fCurPos += strlen(fCurPos);
978 return parsedValue && this->parseEOSToken();
984 bool parsedValue =
false;
985 if (this->parseExpectedStringToken(
"inherit")) {
996 return parsedValue && this->parseEOSToken();
1002 static constexpr std::tuple<const char*, SkSVGFontStyle::Type> gStyleMap[] = {
1009 bool parsedValue =
false;
1012 if (this->parseEnumMap(gStyleMap, &
type)) {
1017 return parsedValue && this->parseEOSToken();
1023 static constexpr std::tuple<const char*, SkSVGFontWeight::Type> gWeightMap[] = {
1040 bool parsedValue =
false;
1043 if (this->parseEnumMap(gWeightMap, &
type)) {
1048 return parsedValue && this->parseEOSToken();
1054 static constexpr std::tuple<const char*, SkSVGTextAnchor::Type> gAnchorMap[] = {
1061 bool parsedValue =
false;
1064 if (this->parseEnumMap(gAnchorMap, &
type)) {
1069 return parsedValue && this->parseEOSToken();
1074 static constexpr std::tuple<const char*, SkSVGPreserveAspectRatio::Align> gAlignMap[] = {
1087 static constexpr std::tuple<const char*, SkSVGPreserveAspectRatio::Scale> gScaleMap[] = {
1092 bool parsedValue =
false;
1095 this->parseExpectedStringToken(
"defer");
1096 this->parseWSToken();
1098 if (this->parseEnumMap(gAlignMap, &par->
fAlign)) {
1102 this->parseWSToken();
1103 this->parseEnumMap(gScaleMap, &par->
fScale);
1106 return parsedValue && this->parseEOSToken();
1115template <
typename T>
1116bool SkSVGAttributeParser::parseList(std::vector<T>* vals) {
1121 if (!this->parse(&v)) {
1127 this->parseCommaWspToken();
1130 return !vals->empty() && this->parseEOSToken();
1135 return this->parseList(lengths);
1140 return this->parseList(numbers);
1145 static constexpr std::tuple<const char*, SkSVGColorspace> gColorspaceMap[] = {
1151 return this->parseEnumMap(gColorspaceMap, colorspace) && this->parseEOSToken();
1157 static const struct {
1160 } gDisplayInfo[] = {
1165 bool parsedValue =
false;
1166 for (
const auto& parseInfo : gDisplayInfo) {
1167 if (this->parseExpectedStringToken(parseInfo.fName)) {
1174 return parsedValue && this->parseEOSToken();
static const int points[]
static float next(float f)
#define SkColorSetRGB(r, g, b)
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
constexpr SkColor SK_ColorBLACK
static bool is_sep(int c)
static bool is_hex(int c)
static bool is_between(int c, int min, int max)
std::vector< SkPoint > SkSVGPointsType
SkMatrix SkSVGTransformType
#define SkDegreesToRadians(degrees)
#define SkScalarRoundToInt(x)
static const SkMatrix & I()
static const char * FindScalar(const char str[], SkScalar *value)
static const char * FindHex(const char str[], uint32_t *value)
static const char * FindS32(const char str[], int32_t *value)
static const char * FindNamedColor(const char str[], size_t len, SkColor *color)
bool parsePreserveAspectRatio(SkSVGPreserveAspectRatio *)
bool parseInteger(SkSVGIntegerType *)
bool parseViewBox(SkSVGViewBoxType *)
SkSVGAttributeParser(const char[])
bool parse(SkSVGIntegerType *v)
std::vector< SkString > Vars
const SkSVGIRI & iri() const
void appendUnichar(SkUnichar uni)
bool startsWith(const char prefixStr[]) const
void void void void void void void remove(size_t offset, size_t length)
void append(const char text[])
const char * c_str() const
static float max(float r, float g, float b)
static float min(float r, float g, float b)
unsigned useCenter Optional< SkMatrix > matrix
SK_SPI SkUnichar NextUTF8(const char **ptr, const char *end)
static constexpr SkPoint Make(float x, float y)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)