@@ -24,12 +24,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
24
24
25
25
#include < sstream>
26
26
#include < iomanip>
27
+ #include < map>
27
28
28
29
#include " ../sha1.h"
29
30
#include " ../base64.h"
30
31
#include " ../hex.h"
31
32
#include " ../porting.h"
32
33
34
+ static bool parseHexColorString (const std::string &value, video::SColor &color);
35
+ static bool parseNamedColorString (const std::string &value, video::SColor &color);
36
+
33
37
#ifdef __ANDROID__
34
38
const wchar_t * wide_chars =
35
39
L" !\" #$%&'()*+,-./0123456789:;<=>?@"
@@ -307,62 +311,269 @@ u64 read_seed(const char *str)
307
311
308
312
bool parseColorString (const std::string &value, video::SColor &color, bool quiet)
309
313
{
310
- const char *hexpattern = NULL ;
311
- video::SColor outcolor (255 , 255 , 255 , 255 );
312
-
313
- if (value[0 ] == ' #' ) {
314
- if (value.size () == 9 )
315
- hexpattern = " #RRGGBBAA" ;
316
- else if (value.size () == 7 )
317
- hexpattern = " #RRGGBB" ;
318
- else if (value.size () == 5 )
319
- hexpattern = " #RGBA" ;
320
- else if (value.size () == 4 )
321
- hexpattern = " #RGB" ;
322
- }
314
+ bool success;
323
315
324
- if (!hexpattern)
325
- goto fail;
316
+ if (value[0 ] == ' #' )
317
+ success = parseHexColorString (value, color);
318
+ else
319
+ success = parseNamedColorString (value, color);
326
320
327
- assert (strlen (hexpattern) == value.size ());
328
- for (size_t pos = 0 ; pos < value.size (); ++pos) {
329
- // '#' in the pattern means skip that character
330
- if (hexpattern[pos] == ' #' )
331
- continue ;
321
+ if (!success && !quiet)
322
+ errorstream << " Invalid color: \" " << value << " \" " << std::endl;
323
+
324
+ return success;
325
+ }
326
+
327
+ static bool parseHexColorString (const std::string &value, video::SColor &color)
328
+ {
329
+ unsigned char components[] = { 0x00 , 0x00 , 0x00 , 0xff }; // R,G,B,A
332
330
333
- // Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A'
334
- // Read one or two digits, depending on hexpattern
335
- unsigned char c1, c2;
336
- if (hexpattern[pos+1 ] == hexpattern[pos]) {
337
- // Two digits, e.g. hexpattern == "#RRGGBB"
338
- if (!hex_digit_decode (value[pos], c1) ||
339
- !hex_digit_decode (value[pos+1 ], c2))
340
- goto fail;
341
- ++pos;
331
+ if (value[0 ] != ' #' )
332
+ return false ;
333
+
334
+ size_t len = value.size ();
335
+ bool short_form;
336
+
337
+ if (len == 9 || len == 7 ) // #RRGGBBAA or #RRGGBB
338
+ short_form = false ;
339
+ else if (len == 5 || len == 4 ) // #RGBA or #RGB
340
+ short_form = true ;
341
+ else
342
+ return false ;
343
+
344
+ bool success = true ;
345
+
346
+ for (size_t pos = 1 , cc = 0 ; pos < len; pos++, cc++) {
347
+ assert (cc < sizeof components / sizeof components[0 ]);
348
+ if (short_form) {
349
+ unsigned char d;
350
+ if (!hex_digit_decode (value[pos], d)) {
351
+ success = false ;
352
+ break ;
353
+ }
354
+ components[cc] = (d & 0xf ) << 4 | (d & 0xf );
342
355
} else {
343
- // One digit, e.g. hexpattern == "#RGB"
344
- if (!hex_digit_decode (value[pos], c1))
345
- goto fail;
346
- c2 = c1;
356
+ unsigned char d1, d2;
357
+ if (!hex_digit_decode (value[pos], d1) ||
358
+ !hex_digit_decode (value[pos+1 ], d2)) {
359
+ success = false ;
360
+ break ;
361
+ }
362
+ components[cc] = (d1 & 0xf ) << 4 | (d2 & 0xf );
363
+ pos++; // skip the second digit -- it's already used
347
364
}
348
- u32 colorpart = ((c1 & 0x0f ) << 4 ) | (c2 & 0x0f );
349
-
350
- // Update outcolor with newly read color part
351
- if (hexpattern[pos] == ' R' )
352
- outcolor.setRed (colorpart);
353
- else if (hexpattern[pos] == ' G' )
354
- outcolor.setGreen (colorpart);
355
- else if (hexpattern[pos] == ' B' )
356
- outcolor.setBlue (colorpart);
357
- else if (hexpattern[pos] == ' A' )
358
- outcolor.setAlpha (colorpart);
359
365
}
360
366
361
- color = outcolor;
362
- return true ;
367
+ if (success) {
368
+ color.setRed (components[0 ]);
369
+ color.setGreen (components[1 ]);
370
+ color.setBlue (components[2 ]);
371
+ color.setAlpha (components[3 ]);
372
+ }
363
373
364
- fail:
365
- if (!quiet)
366
- errorstream << " Invalid color: \" " << value << " \" " << std::endl;
367
- return false ;
374
+ return success;
375
+ }
376
+
377
+ struct ColorContainer {
378
+ ColorContainer ();
379
+ std::map<const std::string, u32 > colors;
380
+ };
381
+
382
+ ColorContainer::ColorContainer ()
383
+ {
384
+ colors[" aliceblue" ] = 0xf0f8ff ;
385
+ colors[" antiquewhite" ] = 0xfaebd7 ;
386
+ colors[" aqua" ] = 0x00ffff ;
387
+ colors[" aquamarine" ] = 0x7fffd4 ;
388
+ colors[" azure" ] = 0xf0ffff ;
389
+ colors[" beige" ] = 0xf5f5dc ;
390
+ colors[" bisque" ] = 0xffe4c4 ;
391
+ colors[" black" ] = 00000000 ;
392
+ colors[" blanchedalmond" ] = 0xffebcd ;
393
+ colors[" blue" ] = 0x0000ff ;
394
+ colors[" blueviolet" ] = 0x8a2be2 ;
395
+ colors[" brown" ] = 0xa52a2a ;
396
+ colors[" burlywood" ] = 0xdeb887 ;
397
+ colors[" cadetblue" ] = 0x5f9ea0 ;
398
+ colors[" chartreuse" ] = 0x7fff00 ;
399
+ colors[" chocolate" ] = 0xd2691e ;
400
+ colors[" coral" ] = 0xff7f50 ;
401
+ colors[" cornflowerblue" ] = 0x6495ed ;
402
+ colors[" cornsilk" ] = 0xfff8dc ;
403
+ colors[" crimson" ] = 0xdc143c ;
404
+ colors[" cyan" ] = 0x00ffff ;
405
+ colors[" darkblue" ] = 0x00008b ;
406
+ colors[" darkcyan" ] = 0x008b8b ;
407
+ colors[" darkgoldenrod" ] = 0xb8860b ;
408
+ colors[" darkgray" ] = 0xa9a9a9 ;
409
+ colors[" darkgreen" ] = 0x006400 ;
410
+ colors[" darkkhaki" ] = 0xbdb76b ;
411
+ colors[" darkmagenta" ] = 0x8b008b ;
412
+ colors[" darkolivegreen" ] = 0x556b2f ;
413
+ colors[" darkorange" ] = 0xff8c00 ;
414
+ colors[" darkorchid" ] = 0x9932cc ;
415
+ colors[" darkred" ] = 0x8b0000 ;
416
+ colors[" darksalmon" ] = 0xe9967a ;
417
+ colors[" darkseagreen" ] = 0x8fbc8f ;
418
+ colors[" darkslateblue" ] = 0x483d8b ;
419
+ colors[" darkslategray" ] = 0x2f4f4f ;
420
+ colors[" darkturquoise" ] = 0x00ced1 ;
421
+ colors[" darkviolet" ] = 0x9400d3 ;
422
+ colors[" deeppink" ] = 0xff1493 ;
423
+ colors[" deepskyblue" ] = 0x00bfff ;
424
+ colors[" dimgray" ] = 0x696969 ;
425
+ colors[" dodgerblue" ] = 0x1e90ff ;
426
+ colors[" firebrick" ] = 0xb22222 ;
427
+ colors[" floralwhite" ] = 0xfffaf0 ;
428
+ colors[" forestgreen" ] = 0x228b22 ;
429
+ colors[" fuchsia" ] = 0xff00ff ;
430
+ colors[" gainsboro" ] = 0xdcdcdc ;
431
+ colors[" ghostwhite" ] = 0xf8f8ff ;
432
+ colors[" gold" ] = 0xffd700 ;
433
+ colors[" goldenrod" ] = 0xdaa520 ;
434
+ colors[" gray" ] = 0x808080 ;
435
+ colors[" green" ] = 0x008000 ;
436
+ colors[" greenyellow" ] = 0xadff2f ;
437
+ colors[" honeydew" ] = 0xf0fff0 ;
438
+ colors[" hotpink" ] = 0xff69b4 ;
439
+ colors[" indianred " ] = 0xcd5c5c ;
440
+ colors[" indigo " ] = 0x4b0082 ;
441
+ colors[" ivory" ] = 0xfffff0 ;
442
+ colors[" khaki" ] = 0xf0e68c ;
443
+ colors[" lavender" ] = 0xe6e6fa ;
444
+ colors[" lavenderblush" ] = 0xfff0f5 ;
445
+ colors[" lawngreen" ] = 0x7cfc00 ;
446
+ colors[" lemonchiffon" ] = 0xfffacd ;
447
+ colors[" lightblue" ] = 0xadd8e6 ;
448
+ colors[" lightcoral" ] = 0xf08080 ;
449
+ colors[" lightcyan" ] = 0xe0ffff ;
450
+ colors[" lightgoldenrodyellow" ] = 0xfafad2 ;
451
+ colors[" lightgray" ] = 0xd3d3d3 ;
452
+ colors[" lightgreen" ] = 0x90ee90 ;
453
+ colors[" lightpink" ] = 0xffb6c1 ;
454
+ colors[" lightsalmon" ] = 0xffa07a ;
455
+ colors[" lightseagreen" ] = 0x20b2aa ;
456
+ colors[" lightskyblue" ] = 0x87cefa ;
457
+ colors[" lightslategray" ] = 0x778899 ;
458
+ colors[" lightsteelblue" ] = 0xb0c4de ;
459
+ colors[" lightyellow" ] = 0xffffe0 ;
460
+ colors[" lime" ] = 0x00ff00 ;
461
+ colors[" limegreen" ] = 0x32cd32 ;
462
+ colors[" linen" ] = 0xfaf0e6 ;
463
+ colors[" magenta" ] = 0xff00ff ;
464
+ colors[" maroon" ] = 0x800000 ;
465
+ colors[" mediumaquamarine" ] = 0x66cdaa ;
466
+ colors[" mediumblue" ] = 0x0000cd ;
467
+ colors[" mediumorchid" ] = 0xba55d3 ;
468
+ colors[" mediumpurple" ] = 0x9370db ;
469
+ colors[" mediumseagreen" ] = 0x3cb371 ;
470
+ colors[" mediumslateblue" ] = 0x7b68ee ;
471
+ colors[" mediumspringgreen" ] = 0x00fa9a ;
472
+ colors[" mediumturquoise" ] = 0x48d1cc ;
473
+ colors[" mediumvioletred" ] = 0xc71585 ;
474
+ colors[" midnightblue" ] = 0x191970 ;
475
+ colors[" mintcream" ] = 0xf5fffa ;
476
+ colors[" mistyrose" ] = 0xffe4e1 ;
477
+ colors[" moccasin" ] = 0xffe4b5 ;
478
+ colors[" navajowhite" ] = 0xffdead ;
479
+ colors[" navy" ] = 0x000080 ;
480
+ colors[" oldlace" ] = 0xfdf5e6 ;
481
+ colors[" olive" ] = 0x808000 ;
482
+ colors[" olivedrab" ] = 0x6b8e23 ;
483
+ colors[" orange" ] = 0xffa500 ;
484
+ colors[" orangered" ] = 0xff4500 ;
485
+ colors[" orchid" ] = 0xda70d6 ;
486
+ colors[" palegoldenrod" ] = 0xeee8aa ;
487
+ colors[" palegreen" ] = 0x98fb98 ;
488
+ colors[" paleturquoise" ] = 0xafeeee ;
489
+ colors[" palevioletred" ] = 0xdb7093 ;
490
+ colors[" papayawhip" ] = 0xffefd5 ;
491
+ colors[" peachpuff" ] = 0xffdab9 ;
492
+ colors[" peru" ] = 0xcd853f ;
493
+ colors[" pink" ] = 0xffc0cb ;
494
+ colors[" plum" ] = 0xdda0dd ;
495
+ colors[" powderblue" ] = 0xb0e0e6 ;
496
+ colors[" purple" ] = 0x800080 ;
497
+ colors[" red" ] = 0xff0000 ;
498
+ colors[" rosybrown" ] = 0xbc8f8f ;
499
+ colors[" royalblue" ] = 0x4169e1 ;
500
+ colors[" saddlebrown" ] = 0x8b4513 ;
501
+ colors[" salmon" ] = 0xfa8072 ;
502
+ colors[" sandybrown" ] = 0xf4a460 ;
503
+ colors[" seagreen" ] = 0x2e8b57 ;
504
+ colors[" seashell" ] = 0xfff5ee ;
505
+ colors[" sienna" ] = 0xa0522d ;
506
+ colors[" silver" ] = 0xc0c0c0 ;
507
+ colors[" skyblue" ] = 0x87ceeb ;
508
+ colors[" slateblue" ] = 0x6a5acd ;
509
+ colors[" slategray" ] = 0x708090 ;
510
+ colors[" snow" ] = 0xfffafa ;
511
+ colors[" springgreen" ] = 0x00ff7f ;
512
+ colors[" steelblue" ] = 0x4682b4 ;
513
+ colors[" tan" ] = 0xd2b48c ;
514
+ colors[" teal" ] = 0x008080 ;
515
+ colors[" thistle" ] = 0xd8bfd8 ;
516
+ colors[" tomato" ] = 0xff6347 ;
517
+ colors[" turquoise" ] = 0x40e0d0 ;
518
+ colors[" violet" ] = 0xee82ee ;
519
+ colors[" wheat" ] = 0xf5deb3 ;
520
+ colors[" white" ] = 0xffffff ;
521
+ colors[" whitesmoke" ] = 0xf5f5f5 ;
522
+ colors[" yellow" ] = 0xffff00 ;
523
+ colors[" yellowgreen" ] = 0x9acd32 ;
524
+
525
+ }
526
+
527
+ static const ColorContainer named_colors;
528
+
529
+ static bool parseNamedColorString (const std::string &value, video::SColor &color)
530
+ {
531
+ std::string color_name;
532
+ std::string alpha_string;
533
+
534
+ /* If the string has a # in it, assume this is the start of a specified
535
+ * alpha value (if it isn't the string is invalid and the error will be
536
+ * caught later on, either because the color name won't be found or the
537
+ * alpha value will fail conversion)
538
+ */
539
+ size_t alpha_pos = value.find (' #' );
540
+ if (alpha_pos != std::string::npos) {
541
+ color_name = value.substr (0 , alpha_pos);
542
+ alpha_string = value.substr (alpha_pos + 1 );
543
+ } else {
544
+ color_name = value;
545
+ }
546
+
547
+ color_name = lowercase (value);
548
+
549
+ std::map<const std::string, unsigned >::const_iterator it;
550
+ it = named_colors.colors .find (color_name);
551
+ if (it == named_colors.colors .end ())
552
+ return false ;
553
+
554
+ u32 color_temp = it->second ;
555
+
556
+ /* An empty string for alpha is ok (none of the color table entries
557
+ * have an alpha value either). Color strings without an alpha specified
558
+ * are interpreted as fully opaque
559
+ *
560
+ * For named colors the supplied alpha string (representing a hex value)
561
+ * must be exactly two digits. For example: colorname#08
562
+ */
563
+ if (!alpha_string.empty ()) {
564
+ if (alpha_string.length () != 2 )
565
+ return false ;
566
+
567
+ unsigned char d1, d2;
568
+ if (!hex_digit_decode (alpha_string.at (0 ), d1)
569
+ || !hex_digit_decode (alpha_string.at (1 ), d2))
570
+ return false ;
571
+ color_temp |= ((d1 & 0xf ) << 4 | (d2 & 0xf )) << 24 ;
572
+ } else {
573
+ color_temp |= 0xff << 24 ; // Fully opaque
574
+ }
575
+
576
+ color = video::SColor (color_temp);
577
+
578
+ return true ;
368
579
}
0 commit comments