OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkParse.h" | |
9 #include "SkSVGAttributeParser.h" | |
10 #include "SkSVGTypes.h" | |
11 | |
12 namespace { | |
13 | |
14 // TODO: these should be shared with SkParse.cpp | |
15 | |
16 inline bool is_between(char c, char min, char max) { | |
17 SkASSERT(min <= max); | |
18 return (unsigned)(c - min) <= (unsigned)(max - min); | |
19 } | |
20 | |
21 inline bool is_eos(char c) { | |
22 return !c; | |
23 } | |
24 | |
25 inline bool is_ws(char c) { | |
26 return is_between(c, 1, 32); | |
27 } | |
28 | |
29 inline bool is_sep(char c) { | |
30 return is_ws(c) || c == ',' || c == ';'; | |
31 } | |
32 | |
33 } // anonymous ns | |
34 | |
35 SkSVGAttributeParser::SkSVGAttributeParser(const char attributeString[]) | |
36 : fChr(attributeString) {} | |
37 | |
38 template <typename F> | |
39 inline bool SkSVGAttributeParser::advanceWhile(F f) { | |
40 auto initial = fChr; | |
41 while (f(*fChr)) { | |
42 fChr++; | |
43 } | |
44 return fChr != initial; | |
45 } | |
46 | |
47 inline bool SkSVGAttributeParser::parseEOSAtom() { | |
48 return is_eos(*fChr); | |
49 } | |
50 | |
51 inline bool SkSVGAttributeParser::parseSepAtom() { | |
52 return this->advanceWhile(is_sep); | |
53 } | |
54 | |
55 inline bool SkSVGAttributeParser::parseWSAtom() { | |
56 return this->advanceWhile(is_ws); | |
57 } | |
58 | |
robertphillips
2016/08/02 22:25:56
consumeExpectedToken ?
f(malita)
2016/08/03 16:50:51
Done (parseExpectedStringToken for consistency wit
| |
59 inline bool SkSVGAttributeParser::parseStringAtom(const char* expected) { | |
60 const char* c = fChr; | |
61 | |
62 while (*c && *expected && *c == *expected) { | |
63 c++; | |
64 expected++; | |
65 } | |
66 | |
67 if (*expected) { | |
68 return false; | |
69 } | |
70 | |
71 fChr = c; | |
72 return true; | |
73 } | |
74 | |
75 bool SkSVGAttributeParser::parseScalarAtom(SkScalar* res) { | |
76 if (const char* next = SkParse::FindScalar(fChr, res)) { | |
77 fChr = next; | |
78 return true; | |
79 } | |
80 return false; | |
81 } | |
82 | |
83 bool SkSVGAttributeParser::parseHexAtom(uint32_t* res) { | |
84 if (const char* next = SkParse::FindHex(fChr, res)) { | |
85 fChr = next; | |
86 return true; | |
87 } | |
88 return false; | |
89 } | |
90 | |
91 bool SkSVGAttributeParser::parseLengthUnitAtom(SkSVGLength::Unit* unit) { | |
92 static const struct { | |
93 const char* fUnitName; | |
94 SkSVGLength::Unit fUnit; | |
95 } gUnitInfo[] = { | |
96 { "%" , SkSVGLength::Unit::kPercentage }, | |
97 { "em", SkSVGLength::Unit::kEMS }, | |
98 { "ex", SkSVGLength::Unit::kEXS }, | |
99 { "px", SkSVGLength::Unit::kPX }, | |
100 { "cm", SkSVGLength::Unit::kCM }, | |
101 { "mm", SkSVGLength::Unit::kMM }, | |
102 { "in", SkSVGLength::Unit::kIN }, | |
103 { "pt", SkSVGLength::Unit::kPT }, | |
104 { "pc", SkSVGLength::Unit::kPC }, | |
105 }; | |
106 | |
107 for (size_t i = 0; i < SK_ARRAY_COUNT(gUnitInfo); ++i) { | |
108 if (this->parseStringAtom(gUnitInfo[i].fUnitName)) { | |
109 *unit = gUnitInfo[i].fUnit; | |
110 return true; | |
111 } | |
112 } | |
113 return false; | |
114 } | |
115 | |
116 bool SkSVGAttributeParser::parseNamedColorAtom(SkColor* c) { | |
117 if (const char* next = SkParse::FindNamedColor(fChr, strlen(fChr), c)) { | |
118 fChr = next; | |
119 return true; | |
120 } | |
121 return false; | |
122 } | |
123 | |
124 bool SkSVGAttributeParser::parseHexColorAtom(SkColor* c) { | |
125 uint32_t v; | |
126 const char* initial = fChr; | |
127 | |
128 if (!this->parseStringAtom("#") || !this->parseHexAtom(&v)) { | |
129 return false; | |
130 } | |
131 | |
132 switch (fChr - initial) { | |
133 case 7: | |
134 // matched #xxxxxxx | |
135 break; | |
136 case 4: | |
137 // matched '#xxx; | |
138 v = ((v << 12) & 0x00f00000) | | |
139 ((v << 8) & 0x000ff000) | | |
140 ((v << 4) & 0x00000ff0) | | |
141 ((v << 0) & 0x0000000f); | |
142 break; | |
143 default: | |
144 return false; | |
145 } | |
146 | |
147 *c = v | 0xff000000; | |
148 return true; | |
149 } | |
150 | |
151 // https://www.w3.org/TR/SVG/types.html#DataTypeColor | |
152 bool SkSVGAttributeParser::parseColor(SkSVGColor* color) { | |
153 SkColor c; | |
154 | |
155 // TODO: rgb(...) | |
156 if (this->parseHexColorAtom(&c) || this->parseNamedColorAtom(&c)) { | |
157 *color = SkSVGColor(c); | |
158 return true; | |
159 } | |
160 | |
161 return false; | |
162 } | |
163 | |
164 // https://www.w3.org/TR/SVG/types.html#DataTypeNumber | |
165 bool SkSVGAttributeParser::parseNumber(SkSVGNumber* number) { | |
166 // consume WS | |
167 this->parseWSAtom(); | |
168 | |
169 SkScalar s; | |
170 if (this->parseScalarAtom(&s)) { | |
171 *number = SkSVGNumber(s); | |
172 // consume trailing separators | |
173 this->parseSepAtom(); | |
174 return true; | |
175 } | |
176 | |
177 return false; | |
178 } | |
179 | |
180 // https://www.w3.org/TR/SVG/types.html#DataTypeLength | |
181 bool SkSVGAttributeParser::parseLength(SkSVGLength* length) { | |
182 SkScalar s; | |
183 SkSVGLength::Unit u = SkSVGLength::Unit::kNumber; | |
184 | |
185 if (this->parseScalarAtom(&s) && | |
186 (this->parseLengthUnitAtom(&u) || this->parseSepAtom() || this->parseEOS Atom())) { | |
187 *length = SkSVGLength(s, u); | |
188 // consume trailing separators | |
189 this->parseSepAtom(); | |
190 return true; | |
191 } | |
192 | |
193 return false; | |
194 } | |
OLD | NEW |