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 
FindNamedColor(const char * name,size_t len,SkColor * color)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) || 0 != 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 
nib2byte(unsigned n)336 static inline unsigned nib2byte(unsigned n)
337 {
338     SkASSERT((n & ~0xF) == 0);
339     return (n << 4) | n;
340 }
341 
FindColor(const char * value,SkColor * colorPtr)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