Chromium Code Reviews| 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 |