• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* libs/graphics/xml/SkParseColor.cpp
2  **
3  ** Copyright 2006, The Android Open Source Project
4  **
5  ** Licensed under the Apache License, Version 2.0 (the "License");
6  ** you may not use this file except in compliance with the License.
7  ** You may obtain a copy of the License at
8  **
9  **     http://www.apache.org/licenses/LICENSE-2.0
10  **
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  */
17  
18  #include "SkParse.h"
19  
20  #ifdef SK_DEBUG
21  #include "SkString.h"
22  
23      // compress names 6 chars per long (packed 5 bits/char )
24          // note: little advantage to splitting chars across longs, since 3 longs at 2 unused bits each
25          // allow for one additional split char (vs. the 18 unsplit chars in the three longs)
26      // use extra two bits to represent:
27          // 00 : final 6 (or fewer) chars (if 'a' is 0x01, zero could have special meaning)
28          // 01 : not final 6 chars
29          // 10 : color
30          // 11 : unused, except as debugging sentinal? (could be -1 for easier test)
31      // !!! the bit to end the word (last) is at the low bit for binary search
32      // lookup first character in offset for quick start
33          // offset is 27-entry table of bytes(?) that trims linear search to at most 21 entries ('d')
34      // shift match into long; set bit 30 if it all doesn't fit
35      // while longs don't match, march forward
36          // if they do match, and bit 30 is set, advance match, clearing bit 30 if
37          // final chars, and advance to next test
38          // if they do match, and bit 30 is clear, get next long (color) and return it
39      // stop at lookup of first char + 1
40  static const struct SkNameRGB {
41      const char* name;
42      int rgb;
43  } colorNames[] = {
44      { "aliceblue",            0xF0F8FF },
45      { "antiquewhite",         0xFAEBD7 },
46      { "aqua",                 0x00FFFF },
47      { "aquamarine",           0x7FFFD4 },
48      { "azure",                0xF0FFFF },
49      { "beige",                0xF5F5DC },
50      { "bisque",               0xFFE4C4 },
51      { "black",                0x000000 },
52      { "blanchedalmond",       0xFFEBCD },
53      { "blue",                 0x0000FF },
54      { "blueviolet",           0x8A2BE2 },
55      { "brown",                0xA52A2A },
56      { "burlywood",            0xDEB887 },
57      { "cadetblue",            0x5F9EA0 },
58      { "chartreuse",           0x7FFF00 },
59      { "chocolate",            0xD2691E },
60      { "coral",                0xFF7F50 },
61      { "cornflowerblue",       0x6495ED },
62      { "cornsilk",             0xFFF8DC },
63      { "crimson",              0xDC143C },
64      { "cyan",                 0x00FFFF },
65      { "darkblue",             0x00008B },
66      { "darkcyan",             0x008B8B },
67      { "darkgoldenrod",        0xB8860B },
68      { "darkgray",             0xA9A9A9 },
69      { "darkgreen",            0x006400 },
70      { "darkkhaki",            0xBDB76B },
71      { "darkmagenta",          0x8B008B },
72      { "darkolivegreen",       0x556B2F },
73      { "darkorange",           0xFF8C00 },
74      { "darkorchid",           0x9932CC },
75      { "darkred",              0x8B0000 },
76      { "darksalmon",           0xE9967A },
77      { "darkseagreen",         0x8FBC8F },
78      { "darkslateblue",        0x483D8B },
79      { "darkslategray",        0x2F4F4F },
80      { "darkturquoise",        0x00CED1 },
81      { "darkviolet",           0x9400D3 },
82      { "deeppink",             0xFF1493 },
83      { "deepskyblue",          0x00BFFF },
84      { "dimgray",              0x696969 },
85      { "dodgerblue",           0x1E90FF },
86      { "firebrick",            0xB22222 },
87      { "floralwhite",          0xFFFAF0 },
88      { "forestgreen",          0x228B22 },
89      { "fuchsia",              0xFF00FF },
90      { "gainsboro",            0xDCDCDC },
91      { "ghostwhite",           0xF8F8FF },
92      { "gold",                 0xFFD700 },
93      { "goldenrod",            0xDAA520 },
94      { "gray",                 0x808080 },
95      { "green",                0x008000 },
96      { "greenyellow",          0xADFF2F },
97      { "honeydew",             0xF0FFF0 },
98      { "hotpink",              0xFF69B4 },
99      { "indianred",            0xCD5C5C },
100      { "indigo",               0x4B0082 },
101      { "ivory",                0xFFFFF0 },
102      { "khaki",                0xF0E68C },
103      { "lavender",             0xE6E6FA },
104      { "lavenderblush",        0xFFF0F5 },
105      { "lawngreen",            0x7CFC00 },
106      { "lemonchiffon",         0xFFFACD },
107      { "lightblue",            0xADD8E6 },
108      { "lightcoral",           0xF08080 },
109      { "lightcyan",            0xE0FFFF },
110      { "lightgoldenrodyellow", 0xFAFAD2 },
111      { "lightgreen",           0x90EE90 },
112      { "lightgrey",            0xD3D3D3 },
113      { "lightpink",            0xFFB6C1 },
114      { "lightsalmon",          0xFFA07A },
115      { "lightseagreen",        0x20B2AA },
116      { "lightskyblue",         0x87CEFA },
117      { "lightslategray",       0x778899 },
118      { "lightsteelblue",       0xB0C4DE },
119      { "lightyellow",          0xFFFFE0 },
120      { "lime",                 0x00FF00 },
121      { "limegreen",            0x32CD32 },
122      { "linen",                0xFAF0E6 },
123      { "magenta",              0xFF00FF },
124      { "maroon",               0x800000 },
125      { "mediumaquamarine",     0x66CDAA },
126      { "mediumblue",           0x0000CD },
127      { "mediumorchid",         0xBA55D3 },
128      { "mediumpurple",         0x9370DB },
129      { "mediumseagreen",       0x3CB371 },
130      { "mediumslateblue",      0x7B68EE },
131      { "mediumspringgreen",    0x00FA9A },
132      { "mediumturquoise",      0x48D1CC },
133      { "mediumvioletred",      0xC71585 },
134      { "midnightblue",         0x191970 },
135      { "mintcream",            0xF5FFFA },
136      { "mistyrose",            0xFFE4E1 },
137      { "moccasin",             0xFFE4B5 },
138      { "navajowhite",          0xFFDEAD },
139      { "navy",                 0x000080 },
140      { "oldlace",              0xFDF5E6 },
141      { "olive",                0x808000 },
142      { "olivedrab",            0x6B8E23 },
143      { "orange",               0xFFA500 },
144      { "orangered",            0xFF4500 },
145      { "orchid",               0xDA70D6 },
146      { "palegoldenrod",        0xEEE8AA },
147      { "palegreen",            0x98FB98 },
148      { "paleturquoise",        0xAFEEEE },
149      { "palevioletred",        0xDB7093 },
150      { "papayawhip",           0xFFEFD5 },
151      { "peachpuff",            0xFFDAB9 },
152      { "peru",                 0xCD853F },
153      { "pink",                 0xFFC0CB },
154      { "plum",                 0xDDA0DD },
155      { "powderblue",           0xB0E0E6 },
156      { "purple",               0x800080 },
157      { "red",                  0xFF0000 },
158      { "rosybrown",            0xBC8F8F },
159      { "royalblue",            0x4169E1 },
160      { "saddlebrown",          0x8B4513 },
161      { "salmon",               0xFA8072 },
162      { "sandybrown",           0xF4A460 },
163      { "seagreen",             0x2E8B57 },
164      { "seashell",             0xFFF5EE },
165      { "sienna",               0xA0522D },
166      { "silver",               0xC0C0C0 },
167      { "skyblue",              0x87CEEB },
168      { "slateblue",            0x6A5ACD },
169      { "slategray",            0x708090 },
170      { "snow",                 0xFFFAFA },
171      { "springgreen",          0x00FF7F },
172      { "steelblue",            0x4682B4 },
173      { "tan",                  0xD2B48C },
174      { "teal",                 0x008080 },
175      { "thistle",              0xD8BFD8 },
176      { "tomato",               0xFF6347 },
177      { "turquoise",            0x40E0D0 },
178      { "violet",               0xEE82EE },
179      { "wheat",                0xF5DEB3 },
180      { "white",                0xFFFFFF },
181      { "whitesmoke",           0xF5F5F5 },
182      { "yellow",               0xFFFF00 },
183      { "yellowgreen",          0x9ACD32 }
184  };
185  
186  int colorNamesSize = sizeof(colorNames) / sizeof(colorNames[0]);
187  
188  #ifdef SK_SUPPORT_UNITTEST
CreateTable()189  static void CreateTable() {
190      SkString comment;
191      size_t originalSize = 0;
192      int replacement = 0;
193      for (int index = 0; index < colorNamesSize; index++) {
194          SkNameRGB nameRGB =  colorNames[index];
195          const char* name = nameRGB.name;
196          size_t len = strlen(name);
197          originalSize += len + 9;
198          bool first = true;
199          bool last = false;
200          do {
201              int compressed = 0;
202              const char* start = name;
203              for (int chIndex = 0; chIndex < 6; chIndex++) {
204                  compressed <<= 5;
205                  compressed |= *name ? *name++ - 'a' + 1 : 0 ;
206              }
207              replacement += sizeof(int);
208              compressed <<= 1;
209              compressed |= 1;
210              if (first) {
211                  compressed |= 0x80000000;
212                  first = false;
213              }
214              if (len <= 6) { // last
215                  compressed &= ~1;
216                  last = true;
217              }
218              len -= 6;
219              SkDebugf("0x%08x, ", compressed);
220              comment.append(start, name - start);
221          } while (last == false);
222          replacement += sizeof(int);
223          SkDebugf("0x%08x, ", nameRGB.rgb);
224          SkDebugf("// %s\n", comment.c_str());
225          comment.reset();
226      }
227      SkDebugf("// original = %d : replacement = %d\n", originalSize, replacement);
228      SkASSERT(0); // always stop after creating table
229  }
230  #endif
231  
232  #endif
233  
234  static const unsigned int gColorNames[] = {
235  0x85891945, 0x32a50000, 0x00f0f8ff, // aliceblue
236  0x85d44c6b, 0x16e84d0a, 0x00faebd7, // antiquewhite
237  0x86350800, 0x0000ffff, // aqua
238  0x86350b43, 0x492e2800, 0x007fffd4, // aquamarine
239  0x87559140, 0x00f0ffff, // azure
240  0x88a93940, 0x00f5f5dc, // beige
241  0x89338d4a, 0x00ffe4c4, // bisque
242  0x89811ac0, 0x00000000, // black
243  0x898170d1, 0x1481635f, 0x38800000, 0x00ffebcd, // blanchedalmond
244  0x89952800, 0x000000ff, // blue
245  0x89952d93, 0x3d85a000, 0x008a2be2, // blueviolet
246  0x8a4fbb80, 0x00a52a2a, // brown
247  0x8ab2666f, 0x3de40000, 0x00deb887, // burlywood
248  0x8c242d05, 0x32a50000, 0x005f9ea0, // cadetblue
249  0x8d019525, 0x16b32800, 0x007fff00, // chartreuse
250  0x8d0f1bd9, 0x06850000, 0x00d2691e, // chocolate
251  0x8df20b00, 0x00ff7f50, // coral
252  0x8df27199, 0x3ee59099, 0x54a00000, 0x006495ed, // cornflowerblue
253  0x8df274d3, 0x31600000, 0x00fff8dc, // cornsilk
254  0x8e496cdf, 0x38000000, 0x00dc143c, // crimson
255  0x8f217000, 0x0000ffff, // cyan
256  0x90325899, 0x54a00000, 0x0000008b, // darkblue
257  0x903258f3, 0x05c00000, 0x00008b8b, // darkcyan
258  0x903259df, 0x3085749f, 0x10000000, 0x00b8860b, // darkgoldenrod
259  0x903259e5, 0x07200000, 0x00a9a9a9, // darkgray
260  0x903259e5, 0x14ae0000, 0x00006400, // darkgreen
261  0x90325ad1, 0x05690000, 0x00bdb76b, // darkkhaki
262  0x90325b43, 0x1caea040, 0x008b008b, // darkmagenta
263  0x90325bd9, 0x26c53c8b, 0x15c00000, 0x00556b2f, // darkolivegreen
264  0x90325be5, 0x05c72800, 0x00ff8c00, // darkorange
265  0x90325be5, 0x0d092000, 0x009932cc, // darkorchid
266  0x90325c8b, 0x10000000, 0x008b0000, // darkred
267  0x90325cc3, 0x31af7000, 0x00e9967a, // darksalmon
268  0x90325ccb, 0x04f2295c, 0x008fbc8f, // darkseagreen
269  0x90325cd9, 0x0685132b, 0x14000000, 0x00483d8b, // darkslateblue
270  0x90325cd9, 0x06853c83, 0x64000000, 0x002f4f4f, // darkslategray
271  0x90325d2b, 0x4a357a67, 0x14000000, 0x0000ced1, // darkturquoise
272  0x90325d93, 0x3d85a000, 0x009400d3, // darkviolet
273  0x90a58413, 0x39600000, 0x00ff1493, // deeppink
274  0x90a584d7, 0x644ca940, 0x0000bfff, // deepskyblue
275  0x912d3c83, 0x64000000, 0x00696969, // dimgray
276  0x91e43965, 0x09952800, 0x001e90ff, // dodgerblue
277  0x993228a5, 0x246b0000, 0x00b22222, // firebrick
278  0x998f9059, 0x5d09a140, 0x00fffaf0, // floralwhite
279  0x99f22ce9, 0x1e452b80, 0x00228b22, // forestgreen
280  0x9aa344d3, 0x04000000, 0x00ff00ff, // fuchsia
281  0x9c2974c5, 0x3e4f0000, 0x00dcdcdc, // gainsboro
282  0x9d0f9d2f, 0x21342800, 0x00f8f8ff, // ghostwhite
283  0x9dec2000, 0x00ffd700, // gold
284  0x9dec215d, 0x49e40000, 0x00daa520, // goldenrod
285  0x9e41c800, 0x00808080, // gray
286  0x9e452b80, 0x00008000, // green
287  0x9e452bb3, 0x158c7dc0, 0x00adff2f, // greenyellow
288  0xa1ee2e49, 0x16e00000, 0x00f0fff0, // honeydew
289  0xa1f4825d, 0x2c000000, 0x00ff69b4, // hotpink
290  0xa5c4485d, 0x48a40000, 0x00cd5c5c, // indianred
291  0xa5c449de, 0x004b0082, // indigo
292  0xa6cf9640, 0x00fffff0, // ivory
293  0xad015a40, 0x00f0e68c, // khaki
294  0xb0362b89, 0x16400000, 0x00e6e6fa, // lavender
295  0xb0362b89, 0x16426567, 0x20000000, 0x00fff0f5, // lavenderblush
296  0xb03771e5, 0x14ae0000, 0x007cfc00, // lawngreen
297  0xb0ad7b87, 0x212633dc, 0x00fffacd, // lemonchiffon
298  0xb1274505, 0x32a50000, 0x00add8e6, // lightblue
299  0xb1274507, 0x3e416000, 0x00f08080, // lightcoral
300  0xb1274507, 0x642e0000, 0x00e0ffff, // lightcyan
301  0xb127450f, 0x3d842ba5, 0x3c992b19, 0x3ee00000, 0x00fafad2, // lightgoldenrodyellow
302  0xb127450f, 0x48a57000, 0x0090ee90, // lightgreen
303  0xb127450f, 0x48b90000, 0x00d3d3d3, // lightgrey
304  0xb1274521, 0x25cb0000, 0x00ffb6c1, // lightpink
305  0xb1274527, 0x058d7b80, 0x00ffa07a, // lightsalmon
306  0xb1274527, 0x1427914b, 0x38000000, 0x0020b2aa, // lightseagreen
307  0xb1274527, 0x2f22654a, 0x0087cefa, // lightskyblue
308  0xb1274527, 0x303429e5, 0x07200000, 0x00778899, // lightslategray
309  0xb1274527, 0x50a56099, 0x54a00000, 0x00b0c4de, // lightsteelblue
310  0xb1274533, 0x158c7dc0, 0x00ffffe0, // lightyellow
311  0xb12d2800, 0x0000ff00, // lime
312  0xb12d29e5, 0x14ae0000, 0x0032cd32, // limegreen
313  0xb12e2b80, 0x00faf0e6, // linen
314  0xb4272ba9, 0x04000000, 0x00ff00ff, // magenta
315  0xb4327bdc, 0x00800000, // maroon
316  0xb4a44d5b, 0x06350b43, 0x492e2800, 0x0066cdaa, // mediumaquamarine
317  0xb4a44d5b, 0x09952800, 0x000000cd, // mediumblue
318  0xb4a44d5b, 0x3e434248, 0x00ba55d3, // mediumorchid
319  0xb4a44d5b, 0x42b2830a, 0x009370db, // mediumpurple
320  0xb4a44d5b, 0x4ca13c8b, 0x15c00000, 0x003cb371, // mediumseagreen
321  0xb4a44d5b, 0x4d81a145, 0x32a50000, 0x007b68ee, // mediumslateblue
322  0xb4a44d5b, 0x4e124b8f, 0x1e452b80, 0x0000fa9a, // mediumspringgreen
323  0xb4a44d5b, 0x52b28d5f, 0x26650000, 0x0048d1cc, // mediumturquoise
324  0xb4a44d5b, 0x592f6169, 0x48a40000, 0x00c71585, // mediumvioletred
325  0xb524724f, 0x2282654a, 0x00191970, // midnightblue
326  0xb52ea0e5, 0x142d0000, 0x00f5fffa, // mintcream
327  0xb533a665, 0x3e650000, 0x00ffe4e1, // mistyrose
328  0xb5e31867, 0x25c00000, 0x00ffe4b5, // moccasin
329  0xb8360a9f, 0x5d09a140, 0x00ffdead, // navajowhite
330  0xb836c800, 0x00000080, // navy
331  0xbd846047, 0x14000000, 0x00fdf5e6, // oldlace
332  0xbd89b140, 0x00808000, // olive
333  0xbd89b149, 0x48220000, 0x006b8e23, // olivedrab
334  0xbe4171ca, 0x00ffa500, // orange
335  0xbe4171cb, 0x48a40000, 0x00ff4500, // orangered
336  0xbe434248, 0x00da70d6, // orchid
337  0xc02c29df, 0x3085749f, 0x10000000, 0x00eee8aa, // palegoldenrod
338  0xc02c29e5, 0x14ae0000, 0x0098fb98, // palegreen
339  0xc02c2d2b, 0x4a357a67, 0x14000000, 0x00afeeee, // paleturquoise
340  0xc02c2d93, 0x3d85a48b, 0x10000000, 0x00db7093, // palevioletred
341  0xc0300e43, 0x5d098000, 0x00ffefd5, // papayawhip
342  0xc0a11a21, 0x54c60000, 0x00ffdab9, // peachpuff
343  0xc0b2a800, 0x00cd853f, // peru
344  0xc12e5800, 0x00ffc0cb, // pink
345  0xc1956800, 0x00dda0dd, // plum
346  0xc1f72165, 0x09952800, 0x00b0e0e6, // powderblue
347  0xc2b2830a, 0x00800080, // purple
348  0xc8a40000, 0x00ff0000, // red
349  0xc9f3c8a5, 0x3eee0000, 0x00bc8f8f, // rosybrown
350  0xc9f90b05, 0x32a50000, 0x004169e1, // royalblue
351  0xcc24230b, 0x0a4fbb80, 0x008b4513, // saddlebrown
352  0xcc2c6bdc, 0x00fa8072, // salmon
353  0xcc2e2645, 0x49f77000, 0x00f4a460, // sandybrown
354  0xcca13c8b, 0x15c00000, 0x002e8b57, // seagreen
355  0xcca19a0b, 0x31800000, 0x00fff5ee, // seashell
356  0xcd257382, 0x00a0522d, // sienna
357  0xcd2cb164, 0x00c0c0c0, // silver
358  0xcd79132b, 0x14000000, 0x0087ceeb, // skyblue
359  0xcd81a145, 0x32a50000, 0x006a5acd, // slateblue
360  0xcd81a14f, 0x48390000, 0x00708090, // slategray
361  0xcdcfb800, 0x00fffafa, // snow
362  0xce124b8f, 0x1e452b80, 0x0000ff7f, // springgreen
363  0xce852b05, 0x32a50000, 0x004682b4, // steelblue
364  0xd02e0000, 0x00d2b48c, // tan
365  0xd0a16000, 0x00008080, // teal
366  0xd1099d19, 0x14000000, 0x00d8bfd8, // thistle
367  0xd1ed0d1e, 0x00ff6347, // tomato
368  0xd2b28d5f, 0x26650000, 0x0040e0d0, // turquoise
369  0xd92f6168, 0x00ee82ee, // violet
370  0xdd050d00, 0x00f5deb3, // wheat
371  0xdd09a140, 0x00ffffff, // white
372  0xdd09a167, 0x35eb2800, 0x00f5f5f5, // whitesmoke
373  0xe4ac63ee, 0x00ffff00, // yellow
374  0xe4ac63ef, 0x1e452b80, 0x009acd32 // yellowgreen
375  }; // original = 2505 : replacement = 1616
376  
377  
FindNamedColor(const char * name,size_t len,SkColor * color)378  const char* SkParse::FindNamedColor(const char* name, size_t len, SkColor* color) {
379      const char* namePtr = name;
380      unsigned int sixMatches[4];
381      unsigned int* sixMatchPtr = sixMatches;
382      bool first = true;
383      bool last = false;
384      char ch;
385      do {
386          unsigned int sixMatch = 0;
387          for (int chIndex = 0; chIndex < 6; chIndex++) {
388              sixMatch <<= 5;
389              ch = *namePtr  | 0x20;
390              if (ch < 'a' || ch > 'z')
391                  ch = 0;
392              else {
393                  ch = ch - 'a' + 1;
394                  namePtr++;
395              }
396              sixMatch |= ch ;  // turn 'A' (0x41) into 'a' (0x61);
397          }
398          sixMatch <<= 1;
399          sixMatch |= 1;
400          if (first) {
401              sixMatch |= 0x80000000;
402              first = false;
403          }
404          ch = *namePtr | 0x20;
405          last = ch < 'a' || ch > 'z';
406          if (last)
407              sixMatch &= ~1;
408          len -= 6;
409          *sixMatchPtr++ = sixMatch;
410      } while (last == false && len > 0);
411      const int colorNameSize = sizeof(gColorNames) / sizeof(unsigned int);
412      int lo = 0;
413      int hi = colorNameSize - 3; // back off to beginning of yellowgreen
414      while (lo <= hi) {
415          int mid = (hi + lo) >> 1;
416          while ((int) gColorNames[mid] >= 0)
417              --mid;
418          sixMatchPtr = sixMatches;
419          while (gColorNames[mid] == *sixMatchPtr) {
420              ++mid;
421              if ((*sixMatchPtr & 1) == 0) { // last
422                  *color = gColorNames[mid] | 0xFF000000;
423                  return namePtr;
424              }
425              ++sixMatchPtr;
426          }
427          int sixMask = *sixMatchPtr & ~0x80000000;
428          int midMask = gColorNames[mid] & ~0x80000000;
429          if (sixMask > midMask) {
430              lo = mid + 2;   // skip color
431              while ((int) gColorNames[lo] >= 0)
432                  ++lo;
433          } else if (hi == mid)
434              return NULL;
435          else
436              hi = mid;
437      }
438      return NULL;
439  }
440  
441  // !!! move to char utilities
442  //static int count_separators(const char* str, const char* sep) {
443  //  char c;
444  //  int separators = 0;
445  //  while ((c = *str++) != '\0') {
446  //      if (strchr(sep, c) == NULL)
447  //          continue;
448  //      do {
449  //          if ((c = *str++) == '\0')
450  //              goto goHome;
451  //      } while (strchr(sep, c) != NULL);
452  //      separators++;
453  //  }
454  //goHome:
455  //  return separators;
456  //}
457  
nib2byte(unsigned n)458  static inline unsigned nib2byte(unsigned n)
459  {
460      SkASSERT((n & ~0xF) == 0);
461      return (n << 4) | n;
462  }
463  
FindColor(const char * value,SkColor * colorPtr)464  const char* SkParse::FindColor(const char* value, SkColor* colorPtr) {
465      unsigned int oldAlpha = SkColorGetA(*colorPtr);
466      if (value[0] == '#') {
467          uint32_t    hex;
468          const char* end = SkParse::FindHex(value + 1, &hex);
469  //      SkASSERT(end);
470          if (end == NULL)
471              return end;
472          size_t len = end - value - 1;
473          if (len == 3 || len == 4) {
474              unsigned a = len == 4 ? nib2byte(hex >> 12) : oldAlpha;
475              unsigned r = nib2byte((hex >> 8) & 0xF);
476              unsigned g = nib2byte((hex >> 4) & 0xF);
477              unsigned b = nib2byte(hex & 0xF);
478              *colorPtr = SkColorSetARGB(a, r, g, b);
479              return end;
480          } else if (len == 6 || len == 8) {
481              if (len == 6)
482                  hex |= oldAlpha << 24;
483              *colorPtr = hex;
484              return end;
485          } else {
486  //          SkASSERT(0);
487              return NULL;
488          }
489  //  } else if (strchr(value, ',')) {
490  //      SkScalar array[4];
491  //      int count = count_separators(value, ",") + 1; // !!! count commas, add 1
492  //      SkASSERT(count == 3 || count == 4);
493  //      array[0] = SK_Scalar1 * 255;
494  //      const char* end = SkParse::FindScalars(value, &array[4 - count], count);
495  //      if (end == NULL)
496  //          return NULL;
497          // !!! range check for errors?
498  //      *colorPtr = SkColorSetARGB(SkScalarRound(array[0]), SkScalarRound(array[1]),
499  //          SkScalarRound(array[2]), SkScalarRound(array[3]));
500  //      return end;
501      } else
502          return FindNamedColor(value, strlen(value), colorPtr);
503  }
504  
505  #ifdef SK_SUPPORT_UNITTEST
TestColor()506  void SkParse::TestColor() {
507      if (false)
508          CreateTable();  // regenerates data table in the output window
509      SkColor result;
510      int index;
511      for (index = 0; index < colorNamesSize; index++) {
512          result = SK_ColorBLACK;
513          SkNameRGB nameRGB = colorNames[index];
514          SkASSERT(FindColor(nameRGB.name, &result) != NULL);
515          SkASSERT(result == (SkColor) (nameRGB.rgb | 0xFF000000));
516      }
517      for (index = 0; index < colorNamesSize; index++) {
518          result = SK_ColorBLACK;
519          SkNameRGB nameRGB = colorNames[index];
520          char bad[24];
521          size_t len = strlen(nameRGB.name);
522          memcpy(bad, nameRGB.name, len);
523          bad[len - 1] -= 1;
524          SkASSERT(FindColor(bad, &result) == false);
525          bad[len - 1] += 2;
526          SkASSERT(FindColor(bad, &result) == false);
527      }
528      result = SK_ColorBLACK;
529      SkASSERT(FindColor("lightGrey", &result));
530      SkASSERT(result == 0xffd3d3d3);
531  //  SkASSERT(FindColor("12,34,56,78", &result));
532  //  SkASSERT(result == ((12 << 24) | (34 << 16) | (56 << 8) | (78 << 0)));
533      result = SK_ColorBLACK;
534      SkASSERT(FindColor("#ABCdef", &result));
535      SkASSERT(result == 0XFFABCdef);
536      SkASSERT(FindColor("#12ABCdef", &result));
537      SkASSERT(result == 0X12ABCdef);
538      result = SK_ColorBLACK;
539      SkASSERT(FindColor("#123", &result));
540      SkASSERT(result == 0Xff112233);
541      SkASSERT(FindColor("#abcd", &result));
542      SkASSERT(result == 0Xaabbccdd);
543      result = SK_ColorBLACK;
544  //  SkASSERT(FindColor("71,162,253", &result));
545  //  SkASSERT(result == ((0xFF << 24) | (71 << 16) | (162 << 8) | (253 << 0)));
546  }
547  #endif
548  
549