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 : fCurPos(attributeString) {} |
| 37 |
| 38 template <typename F> |
| 39 inline bool SkSVGAttributeParser::advanceWhile(F f) { |
| 40 auto initial = fCurPos; |
| 41 while (f(*fCurPos)) { |
| 42 fCurPos++; |
| 43 } |
| 44 return fCurPos != initial; |
| 45 } |
| 46 |
| 47 inline bool SkSVGAttributeParser::parseEOSToken() { |
| 48 return is_eos(*fCurPos); |
| 49 } |
| 50 |
| 51 inline bool SkSVGAttributeParser::parseSepToken() { |
| 52 return this->advanceWhile(is_sep); |
| 53 } |
| 54 |
| 55 inline bool SkSVGAttributeParser::parseWSToken() { |
| 56 return this->advanceWhile(is_ws); |
| 57 } |
| 58 |
| 59 inline bool SkSVGAttributeParser::parseExpectedStringToken(const char* expected)
{ |
| 60 const char* c = fCurPos; |
| 61 |
| 62 while (*c && *expected && *c == *expected) { |
| 63 c++; |
| 64 expected++; |
| 65 } |
| 66 |
| 67 if (*expected) { |
| 68 return false; |
| 69 } |
| 70 |
| 71 fCurPos = c; |
| 72 return true; |
| 73 } |
| 74 |
| 75 bool SkSVGAttributeParser::parseScalarToken(SkScalar* res) { |
| 76 if (const char* next = SkParse::FindScalar(fCurPos, res)) { |
| 77 fCurPos = next; |
| 78 return true; |
| 79 } |
| 80 return false; |
| 81 } |
| 82 |
| 83 bool SkSVGAttributeParser::parseHexToken(uint32_t* res) { |
| 84 if (const char* next = SkParse::FindHex(fCurPos, res)) { |
| 85 fCurPos = next; |
| 86 return true; |
| 87 } |
| 88 return false; |
| 89 } |
| 90 |
| 91 bool SkSVGAttributeParser::parseLengthUnitToken(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->parseExpectedStringToken(gUnitInfo[i].fUnitName)) { |
| 109 *unit = gUnitInfo[i].fUnit; |
| 110 return true; |
| 111 } |
| 112 } |
| 113 return false; |
| 114 } |
| 115 |
| 116 bool SkSVGAttributeParser::parseNamedColorToken(SkColor* c) { |
| 117 if (const char* next = SkParse::FindNamedColor(fCurPos, strlen(fCurPos), c))
{ |
| 118 fCurPos = next; |
| 119 return true; |
| 120 } |
| 121 return false; |
| 122 } |
| 123 |
| 124 bool SkSVGAttributeParser::parseHexColorToken(SkColor* c) { |
| 125 uint32_t v; |
| 126 const char* initial = fCurPos; |
| 127 |
| 128 if (!this->parseExpectedStringToken("#") || !this->parseHexToken(&v)) { |
| 129 return false; |
| 130 } |
| 131 |
| 132 switch (fCurPos - 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->parseHexColorToken(&c) || this->parseNamedColorToken(&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->parseWSToken(); |
| 168 |
| 169 SkScalar s; |
| 170 if (this->parseScalarToken(&s)) { |
| 171 *number = SkSVGNumber(s); |
| 172 // consume trailing separators |
| 173 this->parseSepToken(); |
| 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->parseScalarToken(&s) && |
| 186 (this->parseLengthUnitToken(&u) || this->parseSepToken() || this->parseE
OSToken())) { |
| 187 *length = SkSVGLength(s, u); |
| 188 // consume trailing separators |
| 189 this->parseSepToken(); |
| 190 return true; |
| 191 } |
| 192 |
| 193 return false; |
| 194 } |
OLD | NEW |