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
11static 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
154static 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
299const 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
336static inline unsigned nib2byte(unsigned n)
337{
338 SkASSERT((n & ~0xF) == 0);
339 return (n << 4) | n;
340}
341
342const 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