reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame^] | 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 | static void CreateTable() { |
| 189 | SkString comment; |
| 190 | size_t originalSize = 0; |
| 191 | int replacement = 0; |
| 192 | for (int index = 0; index < colorNamesSize; index++) { |
| 193 | SkNameRGB nameRGB = colorNames[index]; |
| 194 | const char* name = nameRGB.name; |
| 195 | size_t len = strlen(name); |
| 196 | originalSize += len + 9; |
| 197 | bool first = true; |
| 198 | bool last = false; |
| 199 | do { |
| 200 | int compressed = 0; |
| 201 | const char* start = name; |
| 202 | for (int chIndex = 0; chIndex < 6; chIndex++) { |
| 203 | compressed <<= 5; |
| 204 | compressed |= *name ? *name++ - 'a' + 1 : 0 ; |
| 205 | } |
| 206 | replacement += sizeof(int); |
| 207 | compressed <<= 1; |
| 208 | compressed |= 1; |
| 209 | if (first) { |
| 210 | compressed |= 0x80000000; |
| 211 | first = false; |
| 212 | } |
| 213 | if (len <= 6) { // last |
| 214 | compressed &= ~1; |
| 215 | last = true; |
| 216 | } |
| 217 | len -= 6; |
| 218 | SkDebugf("0x%08x, ", compressed); |
| 219 | comment.append(start, name - start); |
| 220 | } while (last == false); |
| 221 | replacement += sizeof(int); |
| 222 | SkDebugf("0x%08x, ", nameRGB.rgb); |
| 223 | SkDebugf("// %s\n", comment.c_str()); |
| 224 | comment.reset(); |
| 225 | } |
| 226 | SkDebugf("// original = %d : replacement = %d\n", originalSize, replacement); |
| 227 | SkASSERT(0); // always stop after creating table |
| 228 | } |
| 229 | |
| 230 | #endif |
| 231 | |
| 232 | static const unsigned int gColorNames[] = { |
| 233 | 0x85891945, 0x32a50000, 0x00f0f8ff, // aliceblue |
| 234 | 0x85d44c6b, 0x16e84d0a, 0x00faebd7, // antiquewhite |
| 235 | 0x86350800, 0x0000ffff, // aqua |
| 236 | 0x86350b43, 0x492e2800, 0x007fffd4, // aquamarine |
| 237 | 0x87559140, 0x00f0ffff, // azure |
| 238 | 0x88a93940, 0x00f5f5dc, // beige |
| 239 | 0x89338d4a, 0x00ffe4c4, // bisque |
| 240 | 0x89811ac0, 0x00000000, // black |
| 241 | 0x898170d1, 0x1481635f, 0x38800000, 0x00ffebcd, // blanchedalmond |
| 242 | 0x89952800, 0x000000ff, // blue |
| 243 | 0x89952d93, 0x3d85a000, 0x008a2be2, // blueviolet |
| 244 | 0x8a4fbb80, 0x00a52a2a, // brown |
| 245 | 0x8ab2666f, 0x3de40000, 0x00deb887, // burlywood |
| 246 | 0x8c242d05, 0x32a50000, 0x005f9ea0, // cadetblue |
| 247 | 0x8d019525, 0x16b32800, 0x007fff00, // chartreuse |
| 248 | 0x8d0f1bd9, 0x06850000, 0x00d2691e, // chocolate |
| 249 | 0x8df20b00, 0x00ff7f50, // coral |
| 250 | 0x8df27199, 0x3ee59099, 0x54a00000, 0x006495ed, // cornflowerblue |
| 251 | 0x8df274d3, 0x31600000, 0x00fff8dc, // cornsilk |
| 252 | 0x8e496cdf, 0x38000000, 0x00dc143c, // crimson |
| 253 | 0x8f217000, 0x0000ffff, // cyan |
| 254 | 0x90325899, 0x54a00000, 0x0000008b, // darkblue |
| 255 | 0x903258f3, 0x05c00000, 0x00008b8b, // darkcyan |
| 256 | 0x903259df, 0x3085749f, 0x10000000, 0x00b8860b, // darkgoldenrod |
| 257 | 0x903259e5, 0x07200000, 0x00a9a9a9, // darkgray |
| 258 | 0x903259e5, 0x14ae0000, 0x00006400, // darkgreen |
| 259 | 0x90325ad1, 0x05690000, 0x00bdb76b, // darkkhaki |
| 260 | 0x90325b43, 0x1caea040, 0x008b008b, // darkmagenta |
| 261 | 0x90325bd9, 0x26c53c8b, 0x15c00000, 0x00556b2f, // darkolivegreen |
| 262 | 0x90325be5, 0x05c72800, 0x00ff8c00, // darkorange |
| 263 | 0x90325be5, 0x0d092000, 0x009932cc, // darkorchid |
| 264 | 0x90325c8b, 0x10000000, 0x008b0000, // darkred |
| 265 | 0x90325cc3, 0x31af7000, 0x00e9967a, // darksalmon |
| 266 | 0x90325ccb, 0x04f2295c, 0x008fbc8f, // darkseagreen |
| 267 | 0x90325cd9, 0x0685132b, 0x14000000, 0x00483d8b, // darkslateblue |
| 268 | 0x90325cd9, 0x06853c83, 0x64000000, 0x002f4f4f, // darkslategray |
| 269 | 0x90325d2b, 0x4a357a67, 0x14000000, 0x0000ced1, // darkturquoise |
| 270 | 0x90325d93, 0x3d85a000, 0x009400d3, // darkviolet |
| 271 | 0x90a58413, 0x39600000, 0x00ff1493, // deeppink |
| 272 | 0x90a584d7, 0x644ca940, 0x0000bfff, // deepskyblue |
| 273 | 0x912d3c83, 0x64000000, 0x00696969, // dimgray |
| 274 | 0x91e43965, 0x09952800, 0x001e90ff, // dodgerblue |
| 275 | 0x993228a5, 0x246b0000, 0x00b22222, // firebrick |
| 276 | 0x998f9059, 0x5d09a140, 0x00fffaf0, // floralwhite |
| 277 | 0x99f22ce9, 0x1e452b80, 0x00228b22, // forestgreen |
| 278 | 0x9aa344d3, 0x04000000, 0x00ff00ff, // fuchsia |
| 279 | 0x9c2974c5, 0x3e4f0000, 0x00dcdcdc, // gainsboro |
| 280 | 0x9d0f9d2f, 0x21342800, 0x00f8f8ff, // ghostwhite |
| 281 | 0x9dec2000, 0x00ffd700, // gold |
| 282 | 0x9dec215d, 0x49e40000, 0x00daa520, // goldenrod |
| 283 | 0x9e41c800, 0x00808080, // gray |
| 284 | 0x9e452b80, 0x00008000, // green |
| 285 | 0x9e452bb3, 0x158c7dc0, 0x00adff2f, // greenyellow |
| 286 | 0xa1ee2e49, 0x16e00000, 0x00f0fff0, // honeydew |
| 287 | 0xa1f4825d, 0x2c000000, 0x00ff69b4, // hotpink |
| 288 | 0xa5c4485d, 0x48a40000, 0x00cd5c5c, // indianred |
| 289 | 0xa5c449de, 0x004b0082, // indigo |
| 290 | 0xa6cf9640, 0x00fffff0, // ivory |
| 291 | 0xad015a40, 0x00f0e68c, // khaki |
| 292 | 0xb0362b89, 0x16400000, 0x00e6e6fa, // lavender |
| 293 | 0xb0362b89, 0x16426567, 0x20000000, 0x00fff0f5, // lavenderblush |
| 294 | 0xb03771e5, 0x14ae0000, 0x007cfc00, // lawngreen |
| 295 | 0xb0ad7b87, 0x212633dc, 0x00fffacd, // lemonchiffon |
| 296 | 0xb1274505, 0x32a50000, 0x00add8e6, // lightblue |
| 297 | 0xb1274507, 0x3e416000, 0x00f08080, // lightcoral |
| 298 | 0xb1274507, 0x642e0000, 0x00e0ffff, // lightcyan |
| 299 | 0xb127450f, 0x3d842ba5, 0x3c992b19, 0x3ee00000, 0x00fafad2, // lightgoldenrodyellow |
| 300 | 0xb127450f, 0x48a57000, 0x0090ee90, // lightgreen |
| 301 | 0xb127450f, 0x48b90000, 0x00d3d3d3, // lightgrey |
| 302 | 0xb1274521, 0x25cb0000, 0x00ffb6c1, // lightpink |
| 303 | 0xb1274527, 0x058d7b80, 0x00ffa07a, // lightsalmon |
| 304 | 0xb1274527, 0x1427914b, 0x38000000, 0x0020b2aa, // lightseagreen |
| 305 | 0xb1274527, 0x2f22654a, 0x0087cefa, // lightskyblue |
| 306 | 0xb1274527, 0x303429e5, 0x07200000, 0x00778899, // lightslategray |
| 307 | 0xb1274527, 0x50a56099, 0x54a00000, 0x00b0c4de, // lightsteelblue |
| 308 | 0xb1274533, 0x158c7dc0, 0x00ffffe0, // lightyellow |
| 309 | 0xb12d2800, 0x0000ff00, // lime |
| 310 | 0xb12d29e5, 0x14ae0000, 0x0032cd32, // limegreen |
| 311 | 0xb12e2b80, 0x00faf0e6, // linen |
| 312 | 0xb4272ba9, 0x04000000, 0x00ff00ff, // magenta |
| 313 | 0xb4327bdc, 0x00800000, // maroon |
| 314 | 0xb4a44d5b, 0x06350b43, 0x492e2800, 0x0066cdaa, // mediumaquamarine |
| 315 | 0xb4a44d5b, 0x09952800, 0x000000cd, // mediumblue |
| 316 | 0xb4a44d5b, 0x3e434248, 0x00ba55d3, // mediumorchid |
| 317 | 0xb4a44d5b, 0x42b2830a, 0x009370db, // mediumpurple |
| 318 | 0xb4a44d5b, 0x4ca13c8b, 0x15c00000, 0x003cb371, // mediumseagreen |
| 319 | 0xb4a44d5b, 0x4d81a145, 0x32a50000, 0x007b68ee, // mediumslateblue |
| 320 | 0xb4a44d5b, 0x4e124b8f, 0x1e452b80, 0x0000fa9a, // mediumspringgreen |
| 321 | 0xb4a44d5b, 0x52b28d5f, 0x26650000, 0x0048d1cc, // mediumturquoise |
| 322 | 0xb4a44d5b, 0x592f6169, 0x48a40000, 0x00c71585, // mediumvioletred |
| 323 | 0xb524724f, 0x2282654a, 0x00191970, // midnightblue |
| 324 | 0xb52ea0e5, 0x142d0000, 0x00f5fffa, // mintcream |
| 325 | 0xb533a665, 0x3e650000, 0x00ffe4e1, // mistyrose |
| 326 | 0xb5e31867, 0x25c00000, 0x00ffe4b5, // moccasin |
| 327 | 0xb8360a9f, 0x5d09a140, 0x00ffdead, // navajowhite |
| 328 | 0xb836c800, 0x00000080, // navy |
| 329 | 0xbd846047, 0x14000000, 0x00fdf5e6, // oldlace |
| 330 | 0xbd89b140, 0x00808000, // olive |
| 331 | 0xbd89b149, 0x48220000, 0x006b8e23, // olivedrab |
| 332 | 0xbe4171ca, 0x00ffa500, // orange |
| 333 | 0xbe4171cb, 0x48a40000, 0x00ff4500, // orangered |
| 334 | 0xbe434248, 0x00da70d6, // orchid |
| 335 | 0xc02c29df, 0x3085749f, 0x10000000, 0x00eee8aa, // palegoldenrod |
| 336 | 0xc02c29e5, 0x14ae0000, 0x0098fb98, // palegreen |
| 337 | 0xc02c2d2b, 0x4a357a67, 0x14000000, 0x00afeeee, // paleturquoise |
| 338 | 0xc02c2d93, 0x3d85a48b, 0x10000000, 0x00db7093, // palevioletred |
| 339 | 0xc0300e43, 0x5d098000, 0x00ffefd5, // papayawhip |
| 340 | 0xc0a11a21, 0x54c60000, 0x00ffdab9, // peachpuff |
| 341 | 0xc0b2a800, 0x00cd853f, // peru |
| 342 | 0xc12e5800, 0x00ffc0cb, // pink |
| 343 | 0xc1956800, 0x00dda0dd, // plum |
| 344 | 0xc1f72165, 0x09952800, 0x00b0e0e6, // powderblue |
| 345 | 0xc2b2830a, 0x00800080, // purple |
| 346 | 0xc8a40000, 0x00ff0000, // red |
| 347 | 0xc9f3c8a5, 0x3eee0000, 0x00bc8f8f, // rosybrown |
| 348 | 0xc9f90b05, 0x32a50000, 0x004169e1, // royalblue |
| 349 | 0xcc24230b, 0x0a4fbb80, 0x008b4513, // saddlebrown |
| 350 | 0xcc2c6bdc, 0x00fa8072, // salmon |
| 351 | 0xcc2e2645, 0x49f77000, 0x00f4a460, // sandybrown |
| 352 | 0xcca13c8b, 0x15c00000, 0x002e8b57, // seagreen |
| 353 | 0xcca19a0b, 0x31800000, 0x00fff5ee, // seashell |
| 354 | 0xcd257382, 0x00a0522d, // sienna |
| 355 | 0xcd2cb164, 0x00c0c0c0, // silver |
| 356 | 0xcd79132b, 0x14000000, 0x0087ceeb, // skyblue |
| 357 | 0xcd81a145, 0x32a50000, 0x006a5acd, // slateblue |
| 358 | 0xcd81a14f, 0x48390000, 0x00708090, // slategray |
| 359 | 0xcdcfb800, 0x00fffafa, // snow |
| 360 | 0xce124b8f, 0x1e452b80, 0x0000ff7f, // springgreen |
| 361 | 0xce852b05, 0x32a50000, 0x004682b4, // steelblue |
| 362 | 0xd02e0000, 0x00d2b48c, // tan |
| 363 | 0xd0a16000, 0x00008080, // teal |
| 364 | 0xd1099d19, 0x14000000, 0x00d8bfd8, // thistle |
| 365 | 0xd1ed0d1e, 0x00ff6347, // tomato |
| 366 | 0xd2b28d5f, 0x26650000, 0x0040e0d0, // turquoise |
| 367 | 0xd92f6168, 0x00ee82ee, // violet |
| 368 | 0xdd050d00, 0x00f5deb3, // wheat |
| 369 | 0xdd09a140, 0x00ffffff, // white |
| 370 | 0xdd09a167, 0x35eb2800, 0x00f5f5f5, // whitesmoke |
| 371 | 0xe4ac63ee, 0x00ffff00, // yellow |
| 372 | 0xe4ac63ef, 0x1e452b80, 0x009acd32 // yellowgreen |
| 373 | }; // original = 2505 : replacement = 1616 |
| 374 | |
| 375 | |
| 376 | const char* SkParse::FindNamedColor(const char* name, size_t len, SkColor* color) { |
| 377 | const char* namePtr = name; |
| 378 | unsigned int sixMatches[4]; |
| 379 | unsigned int* sixMatchPtr = sixMatches; |
| 380 | bool first = true; |
| 381 | bool last = false; |
| 382 | char ch; |
| 383 | do { |
| 384 | unsigned int sixMatch = 0; |
| 385 | for (int chIndex = 0; chIndex < 6; chIndex++) { |
| 386 | sixMatch <<= 5; |
| 387 | ch = *namePtr | 0x20; |
| 388 | if (ch < 'a' || ch > 'z') |
| 389 | ch = 0; |
| 390 | else { |
| 391 | ch = ch - 'a' + 1; |
| 392 | namePtr++; |
| 393 | } |
| 394 | sixMatch |= ch ; // turn 'A' (0x41) into 'a' (0x61); |
| 395 | } |
| 396 | sixMatch <<= 1; |
| 397 | sixMatch |= 1; |
| 398 | if (first) { |
| 399 | sixMatch |= 0x80000000; |
| 400 | first = false; |
| 401 | } |
| 402 | ch = *namePtr | 0x20; |
| 403 | last = ch < 'a' || ch > 'z'; |
| 404 | if (last) |
| 405 | sixMatch &= ~1; |
| 406 | len -= 6; |
| 407 | *sixMatchPtr++ = sixMatch; |
| 408 | } while (last == false && len > 0); |
| 409 | const int colorNameSize = sizeof(gColorNames) / sizeof(unsigned int); |
| 410 | int lo = 0; |
| 411 | int hi = colorNameSize - 3; // back off to beginning of yellowgreen |
| 412 | while (lo <= hi) { |
| 413 | int mid = (hi + lo) >> 1; |
| 414 | while ((int) gColorNames[mid] >= 0) |
| 415 | --mid; |
| 416 | sixMatchPtr = sixMatches; |
| 417 | while (gColorNames[mid] == *sixMatchPtr) { |
| 418 | ++mid; |
| 419 | if ((*sixMatchPtr & 1) == 0) { // last |
| 420 | *color = gColorNames[mid] | 0xFF000000; |
| 421 | return namePtr; |
| 422 | } |
| 423 | ++sixMatchPtr; |
| 424 | } |
| 425 | int sixMask = *sixMatchPtr & ~0x80000000; |
| 426 | int midMask = gColorNames[mid] & ~0x80000000; |
| 427 | if (sixMask > midMask) { |
| 428 | lo = mid + 2; // skip color |
| 429 | while ((int) gColorNames[lo] >= 0) |
| 430 | ++lo; |
| 431 | } else if (hi == mid) |
| 432 | return NULL; |
| 433 | else |
| 434 | hi = mid; |
| 435 | } |
| 436 | return NULL; |
| 437 | } |
| 438 | |
| 439 | // !!! move to char utilities |
| 440 | //static int count_separators(const char* str, const char* sep) { |
| 441 | // char c; |
| 442 | // int separators = 0; |
| 443 | // while ((c = *str++) != '\0') { |
| 444 | // if (strchr(sep, c) == NULL) |
| 445 | // continue; |
| 446 | // do { |
| 447 | // if ((c = *str++) == '\0') |
| 448 | // goto goHome; |
| 449 | // } while (strchr(sep, c) != NULL); |
| 450 | // separators++; |
| 451 | // } |
| 452 | //goHome: |
| 453 | // return separators; |
| 454 | //} |
| 455 | |
| 456 | static inline unsigned nib2byte(unsigned n) |
| 457 | { |
| 458 | SkASSERT((n & ~0xF) == 0); |
| 459 | return (n << 4) | n; |
| 460 | } |
| 461 | |
| 462 | const char* SkParse::FindColor(const char* value, SkColor* colorPtr) { |
| 463 | unsigned int oldAlpha = SkColorGetA(*colorPtr); |
| 464 | if (value[0] == '#') { |
| 465 | uint32_t hex; |
| 466 | const char* end = SkParse::FindHex(value + 1, &hex); |
| 467 | // SkASSERT(end); |
| 468 | if (end == NULL) |
| 469 | return end; |
| 470 | size_t len = end - value - 1; |
| 471 | if (len == 3 || len == 4) { |
| 472 | unsigned a = len == 4 ? nib2byte(hex >> 12) : oldAlpha; |
| 473 | unsigned r = nib2byte((hex >> 8) & 0xF); |
| 474 | unsigned g = nib2byte((hex >> 4) & 0xF); |
| 475 | unsigned b = nib2byte(hex & 0xF); |
| 476 | *colorPtr = SkColorSetARGB(a, r, g, b); |
| 477 | return end; |
| 478 | } else if (len == 6 || len == 8) { |
| 479 | if (len == 6) |
| 480 | hex |= oldAlpha << 24; |
| 481 | *colorPtr = hex; |
| 482 | return end; |
| 483 | } else { |
| 484 | // SkASSERT(0); |
| 485 | return NULL; |
| 486 | } |
| 487 | // } else if (strchr(value, ',')) { |
| 488 | // SkScalar array[4]; |
| 489 | // int count = count_separators(value, ",") + 1; // !!! count commas, add 1 |
| 490 | // SkASSERT(count == 3 || count == 4); |
| 491 | // array[0] = SK_Scalar1 * 255; |
| 492 | // const char* end = SkParse::FindScalars(value, &array[4 - count], count); |
| 493 | // if (end == NULL) |
| 494 | // return NULL; |
| 495 | // !!! range check for errors? |
| 496 | // *colorPtr = SkColorSetARGB(SkScalarRound(array[0]), SkScalarRound(array[1]), |
| 497 | // SkScalarRound(array[2]), SkScalarRound(array[3])); |
| 498 | // return end; |
| 499 | } else |
| 500 | return FindNamedColor(value, strlen(value), colorPtr); |
| 501 | } |
| 502 | |
| 503 | #ifdef SK_DEBUG |
| 504 | void SkParse::TestColor() { |
| 505 | if (false) |
| 506 | CreateTable(); // regenerates data table in the output window |
| 507 | SkColor result; |
| 508 | int index; |
| 509 | for (index = 0; index < colorNamesSize; index++) { |
| 510 | result = SK_ColorBLACK; |
| 511 | SkNameRGB nameRGB = colorNames[index]; |
| 512 | SkASSERT(FindColor(nameRGB.name, &result) != NULL); |
| 513 | SkASSERT(result == (SkColor) (nameRGB.rgb | 0xFF000000)); |
| 514 | } |
| 515 | for (index = 0; index < colorNamesSize; index++) { |
| 516 | result = SK_ColorBLACK; |
| 517 | SkNameRGB nameRGB = colorNames[index]; |
| 518 | char bad[24]; |
| 519 | size_t len = strlen(nameRGB.name); |
| 520 | memcpy(bad, nameRGB.name, len); |
| 521 | bad[len - 1] -= 1; |
| 522 | SkASSERT(FindColor(bad, &result) == false); |
| 523 | bad[len - 1] += 2; |
| 524 | SkASSERT(FindColor(bad, &result) == false); |
| 525 | } |
| 526 | result = SK_ColorBLACK; |
| 527 | SkASSERT(FindColor("lightGrey", &result)); |
| 528 | SkASSERT(result == 0xffd3d3d3); |
| 529 | // SkASSERT(FindColor("12,34,56,78", &result)); |
| 530 | // SkASSERT(result == ((12 << 24) | (34 << 16) | (56 << 8) | (78 << 0))); |
| 531 | result = SK_ColorBLACK; |
| 532 | SkASSERT(FindColor("#ABCdef", &result)); |
| 533 | SkASSERT(result == 0XFFABCdef); |
| 534 | SkASSERT(FindColor("#12ABCdef", &result)); |
| 535 | SkASSERT(result == 0X12ABCdef); |
| 536 | result = SK_ColorBLACK; |
| 537 | SkASSERT(FindColor("#123", &result)); |
| 538 | SkASSERT(result == 0Xff112233); |
| 539 | SkASSERT(FindColor("#abcd", &result)); |
| 540 | SkASSERT(result == 0Xaabbccdd); |
| 541 | result = SK_ColorBLACK; |
| 542 | // SkASSERT(FindColor("71,162,253", &result)); |
| 543 | // SkASSERT(result == ((0xFF << 24) | (71 << 16) | (162 << 8) | (253 << 0))); |
| 544 | } |
| 545 | #endif |
| 546 | |