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;
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();
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);
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);
632 return this->parseParenthesized(
"scale", [
this](
SkMatrix*
m) ->
bool {
634 if (!this->parseScalarToken(&sx)) {
638 if (!(this->parseSepToken() && this->parseScalarToken(&sy))) {
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);
669 return this->parseParenthesized(
"skewX", [
this](
SkMatrix*
m) ->
bool {
671 if (!this->parseScalarToken(&angle)) {
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;
780 if (this->parseExpectedStringToken(gCapInfo[
i].
fName)) {
787 return parsedValue && this->parseEOSToken();
793 static const struct {
803 bool parsedValue =
false;
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;
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")) {
990 if (this->
parse(&length)) {
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)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static SkString join(const CommandLineFlags::StringArray &)
static constexpr SkPoint Make(float x, float y)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)