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 const unsigned int gColorNames[] = { |
12 | 0x85891945, 0x32a50000, 0x00f0f8ff, // aliceblue |
13 | 0x85d44c6b, 0x16e84d0a, 0x00faebd7, // antiquewhite |
14 | 0x86350800, 0x0000ffff, // aqua |
15 | 0x86350b43, 0x492e2800, 0x007fffd4, // aquamarine |
16 | 0x87559140, 0x00f0ffff, // azure |
17 | 0x88a93940, 0x00f5f5dc, // beige |
18 | 0x89338d4a, 0x00ffe4c4, // bisque |
19 | 0x89811ac0, 0x00000000, // black |
20 | 0x898170d1, 0x1481635f, 0x38800000, 0x00ffebcd, // blanchedalmond |
21 | 0x89952800, 0x000000ff, // blue |
22 | 0x89952d93, 0x3d85a000, 0x008a2be2, // blueviolet |
23 | 0x8a4fbb80, 0x00a52a2a, // brown |
24 | 0x8ab2666f, 0x3de40000, 0x00deb887, // burlywood |
25 | 0x8c242d05, 0x32a50000, 0x005f9ea0, // cadetblue |
26 | 0x8d019525, 0x16b32800, 0x007fff00, // chartreuse |
27 | 0x8d0f1bd9, 0x06850000, 0x00d2691e, // chocolate |
28 | 0x8df20b00, 0x00ff7f50, // coral |
29 | 0x8df27199, 0x3ee59099, 0x54a00000, 0x006495ed, // cornflowerblue |
30 | 0x8df274d3, 0x31600000, 0x00fff8dc, // cornsilk |
31 | 0x8e496cdf, 0x38000000, 0x00dc143c, // crimson |
32 | 0x8f217000, 0x0000ffff, // cyan |
33 | 0x90325899, 0x54a00000, 0x0000008b, // darkblue |
34 | 0x903258f3, 0x05c00000, 0x00008b8b, // darkcyan |
35 | 0x903259df, 0x3085749f, 0x10000000, 0x00b8860b, // darkgoldenrod |
36 | 0x903259e5, 0x07200000, 0x00a9a9a9, // darkgray |
37 | 0x903259e5, 0x14ae0000, 0x00006400, // darkgreen |
38 | 0x90325ad1, 0x05690000, 0x00bdb76b, // darkkhaki |
39 | 0x90325b43, 0x1caea040, 0x008b008b, // darkmagenta |
40 | 0x90325bd9, 0x26c53c8b, 0x15c00000, 0x00556b2f, // darkolivegreen |
41 | 0x90325be5, 0x05c72800, 0x00ff8c00, // darkorange |
42 | 0x90325be5, 0x0d092000, 0x009932cc, // darkorchid |
43 | 0x90325c8b, 0x10000000, 0x008b0000, // darkred |
44 | 0x90325cc3, 0x31af7000, 0x00e9967a, // darksalmon |
45 | 0x90325ccb, 0x04f2295c, 0x008fbc8f, // darkseagreen |
46 | 0x90325cd9, 0x0685132b, 0x14000000, 0x00483d8b, // darkslateblue |
47 | 0x90325cd9, 0x06853c83, 0x64000000, 0x002f4f4f, // darkslategray |
48 | 0x90325d2b, 0x4a357a67, 0x14000000, 0x0000ced1, // darkturquoise |
49 | 0x90325d93, 0x3d85a000, 0x009400d3, // darkviolet |
50 | 0x90a58413, 0x39600000, 0x00ff1493, // deeppink |
51 | 0x90a584d7, 0x644ca940, 0x0000bfff, // deepskyblue |
52 | 0x912d3c83, 0x64000000, 0x00696969, // dimgray |
53 | 0x91e43965, 0x09952800, 0x001e90ff, // dodgerblue |
54 | 0x993228a5, 0x246b0000, 0x00b22222, // firebrick |
55 | 0x998f9059, 0x5d09a140, 0x00fffaf0, // floralwhite |
56 | 0x99f22ce9, 0x1e452b80, 0x00228b22, // forestgreen |
57 | 0x9aa344d3, 0x04000000, 0x00ff00ff, // fuchsia |
58 | 0x9c2974c5, 0x3e4f0000, 0x00dcdcdc, // gainsboro |
59 | 0x9d0f9d2f, 0x21342800, 0x00f8f8ff, // ghostwhite |
60 | 0x9dec2000, 0x00ffd700, // gold |
61 | 0x9dec215d, 0x49e40000, 0x00daa520, // goldenrod |
62 | 0x9e41c800, 0x00808080, // gray |
63 | 0x9e452b80, 0x00008000, // green |
64 | 0x9e452bb3, 0x158c7dc0, 0x00adff2f, // greenyellow |
65 | 0xa1ee2e49, 0x16e00000, 0x00f0fff0, // honeydew |
66 | 0xa1f4825d, 0x2c000000, 0x00ff69b4, // hotpink |
67 | 0xa5c4485d, 0x48a40000, 0x00cd5c5c, // indianred |
68 | 0xa5c449de, 0x004b0082, // indigo |
69 | 0xa6cf9640, 0x00fffff0, // ivory |
70 | 0xad015a40, 0x00f0e68c, // khaki |
71 | 0xb0362b89, 0x16400000, 0x00e6e6fa, // lavender |
72 | 0xb0362b89, 0x16426567, 0x20000000, 0x00fff0f5, // lavenderblush |
73 | 0xb03771e5, 0x14ae0000, 0x007cfc00, // lawngreen |
74 | 0xb0ad7b87, 0x212633dc, 0x00fffacd, // lemonchiffon |
75 | 0xb1274505, 0x32a50000, 0x00add8e6, // lightblue |
76 | 0xb1274507, 0x3e416000, 0x00f08080, // lightcoral |
77 | 0xb1274507, 0x642e0000, 0x00e0ffff, // lightcyan |
78 | 0xb127450f, 0x3d842ba5, 0x3c992b19, 0x3ee00000, 0x00fafad2, // lightgoldenrodyellow |
79 | 0xb127450f, 0x48a57000, 0x0090ee90, // lightgreen |
80 | 0xb127450f, 0x48b90000, 0x00d3d3d3, // lightgrey |
81 | 0xb1274521, 0x25cb0000, 0x00ffb6c1, // lightpink |
82 | 0xb1274527, 0x058d7b80, 0x00ffa07a, // lightsalmon |
83 | 0xb1274527, 0x1427914b, 0x38000000, 0x0020b2aa, // lightseagreen |
84 | 0xb1274527, 0x2f22654a, 0x0087cefa, // lightskyblue |
85 | 0xb1274527, 0x303429e5, 0x07200000, 0x00778899, // lightslategray |
86 | 0xb1274527, 0x50a56099, 0x54a00000, 0x00b0c4de, // lightsteelblue |
87 | 0xb1274533, 0x158c7dc0, 0x00ffffe0, // lightyellow |
88 | 0xb12d2800, 0x0000ff00, // lime |
89 | 0xb12d29e5, 0x14ae0000, 0x0032cd32, // limegreen |
90 | 0xb12e2b80, 0x00faf0e6, // linen |
91 | 0xb4272ba9, 0x04000000, 0x00ff00ff, // magenta |
92 | 0xb4327bdc, 0x00800000, // maroon |
93 | 0xb4a44d5b, 0x06350b43, 0x492e2800, 0x0066cdaa, // mediumaquamarine |
94 | 0xb4a44d5b, 0x09952800, 0x000000cd, // mediumblue |
95 | 0xb4a44d5b, 0x3e434248, 0x00ba55d3, // mediumorchid |
96 | 0xb4a44d5b, 0x42b2830a, 0x009370db, // mediumpurple |
97 | 0xb4a44d5b, 0x4ca13c8b, 0x15c00000, 0x003cb371, // mediumseagreen |
98 | 0xb4a44d5b, 0x4d81a145, 0x32a50000, 0x007b68ee, // mediumslateblue |
99 | 0xb4a44d5b, 0x4e124b8f, 0x1e452b80, 0x0000fa9a, // mediumspringgreen |
100 | 0xb4a44d5b, 0x52b28d5f, 0x26650000, 0x0048d1cc, // mediumturquoise |
101 | 0xb4a44d5b, 0x592f6169, 0x48a40000, 0x00c71585, // mediumvioletred |
102 | 0xb524724f, 0x2282654a, 0x00191970, // midnightblue |
103 | 0xb52ea0e5, 0x142d0000, 0x00f5fffa, // mintcream |
104 | 0xb533a665, 0x3e650000, 0x00ffe4e1, // mistyrose |
105 | 0xb5e31867, 0x25c00000, 0x00ffe4b5, // moccasin |
106 | 0xb8360a9f, 0x5d09a140, 0x00ffdead, // navajowhite |
107 | 0xb836c800, 0x00000080, // navy |
108 | 0xbd846047, 0x14000000, 0x00fdf5e6, // oldlace |
109 | 0xbd89b140, 0x00808000, // olive |
110 | 0xbd89b149, 0x48220000, 0x006b8e23, // olivedrab |
111 | 0xbe4171ca, 0x00ffa500, // orange |
112 | 0xbe4171cb, 0x48a40000, 0x00ff4500, // orangered |
113 | 0xbe434248, 0x00da70d6, // orchid |
114 | 0xc02c29df, 0x3085749f, 0x10000000, 0x00eee8aa, // palegoldenrod |
115 | 0xc02c29e5, 0x14ae0000, 0x0098fb98, // palegreen |
116 | 0xc02c2d2b, 0x4a357a67, 0x14000000, 0x00afeeee, // paleturquoise |
117 | 0xc02c2d93, 0x3d85a48b, 0x10000000, 0x00db7093, // palevioletred |
118 | 0xc0300e43, 0x5d098000, 0x00ffefd5, // papayawhip |
119 | 0xc0a11a21, 0x54c60000, 0x00ffdab9, // peachpuff |
120 | 0xc0b2a800, 0x00cd853f, // peru |
121 | 0xc12e5800, 0x00ffc0cb, // pink |
122 | 0xc1956800, 0x00dda0dd, // plum |
123 | 0xc1f72165, 0x09952800, 0x00b0e0e6, // powderblue |
124 | 0xc2b2830a, 0x00800080, // purple |
125 | 0xc8a40000, 0x00ff0000, // red |
126 | 0xc9f3c8a5, 0x3eee0000, 0x00bc8f8f, // rosybrown |
127 | 0xc9f90b05, 0x32a50000, 0x004169e1, // royalblue |
128 | 0xcc24230b, 0x0a4fbb80, 0x008b4513, // saddlebrown |
129 | 0xcc2c6bdc, 0x00fa8072, // salmon |
130 | 0xcc2e2645, 0x49f77000, 0x00f4a460, // sandybrown |
131 | 0xcca13c8b, 0x15c00000, 0x002e8b57, // seagreen |
132 | 0xcca19a0b, 0x31800000, 0x00fff5ee, // seashell |
133 | 0xcd257382, 0x00a0522d, // sienna |
134 | 0xcd2cb164, 0x00c0c0c0, // silver |
135 | 0xcd79132b, 0x14000000, 0x0087ceeb, // skyblue |
136 | 0xcd81a145, 0x32a50000, 0x006a5acd, // slateblue |
137 | 0xcd81a14f, 0x48390000, 0x00708090, // slategray |
138 | 0xcdcfb800, 0x00fffafa, // snow |
139 | 0xce124b8f, 0x1e452b80, 0x0000ff7f, // springgreen |
140 | 0xce852b05, 0x32a50000, 0x004682b4, // steelblue |
141 | 0xd02e0000, 0x00d2b48c, // tan |
142 | 0xd0a16000, 0x00008080, // teal |
143 | 0xd1099d19, 0x14000000, 0x00d8bfd8, // thistle |
144 | 0xd1ed0d1e, 0x00ff6347, // tomato |
145 | 0xd2b28d5f, 0x26650000, 0x0040e0d0, // turquoise |
146 | 0xd92f6168, 0x00ee82ee, // violet |
147 | 0xdd050d00, 0x00f5deb3, // wheat |
148 | 0xdd09a140, 0x00ffffff, // white |
149 | 0xdd09a167, 0x35eb2800, 0x00f5f5f5, // whitesmoke |
150 | 0xe4ac63ee, 0x00ffff00, // yellow |
151 | 0xe4ac63ef, 0x1e452b80, 0x009acd32 // yellowgreen |
152 | }; // original = 2505 : replacement = 1616 |
153 | |
154 | |
155 | const char* SkParse::FindNamedColor(const char* name, size_t len, SkColor* color) { |
156 | const char* namePtr = name; |
157 | unsigned int sixMatches[4]; |
158 | unsigned int* sixMatchPtr = sixMatches; |
159 | bool first = true; |
160 | bool last = false; |
161 | char ch; |
162 | do { |
163 | unsigned int sixMatch = 0; |
164 | for (int chIndex = 0; chIndex < 6; chIndex++) { |
165 | sixMatch <<= 5; |
166 | ch = *namePtr | 0x20; |
167 | if (ch < 'a' || ch > 'z') |
168 | ch = 0; |
169 | else { |
170 | ch = ch - 'a' + 1; |
171 | namePtr++; |
172 | } |
173 | sixMatch |= ch ; // turn 'A' (0x41) into 'a' (0x61); |
174 | } |
175 | sixMatch <<= 1; |
176 | sixMatch |= 1; |
177 | if (first) { |
178 | sixMatch |= 0x80000000; |
179 | first = false; |
180 | } |
181 | ch = *namePtr | 0x20; |
182 | last = ch < 'a' || ch > 'z'; |
183 | if (last) |
184 | sixMatch &= ~1; |
185 | len -= 6; |
186 | *sixMatchPtr++ = sixMatch; |
187 | } while (last == false && len > 0); |
188 | const int colorNameSize = sizeof(gColorNames) / sizeof(unsigned int); |
189 | int lo = 0; |
190 | int hi = colorNameSize - 3; // back off to beginning of yellowgreen |
191 | while (lo <= hi) { |
192 | int mid = (hi + lo) >> 1; |
193 | while ((int) gColorNames[mid] >= 0) |
194 | --mid; |
195 | sixMatchPtr = sixMatches; |
196 | while (gColorNames[mid] == *sixMatchPtr) { |
197 | ++mid; |
198 | if ((*sixMatchPtr & 1) == 0) { // last |
199 | *color = gColorNames[mid] | 0xFF000000; |
200 | return namePtr; |
201 | } |
202 | ++sixMatchPtr; |
203 | } |
204 | int sixMask = *sixMatchPtr & ~0x80000000; |
205 | int midMask = gColorNames[mid] & ~0x80000000; |
206 | if (sixMask > midMask) { |
207 | lo = mid + 2; // skip color |
208 | while ((int) gColorNames[lo] >= 0) |
209 | ++lo; |
210 | } else if (hi == mid) |
211 | return nullptr; |
212 | else |
213 | hi = mid; |
214 | } |
215 | return nullptr; |
216 | } |
217 | |
218 | // !!! move to char utilities |
219 | //static int count_separators(const char* str, const char* sep) { |
220 | // char c; |
221 | // int separators = 0; |
222 | // while ((c = *str++) != '\0') { |
223 | // if (strchr(sep, c) == nullptr) |
224 | // continue; |
225 | // do { |
226 | // if ((c = *str++) == '\0') |
227 | // goto goHome; |
228 | // } while (strchr(sep, c) != nullptr); |
229 | // separators++; |
230 | // } |
231 | //goHome: |
232 | // return separators; |
233 | //} |
234 | |
235 | static inline unsigned nib2byte(unsigned n) |
236 | { |
237 | SkASSERT((n & ~0xF) == 0); |
238 | return (n << 4) | n; |
239 | } |
240 | |
241 | const char* SkParse::FindColor(const char* value, SkColor* colorPtr) { |
242 | unsigned int oldAlpha = SkColorGetA(*colorPtr); |
243 | if (value[0] == '#') { |
244 | uint32_t hex; |
245 | const char* end = SkParse::FindHex(value + 1, &hex); |
246 | // SkASSERT(end); |
247 | if (end == nullptr) |
248 | return end; |
249 | size_t len = end - value - 1; |
250 | if (len == 3 || len == 4) { |
251 | unsigned a = len == 4 ? nib2byte(hex >> 12) : oldAlpha; |
252 | unsigned r = nib2byte((hex >> 8) & 0xF); |
253 | unsigned g = nib2byte((hex >> 4) & 0xF); |
254 | unsigned b = nib2byte(hex & 0xF); |
255 | *colorPtr = SkColorSetARGB(a, r, g, b); |
256 | return end; |
257 | } else if (len == 6 || len == 8) { |
258 | if (len == 6) |
259 | hex |= oldAlpha << 24; |
260 | *colorPtr = hex; |
261 | return end; |
262 | } else { |
263 | // SkASSERT(0); |
264 | return nullptr; |
265 | } |
266 | // } else if (strchr(value, ',')) { |
267 | // SkScalar array[4]; |
268 | // int count = count_separators(value, ",") + 1; // !!! count commas, add 1 |
269 | // SkASSERT(count == 3 || count == 4); |
270 | // array[0] = SK_Scalar1 * 255; |
271 | // const char* end = SkParse::FindScalars(value, &array[4 - count], count); |
272 | // if (end == nullptr) |
273 | // return nullptr; |
274 | // !!! range check for errors? |
275 | // *colorPtr = SkColorSetARGB(SkScalarRoundToInt(array[0]), SkScalarRoundToInt(array[1]), |
276 | // SkScalarRoundToInt(array[2]), SkScalarRoundToInt(array[3])); |
277 | // return end; |
278 | } else |
279 | return FindNamedColor(value, strlen(value), colorPtr); |
280 | } |
281 | |