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