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