| 1 | /* |
| 2 | * Copyright 2006 The Android Open Source Project |
| 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 | |
| 9 | #include "include/utils/SkParse.h" |
| 10 | |
| 11 | static constexpr const char* gColorNames[] = { |
| 12 | "aliceblue" , |
| 13 | "antiquewhite" , |
| 14 | "aqua" , |
| 15 | "aquamarine" , |
| 16 | "azure" , |
| 17 | "beige" , |
| 18 | "bisque" , |
| 19 | "black" , |
| 20 | "blanchedalmond" , |
| 21 | "blue" , |
| 22 | "blueviolet" , |
| 23 | "brown" , |
| 24 | "burlywood" , |
| 25 | "cadetblue" , |
| 26 | "chartreuse" , |
| 27 | "chocolate" , |
| 28 | "coral" , |
| 29 | "cornflowerblue" , |
| 30 | "cornsilk" , |
| 31 | "crimson" , |
| 32 | "cyan" , |
| 33 | "darkblue" , |
| 34 | "darkcyan" , |
| 35 | "darkgoldenrod" , |
| 36 | "darkgray" , |
| 37 | "darkgreen" , |
| 38 | "darkkhaki" , |
| 39 | "darkmagenta" , |
| 40 | "darkolivegreen" , |
| 41 | "darkorange" , |
| 42 | "darkorchid" , |
| 43 | "darkred" , |
| 44 | "darksalmon" , |
| 45 | "darkseagreen" , |
| 46 | "darkslateblue" , |
| 47 | "darkslategray" , |
| 48 | "darkturquoise" , |
| 49 | "darkviolet" , |
| 50 | "deeppink" , |
| 51 | "deepskyblue" , |
| 52 | "dimgray" , |
| 53 | "dodgerblue" , |
| 54 | "firebrick" , |
| 55 | "floralwhite" , |
| 56 | "forestgreen" , |
| 57 | "fuchsia" , |
| 58 | "gainsboro" , |
| 59 | "ghostwhite" , |
| 60 | "gold" , |
| 61 | "goldenrod" , |
| 62 | "gray" , |
| 63 | "green" , |
| 64 | "greenyellow" , |
| 65 | "honeydew" , |
| 66 | "hotpink" , |
| 67 | "indianred" , |
| 68 | "indigo" , |
| 69 | "ivory" , |
| 70 | "khaki" , |
| 71 | "lavender" , |
| 72 | "lavenderblush" , |
| 73 | "lawngreen" , |
| 74 | "lemonchiffon" , |
| 75 | "lightblue" , |
| 76 | "lightcoral" , |
| 77 | "lightcyan" , |
| 78 | "lightgoldenrodyellow" , |
| 79 | "lightgreen" , |
| 80 | "lightgrey" , |
| 81 | "lightpink" , |
| 82 | "lightsalmon" , |
| 83 | "lightseagreen" , |
| 84 | "lightskyblue" , |
| 85 | "lightslategray" , |
| 86 | "lightsteelblue" , |
| 87 | "lightyellow" , |
| 88 | "lime" , |
| 89 | "limegreen" , |
| 90 | "linen" , |
| 91 | "magenta" , |
| 92 | "maroon" , |
| 93 | "mediumaquamarine" , |
| 94 | "mediumblue" , |
| 95 | "mediumorchid" , |
| 96 | "mediumpurple" , |
| 97 | "mediumseagreen" , |
| 98 | "mediumslateblue" , |
| 99 | "mediumspringgreen" , |
| 100 | "mediumturquoise" , |
| 101 | "mediumvioletred" , |
| 102 | "midnightblue" , |
| 103 | "mintcream" , |
| 104 | "mistyrose" , |
| 105 | "moccasin" , |
| 106 | "navajowhite" , |
| 107 | "navy" , |
| 108 | "oldlace" , |
| 109 | "olive" , |
| 110 | "olivedrab" , |
| 111 | "orange" , |
| 112 | "orangered" , |
| 113 | "orchid" , |
| 114 | "palegoldenrod" , |
| 115 | "palegreen" , |
| 116 | "paleturquoise" , |
| 117 | "palevioletred" , |
| 118 | "papayawhip" , |
| 119 | "peachpuff" , |
| 120 | "peru" , |
| 121 | "pink" , |
| 122 | "plum" , |
| 123 | "powderblue" , |
| 124 | "purple" , |
| 125 | "red" , |
| 126 | "rosybrown" , |
| 127 | "royalblue" , |
| 128 | "saddlebrown" , |
| 129 | "salmon" , |
| 130 | "sandybrown" , |
| 131 | "seagreen" , |
| 132 | "seashell" , |
| 133 | "sienna" , |
| 134 | "silver" , |
| 135 | "skyblue" , |
| 136 | "slateblue" , |
| 137 | "slategray" , |
| 138 | "snow" , |
| 139 | "springgreen" , |
| 140 | "steelblue" , |
| 141 | "tan" , |
| 142 | "teal" , |
| 143 | "thistle" , |
| 144 | "tomato" , |
| 145 | "turquoise" , |
| 146 | "violet" , |
| 147 | "wheat" , |
| 148 | "white" , |
| 149 | "whitesmoke" , |
| 150 | "yellow" , |
| 151 | "yellowgreen" , |
| 152 | }; |
| 153 | |
| 154 | static constexpr struct ColorRec { |
| 155 | uint8_t r, g, b; |
| 156 | } gColors[] = { |
| 157 | { 0xf0,0xf8,0xff }, // aliceblue |
| 158 | { 0xfa,0xeb,0xd7 }, // antiquewhite |
| 159 | { 0x00,0xff,0xff }, // aqua |
| 160 | { 0x7f,0xff,0xd4 }, // aquamarine |
| 161 | { 0xf0,0xff,0xff }, // azure |
| 162 | { 0xf5,0xf5,0xdc }, // beige |
| 163 | { 0xff,0xe4,0xc4 }, // bisque |
| 164 | { 0x00,0x00,0x00 }, // black |
| 165 | { 0xff,0xeb,0xcd }, // blanchedalmond |
| 166 | { 0x00,0x00,0xff }, // blue |
| 167 | { 0x8a,0x2b,0xe2 }, // blueviolet |
| 168 | { 0xa5,0x2a,0x2a }, // brown |
| 169 | { 0xde,0xb8,0x87 }, // burlywood |
| 170 | { 0x5f,0x9e,0xa0 }, // cadetblue |
| 171 | { 0x7f,0xff,0x00 }, // chartreuse |
| 172 | { 0xd2,0x69,0x1e }, // chocolate |
| 173 | { 0xff,0x7f,0x50 }, // coral |
| 174 | { 0x64,0x95,0xed }, // cornflowerblue |
| 175 | { 0xff,0xf8,0xdc }, // cornsilk |
| 176 | { 0xdc,0x14,0x3c }, // crimson |
| 177 | { 0x00,0xff,0xff }, // cyan |
| 178 | { 0x00,0x00,0x8b }, // darkblue |
| 179 | { 0x00,0x8b,0x8b }, // darkcyan |
| 180 | { 0xb8,0x86,0x0b }, // darkgoldenrod |
| 181 | { 0xa9,0xa9,0xa9 }, // darkgray |
| 182 | { 0x00,0x64,0x00 }, // darkgreen |
| 183 | { 0xbd,0xb7,0x6b }, // darkkhaki |
| 184 | { 0x8b,0x00,0x8b }, // darkmagenta |
| 185 | { 0x55,0x6b,0x2f }, // darkolivegreen |
| 186 | { 0xff,0x8c,0x00 }, // darkorange |
| 187 | { 0x99,0x32,0xcc }, // darkorchid |
| 188 | { 0x8b,0x00,0x00 }, // darkred |
| 189 | { 0xe9,0x96,0x7a }, // darksalmon |
| 190 | { 0x8f,0xbc,0x8f }, // darkseagreen |
| 191 | { 0x48,0x3d,0x8b }, // darkslateblue |
| 192 | { 0x2f,0x4f,0x4f }, // darkslategray |
| 193 | { 0x00,0xce,0xd1 }, // darkturquoise |
| 194 | { 0x94,0x00,0xd3 }, // darkviolet |
| 195 | { 0xff,0x14,0x93 }, // deeppink |
| 196 | { 0x00,0xbf,0xff }, // deepskyblue |
| 197 | { 0x69,0x69,0x69 }, // dimgray |
| 198 | { 0x1e,0x90,0xff }, // dodgerblue |
| 199 | { 0xb2,0x22,0x22 }, // firebrick |
| 200 | { 0xff,0xfa,0xf0 }, // floralwhite |
| 201 | { 0x22,0x8b,0x22 }, // forestgreen |
| 202 | { 0xff,0x00,0xff }, // fuchsia |
| 203 | { 0xdc,0xdc,0xdc }, // gainsboro |
| 204 | { 0xf8,0xf8,0xff }, // ghostwhite |
| 205 | { 0xff,0xd7,0x00 }, // gold |
| 206 | { 0xda,0xa5,0x20 }, // goldenrod |
| 207 | { 0x80,0x80,0x80 }, // gray |
| 208 | { 0x00,0x80,0x00 }, // green |
| 209 | { 0xad,0xff,0x2f }, // greenyellow |
| 210 | { 0xf0,0xff,0xf0 }, // honeydew |
| 211 | { 0xff,0x69,0xb4 }, // hotpink |
| 212 | { 0xcd,0x5c,0x5c }, // indianred |
| 213 | { 0x4b,0x00,0x82 }, // indigo |
| 214 | { 0xff,0xff,0xf0 }, // ivory |
| 215 | { 0xf0,0xe6,0x8c }, // khaki |
| 216 | { 0xe6,0xe6,0xfa }, // lavender |
| 217 | { 0xff,0xf0,0xf5 }, // lavenderblush |
| 218 | { 0x7c,0xfc,0x00 }, // lawngreen |
| 219 | { 0xff,0xfa,0xcd }, // lemonchiffon |
| 220 | { 0xad,0xd8,0xe6 }, // lightblue |
| 221 | { 0xf0,0x80,0x80 }, // lightcoral |
| 222 | { 0xe0,0xff,0xff }, // lightcyan |
| 223 | { 0xfa,0xfa,0xd2 }, // lightgoldenrodyellow |
| 224 | { 0x90,0xee,0x90 }, // lightgreen |
| 225 | { 0xd3,0xd3,0xd3 }, // lightgrey |
| 226 | { 0xff,0xb6,0xc1 }, // lightpink |
| 227 | { 0xff,0xa0,0x7a }, // lightsalmon |
| 228 | { 0x20,0xb2,0xaa }, // lightseagreen |
| 229 | { 0x87,0xce,0xfa }, // lightskyblue |
| 230 | { 0x77,0x88,0x99 }, // lightslategray |
| 231 | { 0xb0,0xc4,0xde }, // lightsteelblue |
| 232 | { 0xff,0xff,0xe0 }, // lightyellow |
| 233 | { 0x00,0xff,0x00 }, // lime |
| 234 | { 0x32,0xcd,0x32 }, // limegreen |
| 235 | { 0xfa,0xf0,0xe6 }, // linen |
| 236 | { 0xff,0x00,0xff }, // magenta |
| 237 | { 0x80,0x00,0x00 }, // maroon |
| 238 | { 0x66,0xcd,0xaa }, // mediumaquamarine |
| 239 | { 0x00,0x00,0xcd }, // mediumblue |
| 240 | { 0xba,0x55,0xd3 }, // mediumorchid |
| 241 | { 0x93,0x70,0xdb }, // mediumpurple |
| 242 | { 0x3c,0xb3,0x71 }, // mediumseagreen |
| 243 | { 0x7b,0x68,0xee }, // mediumslateblue |
| 244 | { 0x00,0xfa,0x9a }, // mediumspringgreen |
| 245 | { 0x48,0xd1,0xcc }, // mediumturquoise |
| 246 | { 0xc7,0x15,0x85 }, // mediumvioletred |
| 247 | { 0x19,0x19,0x70 }, // midnightblue |
| 248 | { 0xf5,0xff,0xfa }, // mintcream |
| 249 | { 0xff,0xe4,0xe1 }, // mistyrose |
| 250 | { 0xff,0xe4,0xb5 }, // moccasin |
| 251 | { 0xff,0xde,0xad }, // navajowhite |
| 252 | { 0x00,0x00,0x80 }, // navy |
| 253 | { 0xfd,0xf5,0xe6 }, // oldlace |
| 254 | { 0x80,0x80,0x00 }, // olive |
| 255 | { 0x6b,0x8e,0x23 }, // olivedrab |
| 256 | { 0xff,0xa5,0x00 }, // orange |
| 257 | { 0xff,0x45,0x00 }, // orangered |
| 258 | { 0xda,0x70,0xd6 }, // orchid |
| 259 | { 0xee,0xe8,0xaa }, // palegoldenrod |
| 260 | { 0x98,0xfb,0x98 }, // palegreen |
| 261 | { 0xaf,0xee,0xee }, // paleturquoise |
| 262 | { 0xdb,0x70,0x93 }, // palevioletred |
| 263 | { 0xff,0xef,0xd5 }, // papayawhip |
| 264 | { 0xff,0xda,0xb9 }, // peachpuff |
| 265 | { 0xcd,0x85,0x3f }, // peru |
| 266 | { 0xff,0xc0,0xcb }, // pink |
| 267 | { 0xdd,0xa0,0xdd }, // plum |
| 268 | { 0xb0,0xe0,0xe6 }, // powderblue |
| 269 | { 0x80,0x00,0x80 }, // purple |
| 270 | { 0xff,0x00,0x00 }, // red |
| 271 | { 0xbc,0x8f,0x8f }, // rosybrown |
| 272 | { 0x41,0x69,0xe1 }, // royalblue |
| 273 | { 0x8b,0x45,0x13 }, // saddlebrown |
| 274 | { 0xfa,0x80,0x72 }, // salmon |
| 275 | { 0xf4,0xa4,0x60 }, // sandybrown |
| 276 | { 0x2e,0x8b,0x57 }, // seagreen |
| 277 | { 0xff,0xf5,0xee }, // seashell |
| 278 | { 0xa0,0x52,0x2d }, // sienna |
| 279 | { 0xc0,0xc0,0xc0 }, // silver |
| 280 | { 0x87,0xce,0xeb }, // skyblue |
| 281 | { 0x6a,0x5a,0xcd }, // slateblue |
| 282 | { 0x70,0x80,0x90 }, // slategray |
| 283 | { 0xff,0xfa,0xfa }, // snow |
| 284 | { 0x00,0xff,0x7f }, // springgreen |
| 285 | { 0x46,0x82,0xb4 }, // steelblue |
| 286 | { 0xd2,0xb4,0x8c }, // tan |
| 287 | { 0x00,0x80,0x80 }, // teal |
| 288 | { 0xd8,0xbf,0xd8 }, // thistle |
| 289 | { 0xff,0x63,0x47 }, // tomato |
| 290 | { 0x40,0xe0,0xd0 }, // turquoise |
| 291 | { 0xee,0x82,0xee }, // violet |
| 292 | { 0xf5,0xde,0xb3 }, // wheat |
| 293 | { 0xff,0xff,0xff }, // white |
| 294 | { 0xf5,0xf5,0xf5 }, // whitesmoke |
| 295 | { 0xff,0xff,0x00 }, // yellow |
| 296 | { 0x9a,0xcd,0x32 }, // yellowgreen |
| 297 | }; |
| 298 | |
| 299 | const char* SkParse::FindNamedColor(const char* name, size_t len, SkColor* color) { |
| 300 | const auto rec = std::lower_bound(std::begin(gColorNames), |
| 301 | std::end (gColorNames), |
| 302 | name, // key |
| 303 | [](const char* name, const char* key) { |
| 304 | return strcmp(name, key) < 0; |
| 305 | }); |
| 306 | |
| 307 | if (rec == std::end(gColorNames) || strcmp(name, *rec)) { |
| 308 | return nullptr; |
| 309 | } |
| 310 | |
| 311 | if (color) { |
| 312 | int index = rec - gColorNames; |
| 313 | *color = SkColorSetRGB(gColors[index].r, gColors[index].g, gColors[index].b); |
| 314 | } |
| 315 | |
| 316 | return name + strlen(*rec); |
| 317 | } |
| 318 | |
| 319 | // !!! move to char utilities |
| 320 | //static int count_separators(const char* str, const char* sep) { |
| 321 | // char c; |
| 322 | // int separators = 0; |
| 323 | // while ((c = *str++) != '\0') { |
| 324 | // if (strchr(sep, c) == nullptr) |
| 325 | // continue; |
| 326 | // do { |
| 327 | // if ((c = *str++) == '\0') |
| 328 | // goto goHome; |
| 329 | // } while (strchr(sep, c) != nullptr); |
| 330 | // separators++; |
| 331 | // } |
| 332 | //goHome: |
| 333 | // return separators; |
| 334 | //} |
| 335 | |
| 336 | static inline unsigned nib2byte(unsigned n) |
| 337 | { |
| 338 | SkASSERT((n & ~0xF) == 0); |
| 339 | return (n << 4) | n; |
| 340 | } |
| 341 | |
| 342 | const char* SkParse::FindColor(const char* value, SkColor* colorPtr) { |
| 343 | unsigned int oldAlpha = SkColorGetA(*colorPtr); |
| 344 | if (value[0] == '#') { |
| 345 | uint32_t hex; |
| 346 | const char* end = SkParse::FindHex(value + 1, &hex); |
| 347 | // SkASSERT(end); |
| 348 | if (end == nullptr) |
| 349 | return end; |
| 350 | size_t len = end - value - 1; |
| 351 | if (len == 3 || len == 4) { |
| 352 | unsigned a = len == 4 ? nib2byte(hex >> 12) : oldAlpha; |
| 353 | unsigned r = nib2byte((hex >> 8) & 0xF); |
| 354 | unsigned g = nib2byte((hex >> 4) & 0xF); |
| 355 | unsigned b = nib2byte(hex & 0xF); |
| 356 | *colorPtr = SkColorSetARGB(a, r, g, b); |
| 357 | return end; |
| 358 | } else if (len == 6 || len == 8) { |
| 359 | if (len == 6) |
| 360 | hex |= oldAlpha << 24; |
| 361 | *colorPtr = hex; |
| 362 | return end; |
| 363 | } else { |
| 364 | // SkASSERT(0); |
| 365 | return nullptr; |
| 366 | } |
| 367 | // } else if (strchr(value, ',')) { |
| 368 | // SkScalar array[4]; |
| 369 | // int count = count_separators(value, ",") + 1; // !!! count commas, add 1 |
| 370 | // SkASSERT(count == 3 || count == 4); |
| 371 | // array[0] = SK_Scalar1 * 255; |
| 372 | // const char* end = SkParse::FindScalars(value, &array[4 - count], count); |
| 373 | // if (end == nullptr) |
| 374 | // return nullptr; |
| 375 | // !!! range check for errors? |
| 376 | // *colorPtr = SkColorSetARGB(SkScalarRoundToInt(array[0]), SkScalarRoundToInt(array[1]), |
| 377 | // SkScalarRoundToInt(array[2]), SkScalarRoundToInt(array[3])); |
| 378 | // return end; |
| 379 | } else |
| 380 | return FindNamedColor(value, strlen(value), colorPtr); |
| 381 | } |
| 382 | |