egra: cosmetix, added brief comments for most interesting widget methods
[iv.d.git] / sdpy / color.d
blob2c50729bfa047742daf814464d4865fa22a54c43
1 /*
2 * Pixel Graphics Library
3 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
4 * Understanding is not required. Only obedience.
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 3 of the License ONLY.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module iv.sdpy.color /*is aliced*/;
20 import iv.alice;
21 import iv.sdpy.compat;
24 // ////////////////////////////////////////////////////////////////////////// //
25 @gcc_inline ubyte clampToByte(T) (T n) @safe pure nothrow @nogc if (__traits(isIntegral, T)) {
26 //static assert(!__traits(isUnsigned, T), "clampToByte can't process unsigned types");
27 static if (__VERSION__ > 2067) pragma(inline, true);
28 static if (T.sizeof == 2 || T.sizeof == 4) {
29 static if (__traits(isUnsigned, T)) {
30 return cast(ubyte)(n&0xff|(255-((-cast(int)(n < 256))>>24)));
31 } else {
32 n &= -cast(int)(n >= 0);
33 return cast(ubyte)(n|((255-cast(int)n)>>31));
35 } else static if (T.sizeof == 1) {
36 static assert(__traits(isUnsigned, T), "clampToByte: signed byte? no, really?");
37 return cast(ubyte)n;
38 } else {
39 static assert(false, "clampToByte: integer too big");
43 static assert(clampToByte(666) == 255);
44 static assert(clampToByte(-666) == 0);
45 static assert(clampToByte(250) == 250);
46 static assert(clampToByte(-250) == 0);
47 static assert(clampToByte(cast(uint)250) == 250);
48 static assert(clampToByte(cast(uint)1000) == 255);
49 static assert(clampToByte(cast(uint)0xfffffff0) == 255);
53 private @gcc_inline T absInternal(T) (T a) {
54 static if (__VERSION__ > 2067) pragma(inline, true);
55 return (a < 0 ? -a : a);
58 private @gcc_inline TT minInternal(TT, T...) (T args) if (T.length > 0) {
59 static if (__VERSION__ > 2067) pragma(inline, true);
60 TT res = cast(TT)args[0];
61 foreach (immutable n; args[1..$]) if (n < res) res = cast(TT)n;
62 return res;
65 private @gcc_inline TT maxInternal(TT, T...) (T args) if (T.length > 0) {
66 static if (__VERSION__ > 2067) pragma(inline, true);
67 TT res = cast(TT)args[0];
68 foreach (immutable n; args[1..$]) if (n > res) res = cast(TT)n;
69 return res;
73 // ////////////////////////////////////////////////////////////////////////// //
74 align(1) struct VColor {
75 align(1):
76 union {
77 uint u32;
78 /// struct to ease color components extraction/replacing
79 version(LittleEndian) {
80 align(1) struct {
81 align(1):
82 ubyte b, g, r, a;
84 } else version(BigEndian) {
85 align(1) struct {
86 align(1):
87 ubyte a, r, g, b;
89 } else {
90 static assert(0, "WTF?!");
93 // consts
94 enum {
95 AShift = 24,
96 RShift = 16,
97 GShift = 8,
98 BShift = 0,
100 enum : uint {
101 AMask = cast(uint)(0xffu<<AShift),
102 RMask = cast(uint)(0xffu<<RShift),
103 GMask = cast(uint)(0xffu<<GShift),
104 BMask = cast(uint)(0xffu<<BShift),
106 static if (__VERSION__ >= 2067) {
107 enum : VColor {
108 transparent = VColor(AMask), /// completely transparent pixel color
109 black = VColor(0), /// completely black pixel color
110 white = VColor(RMask|GMask|BMask), /// completely white pixel color
111 red = VColor(RMask), /// completely red pixel color
112 green = VColor(GMask), /// completely green pixel color
113 blue = VColor(BMask), /// completely blue pixel color
115 } else {
116 // alas, old DMDFE sux
117 static @property pure nothrow @safe @nogc {
118 @gcc_inline VColor transparent () { return VColor(AMask); }
119 @gcc_inline VColor black () { return VColor(0); }
120 @gcc_inline VColor white () { return VColor(RMask|GMask|BMask); }
121 @gcc_inline VColor red () { return VColor(RMask); }
122 @gcc_inline VColor green () { return VColor(GMask); }
123 @gcc_inline VColor blue () { return VColor(BMask); }
127 // this mixin can be used to alphablend two `uint` colors
128 // `colu32name` is variable that holds color to blend,
129 // `destu32name` is variable that holds "current" color (from surface, for example)
130 // alpha value of `destu32name` doesn't matter
131 // alpha value of `colu32name` means: 0 for replace color, 255 for keep `destu32name`
132 enum ColorBlendMixinStr(string colu32name, string destu32name) = "{
133 static if (VColor.AShift == 24) {
134 immutable uint a_tmp_ = (256-(("~colu32name~")>>24))&(-(1-(((("~colu32name~")>>24)+1)>>8))); // to not loose bits, but 255 should become 0
135 immutable uint dc_tmp_ = ("~destu32name~")&0xffffff;
136 immutable uint srb_tmp_ = (("~colu32name~")&0xff00ff);
137 immutable uint sg_tmp_ = (("~colu32name~")&0x00ff00);
138 } else static if (VColor.AShift == 0) {
139 immutable uint a_tmp_ = (256-(("~colu32name~")&0xff))&(-(1-(((("~colu32name~")&0xff)+1)>>8))); // to not loose bits, but 255 should become 0
140 immutable uint dc_tmp_ = (("~destu32name~")>>8)&0xffffff;
141 immutable uint srb_tmp_ = ((("~colu32name~")>>8)&0xff00ff);
142 immutable uint sg_tmp_ = ((("~colu32name~")>>8)&0x00ff00);
143 } else {
144 static assert(0, `unsupported VColor.AMask value (only 0 and 24 are allowed)`);
146 immutable uint drb_tmp_ = (dc_tmp_&0xff00ff);
147 immutable uint dg_tmp_ = (dc_tmp_&0x00ff00);
148 immutable uint orb_tmp_ = (drb_tmp_+(((srb_tmp_-drb_tmp_)*a_tmp_+0x800080)>>8))&0xff00ff;
149 immutable uint og_tmp_ = (dg_tmp_+(((sg_tmp_-dg_tmp_)*a_tmp_+0x008000)>>8))&0x00ff00;
150 static if (VColor.AShift == 24) {
151 ("~destu32name~") = (orb_tmp_|og_tmp_)&~VColor.AMask;
152 } else {
153 // move colors to highest bits
154 ("~destu32name~") = (orb_tmp_|og_tmp_)<<8;
158 // methods
159 string toString () const nothrow @safe {
160 static usize b2s() (char[] dest, ubyte b) {
161 if (b >= 100) {
162 dest[0] = cast(char)(b/100%10+'0');
163 dest[1] = cast(char)(b/10%10+'0');
164 dest[2] = cast(char)(b%10+'0');
165 return 3;
166 } else if (b >= 10) {
167 dest[0] = cast(char)(b/10%10+'0');
168 dest[1] = cast(char)(b%10+'0');
169 return 2;
170 } else {
171 dest[0] = cast(char)(b%10+'0');
172 return 1;
175 char[32] buf;
176 usize pos = 0;
177 switch (u32) {
178 case AMask: return "transparent";
179 case 0: return "black";
180 case RMask: return "red";
181 case GMask: return "green";
182 case BMask: return "blue";
183 case RMask|GMask|BMask: return "white";
184 default:
186 buf[pos++] = 'r';
187 buf[pos++] = 'g';
188 buf[pos++] = 'b';
189 if (a != 0) buf[pos++] = 'a';
190 buf[pos++] = '(';
191 pos += b2s(buf[pos..$], r);
192 buf[pos++] = ',';
193 pos += b2s(buf[pos..$], g);
194 buf[pos++] = ',';
195 pos += b2s(buf[pos..$], b);
196 if (a != 0) {
197 buf[pos++] = ',';
198 pos += b2s(buf[pos..$], a);
200 buf[pos++] = ')';
201 return buf[0..pos].idup;
203 @safe nothrow @nogc:
204 this (uint v) pure { u32 = v; }
205 this (const(char)[] s) { u32 = parseColorName(s).u32; }
206 this (string s) { u32 = parseColorName(s).u32; }
208 // `to!` support
209 //static auto opCast(T) (const(char)[] s) if (is(T == VColor)) { return parseColorName(s); }
210 //auto opCast(T) (const(char)[] s) if (is(T == uint)) { return u32; }
212 /// Is color completely transparent?
213 @gcc_inline @property bool isTransparent() () const pure {
214 static if (__VERSION__ > 2067) pragma(inline, true);
215 return (a == 255);
218 /// Is color completely opaque?
219 @gcc_inline @property bool isOpaque() () const pure {
220 static if (__VERSION__ > 2067) pragma(inline, true);
221 return (a == 0);
224 @gcc_inline @property VColor setAlpha(T) (T a) const pure if (__traits(isIntegral, T)) {
225 static if (__VERSION__ > 2067) pragma(inline, true);
226 return VColor((u32&~AMask)|(clampToByte(a)<<AShift));
230 * Build rgba color from components.
232 * Params:
233 * r = red component [0..255]
234 * g = green component [0..255]
235 * b = blue component [0..255]
236 * a = transparency [0..255] (0: completely opaque; 255: completely transparent)
238 * Returns:
239 * VColor
241 @gcc_inline static VColor rgba(TR, TG, TB, TA) (TR r, TG g, TB b, TA a) pure
242 if (__traits(isIntegral, TR) && __traits(isIntegral, TG) && __traits(isIntegral, TB) && __traits(isIntegral, TA))
244 static if (__VERSION__ > 2067) pragma(inline, true);
245 return VColor(
246 (clampToByte(a)<<AShift)|
247 (clampToByte(r)<<RShift)|
248 (clampToByte(g)<<GShift)|
249 (clampToByte(b)<<BShift));
252 * Build opaque non-transparent rgb color from components.
254 * Params:
255 * r = red component [0..255]
256 * g = green component [0..255]
257 * b = blue component [0..255]
259 * Returns:
260 * VColor
262 @gcc_inline static VColor rgb(TR, TG, TB) (TR r, TG g, TB b) pure
263 if (__traits(isIntegral, TR) && __traits(isIntegral, TG) && __traits(isIntegral, TB))
265 static if (__VERSION__ > 2067) pragma(inline, true);
266 return VColor(
267 (clampToByte(r)<<RShift)|
268 (clampToByte(g)<<GShift)|
269 (clampToByte(b)<<BShift));
272 // HSL functions were taken from arsd.color, written by Adam D. Ruppe, modified by Ketmar
273 // Converts hsl to rgb
274 static VColor hsl(T) (T h, T s, T l, T a=0) pure if (__traits(isFloating, T)) {
275 h %= 360;
276 immutable real C = (1-absInternal(2*l-1))*s;
277 immutable real hPrime = h/60;
278 immutable real X = C*(1-absInternal(hPrime%2-1));
279 real r, g, b;
280 if (h is real.nan) {
281 r = g = b = 0;
282 } else if (hPrime >= 0 && hPrime < 1) {
283 r = C;
284 g = X;
285 b = 0;
286 } else if (hPrime >= 1 && hPrime < 2) {
287 r = X;
288 g = C;
289 b = 0;
290 } else if (hPrime >= 2 && hPrime < 3) {
291 r = 0;
292 g = C;
293 b = X;
294 } else if (hPrime >= 3 && hPrime < 4) {
295 r = 0;
296 g = X;
297 b = C;
298 } else if (hPrime >= 4 && hPrime < 5) {
299 r = X;
300 g = 0;
301 b = C;
302 } else if (hPrime >= 5 && hPrime < 6) {
303 r = C;
304 g = 0;
305 b = X;
308 immutable real m = l-C/2;
309 r += m;
310 g += m;
311 b += m;
313 return VColor.rgba(cast(ubyte)(r*255), cast(ubyte)(g*255), cast(ubyte)(b*255), cast(ubyte)(a));
317 // Converts an RGB color into an HSL triplet.
318 // useWeightedLightness will try to get a better value for luminosity for the human eye,
319 // which is more sensitive to green than red and more to red than blue.
320 // If it is false, it just does average of the rgb.
321 void toHsl(T=real) (out T Ho, out T So, out T Lo, bool useWeightedLightness=false) pure if (__traits(isFloating, T)) {
322 // use bitops for CTFE
323 immutable real r1 = cast(real)((this.u32>>RShift)&0xff)/255;
324 immutable real g1 = cast(real)((this.u32>>GShift)&0xff)/255;
325 immutable real b1 = cast(real)((this.u32>>BShift)&0xff)/255;
327 immutable real maxColor = maxInternal!real(r1, g1, b1);
328 immutable real minColor = minInternal!real(r1, g1, b1);
330 real L = (maxColor+minColor)/2;
331 if (useWeightedLightness) {
332 // the colors don't affect the eye equally
333 // this is a little more accurate than plain HSL numbers
334 L = 0.2126*r1+0.7152*g1+0.0722*b1;
336 real S = 0;
337 real H = 0;
338 if (maxColor != minColor) {
339 if (L < 0.5) {
340 S = (maxColor-minColor)/(maxColor+minColor);
341 } else {
342 S = (maxColor-minColor)/(2.0-maxColor-minColor);
344 if (r1 == maxColor) {
345 H = (g1-b1)/(maxColor-minColor);
346 } else if(g1 == maxColor) {
347 H = 2.0+(b1-r1)/(maxColor-minColor);
348 } else {
349 H = 4.0+(r1-g1)/(maxColor-minColor);
353 H = H*60;
354 if (H < 0) H += 360;
356 //return [H, S, L];
357 Ho = cast(T)H;
358 So = cast(T)S;
359 Lo = cast(T)L;
362 VColor lighten(T) (T percentage) pure if (__traits(isFloating, T)) {
363 real h, s, l;
364 toHsl(h, s, l);
365 l *= (1+percentage);
366 if (l > 1) l = 1;
367 else if (l < 0) l = 0; //k8:???
368 return hsl(h, s, l, cast(real)this.a);
371 VColor darken(T) (T percentage) pure if (__traits(isFloating, T)) {
372 real h, s, l;
373 toHsl(h, s, l);
374 l *= (1-percentage);
375 if (l > 1) l = 1;
376 else if (l < 0) l = 0; //k8:???
377 return hsl(h, s, l, cast(real)this.a);
380 // for light colors, call darken. for dark colors, call lighten.
381 // The goal: get toward center grey.
382 VColor moderate(T) (T percentage) pure if (__traits(isFloating, T)) {
383 real h, s, l;
384 toHsl(h, s, l);
385 if (l > 0.5) l *= (1-percentage);
386 else if (l <= 0.01) l = percentage; // if we are given black, moderating it means getting *something* out
387 else l *= (1+percentage);
388 if (l > 1) l = 1;
389 else if (l < 0) l = 0; //k8:???
390 return hsl(h, s, l, cast(real)this.a);
393 /// the opposite of moderate. Make darks darker and lights lighter
394 VColor extremify(T) (T percentage) pure if (__traits(isFloating, T)) {
395 real h, s, l;
396 toHsl(h, s, l);
397 if (l < 0.5) l *= (1-percentage); else l *= (1+percentage);
398 if (l > 1) l = 1;
399 else if (l < 0) l = 0; //k8:???
400 return hsl(h, s, l, cast(real)this.a);
403 /// Move around the lightness wheel, trying not to break on moderate things
404 VColor oppositeLightness() () pure {
405 real h, s, l;
406 toHsl(h, s, l);
407 auto original = l;
408 if (original > 0.4 && original < 0.6) {
409 l = 0.8-original; // so it isn't quite the same
410 } else {
411 l = 1-original;
413 return hsl(h, s, l, cast(real)this.a);
416 /// Try to determine a text color - either white or black - based on the input
417 VColor textColor() () pure {
418 real h, s, l;
419 toHsl(h, s, l, true); // give green a bonus for contrast
420 return (l > 0.71 ? VColor.black : VColor.white);
423 static assert(VColor.sizeof == uint.sizeof);
425 static assert(VColor.black.textColor == VColor.white);
426 static assert(VColor.hsl(1.0, 1.0, 1.0) == VColor.white);
427 static assert(VColor.hsl(1.0, 1.0, 0.0) == VColor.black);
428 //pragma(msg, VColor.hsl(1.0, 1.0, 0.0));
432 // ////////////////////////////////////////////////////////////////////////// //
433 private int digit (char ch, int base) pure @safe nothrow @nogc {
434 static if (__VERSION__ > 2067) pragma(inline, true);
435 if (ch >= '0' && ch <= '9') ch -= '0';
436 else if (ch >= 'A' && ch <= 'Z') ch -= 'A'-10;
437 else if (ch >= 'a' && ch <= 'z') ch -= 'a'-10;
438 else ch = '\xff';
439 return (ch < base ? ch : -1);
443 // ////////////////////////////////////////////////////////////////////////// //
444 private __gshared VColor[string] knownColors;
447 private void loadColors (string srctext) {
448 ubyte[3] rgb;
449 usize pos;
450 mainloop: while (srctext.length) {
451 pos = 0;
452 while (pos < srctext.length && srctext[pos] != '\n') ++pos;
453 if (pos < srctext.length) ++pos;
454 auto ln = srctext[0..pos];
455 srctext = srctext[pos..$];
456 while (ln.length && ln[$-1] <= ' ') ln = ln[0..$-1];
457 pos = 0;
458 while (pos < ln.length && ln[pos] != '#') ++pos;
459 ln = ln[0..pos];
460 //{ import std.stdio; writeln("*[", ln, "]"); }
461 foreach (immutable idx; 0..3) {
462 while (ln.length && ln[0] <= ' ') ln = ln[1..$];
463 if (ln.length == 0 || ln[0] < '0' || ln[0] > '9') continue mainloop;
464 uint num = 0;
465 while (ln.length && ln[0] >= '0' && ln[0] <= '9') {
466 num = num*10+(ln[0]-'0');
467 if (num > 255) continue mainloop;
468 ln = ln[1..$];
470 rgb[idx] = cast(ubyte)num;
471 //{ import std.stdio; writeln("**[", ln, "]"); }
473 while (ln.length && ln[0] <= ' ') ln = ln[1..$];
474 if (ln.length == 0) continue mainloop;
475 //{ import std.stdio; writeln("[", ln, "] = (", rgb[0], ", ", rgb[1], ", ", rgb[2], ")"); }
476 knownColors[ln.idup] = VColor.rgb(rgb[0], rgb[1], rgb[2]);
481 shared static this () {
483 try {
484 loadColors("/usr/share/X11/rgb.txt");
485 } catch (Exception) {
486 knownColors["red"] = VColor.rgb(255, 0, 0);
487 knownColors["green"] = VColor.rgb(0, 255, 0);
488 knownColors["blue"] = VColor.rgb(0, 0, 255);
489 knownColors["black"] = VColor.rgb(0, 0, 0);
490 knownColors["white"] = VColor.rgb(255, 255, 255);
491 knownColors["silver"] = VColor.rgb(192, 192, 192);
494 loadColors(colorList_);
498 // ////////////////////////////////////////////////////////////////////////// //
499 public VColor parseColorName (const(char)[] cname, bool* ok=null) @trusted nothrow @nogc {
500 bool parseNum (out ubyte v) @safe nothrow @nogc {
501 int base = 10;
502 while (cname.length && (cname[0] <= ' ' || cname[0] == '_')) cname = cname[1..$];
503 if (cname.length == 0 || cname[0] < '0' || cname[0] > '9') return false;
504 if (cname.length > 2 && cname[0] == '0' && (cname[1] == 'x' || cname[1] == 'X')) {
505 // hex number
506 cname = cname[2..$];
507 base = 16;
508 } else if (cname.length > 2 && cname[0] == '0' && (cname[1] == 'o' || cname[1] == 'O')) {
509 // octal number
510 cname = cname[2..$];
511 base = 8;
512 } else if (cname.length > 2 && cname[0] == '0' && (cname[1] == 'b' || cname[1] == 'B')) {
513 // binary number
514 cname = cname[2..$];
515 base = 2;
516 } else if (cname.length > 2 && cname[0] == '0' && (cname[1] == 'd' || cname[1] == 'D')) {
517 // decimal number
518 cname = cname[2..$];
520 if (cname.length == 0 || digit(cname[0], base) < 0) return false;
521 int n = 0;
522 while (cname.length) {
523 int d = digit(cname[0], base);
524 if (d < 0) {
525 if (cname[0] != '_') {
526 while (cname.length && cname[0] <= ' ') cname = cname[1..$];
527 break;
529 } else {
530 n = n*base+d;
531 if (n > 255) return false;
533 cname = cname[1..$];
535 v = cast(ubyte)n;
536 return true;
539 if (ok !is null) *ok = false;
540 while (cname.length && cname[0] <= ' ') cname = cname[1..$];
541 while (cname.length && cname[$-1] <= ' ') cname = cname[0..$-1];
542 if (cname.length == 0) return VColor.transparent;
543 if (cname[0] == '#') {
544 cname = cname[1..$];
545 ubyte[6] hd;
546 uint hdpos = 0;
547 // collect hex digits
548 foreach (char ch; cname) {
549 if (ch <= ' ' || ch == '_') continue;
550 if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) {
551 if (hdpos >= hd.length) return VColor.transparent;
552 if (ch >= 'a') ch -= 'a'-10;
553 else if (ch >= 'A') ch -= 'A'-10;
554 else ch -= '0';
555 hd[hdpos++] = cast(ubyte)ch;
556 } else if (ch > ' ' && ch != '_') {
557 return VColor.transparent;
560 if (hdpos == 3) {
561 if (ok !is null) *ok = true;
562 //return VColor.rgb(hd[0]*16+hd[0], hd[1]*16+hd[1], hd[2]*16+hd[2]);
563 return VColor.rgb(hd[0]*17, hd[1]*17, hd[2]*17);
564 } else if (hdpos == 6) {
565 if (ok !is null) *ok = true;
566 return VColor.rgb(hd[0]*16+hd[1], hd[2]*16+hd[3], hd[4]*16+hd[5]);
567 } else {
568 return VColor.transparent;
571 if (cname.length > 3 && cname[0..3] == "rgb") {
572 cname = cname[3..$];
573 if (cname[0] == 'a') cname = cname[1..$];
574 while (cname.length && cname[0] <= ' ') cname = cname[1..$];
575 if (cname.length < 2 || cname[0] != '(' || cname[$-1] != ')') return VColor.transparent;
576 cname = cname[1..$];
577 ubyte[4] rgba;
578 uint cidx = 0;
579 for (;;) {
580 while (cname.length && (cname[0] <= ' ' || cname[0] == '_')) cname = cname[1..$];
581 if (cidx >= rgba.length) return VColor.transparent;
582 if (cname[0] != ',') {
583 if (!parseNum(rgba[cidx])) return VColor.transparent;
585 ++cidx;
586 if (cname[0] == ')') break;
587 if (cname[0] != ',') return VColor.transparent;
588 cname = cname[1..$];
590 if (cidx < 3) return VColor.transparent;
591 if (ok !is null) *ok = true;
592 return VColor.rgba(rgba[0], rgba[1], rgba[2], rgba[3]);
594 // try predefined colors
596 char[64] nbuf;
597 usize pos = 0;
598 foreach (char ch; cname) {
599 if (ch <= ' ') continue;
600 if (ch >= 'A' && ch <= 'Z') ch += 32; // poor man's `toLower()`
601 if (pos >= nbuf.length) return VColor.transparent;
602 nbuf[pos++] = ch;
604 if (pos == 0) return VColor.transparent;
605 if (auto cl = nbuf[0..pos] in knownColors) {
606 if (ok !is null) *ok = true;
607 return *cl;
609 if (nbuf[0..pos] == "transparent") {
610 if (ok !is null) *ok = true;
611 return VColor.transparent;
614 return VColor.transparent;
617 unittest {
618 import iv.writer;
619 version(test_color_parser) {
620 void dumpColor (string cname) {
621 bool ok;
622 auto clr = parseColorName(cname, &ok);
623 writefln!"0x%08x; ok=%s; [%s]"(clr, ok, cname);
626 dumpColor("#f00");
627 dumpColor("#e00");
628 dumpColor("#00_ff_00");
629 dumpColor("#00fe0_0");
630 dumpColor("rgb(1, 2, 3 )");
631 dumpColor("rgba(1, 2, 3 )");
632 dumpColor("rgba(1, 2, 3 , 4)");
633 dumpColor("rgba(1,,, 4)");
634 dumpColor("green");
635 dumpColor("gray");
636 dumpColor("orange");
637 dumpColor("dark orange");
638 dumpColor("olive");
639 dumpColor("yellow");
640 dumpColor("gold");
645 // ////////////////////////////////////////////////////////////////////////// //
646 private immutable string colorList_ = `
647 255 250 250 snow
648 248 248 255 ghostwhite
649 245 245 245 whitesmoke
650 220 220 220 gainsboro
651 255 250 240 floralwhite
652 253 245 230 oldlace
653 250 240 230 linen
654 250 235 215 antiquewhite
655 255 239 213 papayawhip
656 255 235 205 blanchedalmond
657 255 228 196 bisque
658 255 218 185 peachpuff
659 255 222 173 navajowhite
660 255 228 181 moccasin
661 255 248 220 cornsilk
662 255 255 240 ivory
663 255 250 205 lemonchiffon
664 255 245 238 seashell
665 240 255 240 honeydew
666 245 255 250 mintcream
667 240 255 255 azure
668 240 248 255 aliceblue
669 230 230 250 lavender
670 255 240 245 lavenderblush
671 255 228 225 mistyrose
672 255 255 255 white
673 0 0 0 black
674 47 79 79 darkslategray
675 47 79 79 darkslategrey
676 105 105 105 dimgray
677 105 105 105 dimgrey
678 112 128 144 slategray
679 112 128 144 slategrey
680 119 136 153 lightslategray
681 119 136 153 lightslategrey
682 190 190 190 gray
683 190 190 190 grey
684 190 190 190 x11gray
685 190 190 190 x11grey
686 128 128 128 webgray
687 128 128 128 webgrey
688 211 211 211 lightgrey
689 211 211 211 lightgray
690 25 25 112 midnightblue
691 0 0 128 navy
692 0 0 128 navyblue
693 100 149 237 cornflowerblue
694 72 61 139 darkslateblue
695 106 90 205 slateblue
696 123 104 238 mediumslateblue
697 132 112 255 lightslateblue
698 0 0 205 mediumblue
699 65 105 225 royalblue
700 0 0 255 blue
701 30 144 255 dodgerblue
702 0 191 255 deepskyblue
703 135 206 235 skyblue
704 135 206 250 lightskyblue
705 70 130 180 steelblue
706 176 196 222 lightsteelblue
707 173 216 230 lightblue
708 176 224 230 powderblue
709 175 238 238 paleturquoise
710 0 206 209 darkturquoise
711 72 209 204 mediumturquoise
712 64 224 208 turquoise
713 0 255 255 cyan
714 0 255 255 aqua
715 224 255 255 lightcyan
716 95 158 160 cadetblue
717 102 205 170 mediumaquamarine
718 127 255 212 aquamarine
719 0 100 0 darkgreen
720 85 107 47 darkolivegreen
721 143 188 143 darkseagreen
722 46 139 87 seagreen
723 60 179 113 mediumseagreen
724 32 178 170 lightseagreen
725 152 251 152 palegreen
726 0 255 127 springgreen
727 124 252 0 lawngreen
728 0 255 0 green
729 0 255 0 lime
730 0 255 0 x11green
731 0 128 0 webgreen
732 127 255 0 chartreuse
733 0 250 154 mediumspringgreen
734 173 255 47 greenyellow
735 50 205 50 limegreen
736 154 205 50 yellowgreen
737 34 139 34 forestgreen
738 107 142 35 olivedrab
739 189 183 107 darkkhaki
740 240 230 140 khaki
741 238 232 170 palegoldenrod
742 250 250 210 lightgoldenrodyellow
743 255 255 224 lightyellow
744 255 255 0 yellow
745 255 215 0 gold
746 238 221 130 lightgoldenrod
747 218 165 32 goldenrod
748 184 134 11 darkgoldenrod
749 188 143 143 rosybrown
750 205 92 92 indianred
751 139 69 19 saddlebrown
752 160 82 45 sienna
753 205 133 63 peru
754 222 184 135 burlywood
755 245 245 220 beige
756 245 222 179 wheat
757 244 164 96 sandybrown
758 210 180 140 tan
759 210 105 30 chocolate
760 178 34 34 firebrick
761 165 42 42 brown
762 233 150 122 darksalmon
763 250 128 114 salmon
764 255 160 122 lightsalmon
765 255 165 0 orange
766 255 140 0 darkorange
767 255 127 80 coral
768 240 128 128 lightcoral
769 255 99 71 tomato
770 255 69 0 orangered
771 255 0 0 red
772 255 105 180 hotpink
773 255 20 147 deeppink
774 255 192 203 pink
775 255 182 193 lightpink
776 219 112 147 palevioletred
777 176 48 96 maroon
778 176 48 96 x11maroon
779 128 0 0 webmaroon
780 199 21 133 mediumvioletred
781 208 32 144 violetred
782 255 0 255 magenta
783 255 0 255 fuchsia
784 238 130 238 violet
785 221 160 221 plum
786 218 112 214 orchid
787 186 85 211 mediumorchid
788 153 50 204 darkorchid
789 148 0 211 darkviolet
790 138 43 226 blueviolet
791 160 32 240 purple
792 160 32 240 x11purple
793 128 0 128 webpurple
794 147 112 219 mediumpurple
795 216 191 216 thistle
796 255 250 250 snow1
797 238 233 233 snow2
798 205 201 201 snow3
799 139 137 137 snow4
800 255 245 238 seashell1
801 238 229 222 seashell2
802 205 197 191 seashell3
803 139 134 130 seashell4
804 255 239 219 antiquewhite1
805 238 223 204 antiquewhite2
806 205 192 176 antiquewhite3
807 139 131 120 antiquewhite4
808 255 228 196 bisque1
809 238 213 183 bisque2
810 205 183 158 bisque3
811 139 125 107 bisque4
812 255 218 185 peachpuff1
813 238 203 173 peachpuff2
814 205 175 149 peachpuff3
815 139 119 101 peachpuff4
816 255 222 173 navajowhite1
817 238 207 161 navajowhite2
818 205 179 139 navajowhite3
819 139 121 94 navajowhite4
820 255 250 205 lemonchiffon1
821 238 233 191 lemonchiffon2
822 205 201 165 lemonchiffon3
823 139 137 112 lemonchiffon4
824 255 248 220 cornsilk1
825 238 232 205 cornsilk2
826 205 200 177 cornsilk3
827 139 136 120 cornsilk4
828 255 255 240 ivory1
829 238 238 224 ivory2
830 205 205 193 ivory3
831 139 139 131 ivory4
832 240 255 240 honeydew1
833 224 238 224 honeydew2
834 193 205 193 honeydew3
835 131 139 131 honeydew4
836 255 240 245 lavenderblush1
837 238 224 229 lavenderblush2
838 205 193 197 lavenderblush3
839 139 131 134 lavenderblush4
840 255 228 225 mistyrose1
841 238 213 210 mistyrose2
842 205 183 181 mistyrose3
843 139 125 123 mistyrose4
844 240 255 255 azure1
845 224 238 238 azure2
846 193 205 205 azure3
847 131 139 139 azure4
848 131 111 255 slateblue1
849 122 103 238 slateblue2
850 105 89 205 slateblue3
851 71 60 139 slateblue4
852 72 118 255 royalblue1
853 67 110 238 royalblue2
854 58 95 205 royalblue3
855 39 64 139 royalblue4
856 0 0 255 blue1
857 0 0 238 blue2
858 0 0 205 blue3
859 0 0 139 blue4
860 30 144 255 dodgerblue1
861 28 134 238 dodgerblue2
862 24 116 205 dodgerblue3
863 16 78 139 dodgerblue4
864 99 184 255 steelblue1
865 92 172 238 steelblue2
866 79 148 205 steelblue3
867 54 100 139 steelblue4
868 0 191 255 deepskyblue1
869 0 178 238 deepskyblue2
870 0 154 205 deepskyblue3
871 0 104 139 deepskyblue4
872 135 206 255 skyblue1
873 126 192 238 skyblue2
874 108 166 205 skyblue3
875 74 112 139 skyblue4
876 176 226 255 lightskyblue1
877 164 211 238 lightskyblue2
878 141 182 205 lightskyblue3
879 96 123 139 lightskyblue4
880 198 226 255 slategray1
881 185 211 238 slategray2
882 159 182 205 slategray3
883 108 123 139 slategray4
884 202 225 255 lightsteelblue1
885 188 210 238 lightsteelblue2
886 162 181 205 lightsteelblue3
887 110 123 139 lightsteelblue4
888 191 239 255 lightblue1
889 178 223 238 lightblue2
890 154 192 205 lightblue3
891 104 131 139 lightblue4
892 224 255 255 lightcyan1
893 209 238 238 lightcyan2
894 180 205 205 lightcyan3
895 122 139 139 lightcyan4
896 187 255 255 paleturquoise1
897 174 238 238 paleturquoise2
898 150 205 205 paleturquoise3
899 102 139 139 paleturquoise4
900 152 245 255 cadetblue1
901 142 229 238 cadetblue2
902 122 197 205 cadetblue3
903 83 134 139 cadetblue4
904 0 245 255 turquoise1
905 0 229 238 turquoise2
906 0 197 205 turquoise3
907 0 134 139 turquoise4
908 0 255 255 cyan1
909 0 238 238 cyan2
910 0 205 205 cyan3
911 0 139 139 cyan4
912 151 255 255 darkslategray1
913 141 238 238 darkslategray2
914 121 205 205 darkslategray3
915 82 139 139 darkslategray4
916 127 255 212 aquamarine1
917 118 238 198 aquamarine2
918 102 205 170 aquamarine3
919 69 139 116 aquamarine4
920 193 255 193 darkseagreen1
921 180 238 180 darkseagreen2
922 155 205 155 darkseagreen3
923 105 139 105 darkseagreen4
924 84 255 159 seagreen1
925 78 238 148 seagreen2
926 67 205 128 seagreen3
927 46 139 87 seagreen4
928 154 255 154 palegreen1
929 144 238 144 palegreen2
930 124 205 124 palegreen3
931 84 139 84 palegreen4
932 0 255 127 springgreen1
933 0 238 118 springgreen2
934 0 205 102 springgreen3
935 0 139 69 springgreen4
936 0 255 0 green1
937 0 238 0 green2
938 0 205 0 green3
939 0 139 0 green4
940 127 255 0 chartreuse1
941 118 238 0 chartreuse2
942 102 205 0 chartreuse3
943 69 139 0 chartreuse4
944 192 255 62 olivedrab1
945 179 238 58 olivedrab2
946 154 205 50 olivedrab3
947 105 139 34 olivedrab4
948 202 255 112 darkolivegreen1
949 188 238 104 darkolivegreen2
950 162 205 90 darkolivegreen3
951 110 139 61 darkolivegreen4
952 255 246 143 khaki1
953 238 230 133 khaki2
954 205 198 115 khaki3
955 139 134 78 khaki4
956 255 236 139 lightgoldenrod1
957 238 220 130 lightgoldenrod2
958 205 190 112 lightgoldenrod3
959 139 129 76 lightgoldenrod4
960 255 255 224 lightyellow1
961 238 238 209 lightyellow2
962 205 205 180 lightyellow3
963 139 139 122 lightyellow4
964 255 255 0 yellow1
965 238 238 0 yellow2
966 205 205 0 yellow3
967 139 139 0 yellow4
968 255 215 0 gold1
969 238 201 0 gold2
970 205 173 0 gold3
971 139 117 0 gold4
972 255 193 37 goldenrod1
973 238 180 34 goldenrod2
974 205 155 29 goldenrod3
975 139 105 20 goldenrod4
976 255 185 15 darkgoldenrod1
977 238 173 14 darkgoldenrod2
978 205 149 12 darkgoldenrod3
979 139 101 8 darkgoldenrod4
980 255 193 193 rosybrown1
981 238 180 180 rosybrown2
982 205 155 155 rosybrown3
983 139 105 105 rosybrown4
984 255 106 106 indianred1
985 238 99 99 indianred2
986 205 85 85 indianred3
987 139 58 58 indianred4
988 255 130 71 sienna1
989 238 121 66 sienna2
990 205 104 57 sienna3
991 139 71 38 sienna4
992 255 211 155 burlywood1
993 238 197 145 burlywood2
994 205 170 125 burlywood3
995 139 115 85 burlywood4
996 255 231 186 wheat1
997 238 216 174 wheat2
998 205 186 150 wheat3
999 139 126 102 wheat4
1000 255 165 79 tan1
1001 238 154 73 tan2
1002 205 133 63 tan3
1003 139 90 43 tan4
1004 255 127 36 chocolate1
1005 238 118 33 chocolate2
1006 205 102 29 chocolate3
1007 139 69 19 chocolate4
1008 255 48 48 firebrick1
1009 238 44 44 firebrick2
1010 205 38 38 firebrick3
1011 139 26 26 firebrick4
1012 255 64 64 brown1
1013 238 59 59 brown2
1014 205 51 51 brown3
1015 139 35 35 brown4
1016 255 140 105 salmon1
1017 238 130 98 salmon2
1018 205 112 84 salmon3
1019 139 76 57 salmon4
1020 255 160 122 lightsalmon1
1021 238 149 114 lightsalmon2
1022 205 129 98 lightsalmon3
1023 139 87 66 lightsalmon4
1024 255 165 0 orange1
1025 238 154 0 orange2
1026 205 133 0 orange3
1027 139 90 0 orange4
1028 255 127 0 darkorange1
1029 238 118 0 darkorange2
1030 205 102 0 darkorange3
1031 139 69 0 darkorange4
1032 255 114 86 coral1
1033 238 106 80 coral2
1034 205 91 69 coral3
1035 139 62 47 coral4
1036 255 99 71 tomato1
1037 238 92 66 tomato2
1038 205 79 57 tomato3
1039 139 54 38 tomato4
1040 255 69 0 orangered1
1041 238 64 0 orangered2
1042 205 55 0 orangered3
1043 139 37 0 orangered4
1044 255 0 0 red1
1045 238 0 0 red2
1046 205 0 0 red3
1047 139 0 0 red4
1048 255 20 147 deeppink1
1049 238 18 137 deeppink2
1050 205 16 118 deeppink3
1051 139 10 80 deeppink4
1052 255 110 180 hotpink1
1053 238 106 167 hotpink2
1054 205 96 144 hotpink3
1055 139 58 98 hotpink4
1056 255 181 197 pink1
1057 238 169 184 pink2
1058 205 145 158 pink3
1059 139 99 108 pink4
1060 255 174 185 lightpink1
1061 238 162 173 lightpink2
1062 205 140 149 lightpink3
1063 139 95 101 lightpink4
1064 255 130 171 palevioletred1
1065 238 121 159 palevioletred2
1066 205 104 137 palevioletred3
1067 139 71 93 palevioletred4
1068 255 52 179 maroon1
1069 238 48 167 maroon2
1070 205 41 144 maroon3
1071 139 28 98 maroon4
1072 255 62 150 violetred1
1073 238 58 140 violetred2
1074 205 50 120 violetred3
1075 139 34 82 violetred4
1076 255 0 255 magenta1
1077 238 0 238 magenta2
1078 205 0 205 magenta3
1079 139 0 139 magenta4
1080 255 131 250 orchid1
1081 238 122 233 orchid2
1082 205 105 201 orchid3
1083 139 71 137 orchid4
1084 255 187 255 plum1
1085 238 174 238 plum2
1086 205 150 205 plum3
1087 139 102 139 plum4
1088 224 102 255 mediumorchid1
1089 209 95 238 mediumorchid2
1090 180 82 205 mediumorchid3
1091 122 55 139 mediumorchid4
1092 191 62 255 darkorchid1
1093 178 58 238 darkorchid2
1094 154 50 205 darkorchid3
1095 104 34 139 darkorchid4
1096 155 48 255 purple1
1097 145 44 238 purple2
1098 125 38 205 purple3
1099 85 26 139 purple4
1100 171 130 255 mediumpurple1
1101 159 121 238 mediumpurple2
1102 137 104 205 mediumpurple3
1103 93 71 139 mediumpurple4
1104 255 225 255 thistle1
1105 238 210 238 thistle2
1106 205 181 205 thistle3
1107 139 123 139 thistle4
1108 0 0 0 gray0
1109 0 0 0 grey0
1110 3 3 3 gray1
1111 3 3 3 grey1
1112 5 5 5 gray2
1113 5 5 5 grey2
1114 8 8 8 gray3
1115 8 8 8 grey3
1116 10 10 10 gray4
1117 10 10 10 grey4
1118 13 13 13 gray5
1119 13 13 13 grey5
1120 15 15 15 gray6
1121 15 15 15 grey6
1122 18 18 18 gray7
1123 18 18 18 grey7
1124 20 20 20 gray8
1125 20 20 20 grey8
1126 23 23 23 gray9
1127 23 23 23 grey9
1128 26 26 26 gray10
1129 26 26 26 grey10
1130 28 28 28 gray11
1131 28 28 28 grey11
1132 31 31 31 gray12
1133 31 31 31 grey12
1134 33 33 33 gray13
1135 33 33 33 grey13
1136 36 36 36 gray14
1137 36 36 36 grey14
1138 38 38 38 gray15
1139 38 38 38 grey15
1140 41 41 41 gray16
1141 41 41 41 grey16
1142 43 43 43 gray17
1143 43 43 43 grey17
1144 46 46 46 gray18
1145 46 46 46 grey18
1146 48 48 48 gray19
1147 48 48 48 grey19
1148 51 51 51 gray20
1149 51 51 51 grey20
1150 54 54 54 gray21
1151 54 54 54 grey21
1152 56 56 56 gray22
1153 56 56 56 grey22
1154 59 59 59 gray23
1155 59 59 59 grey23
1156 61 61 61 gray24
1157 61 61 61 grey24
1158 64 64 64 gray25
1159 64 64 64 grey25
1160 66 66 66 gray26
1161 66 66 66 grey26
1162 69 69 69 gray27
1163 69 69 69 grey27
1164 71 71 71 gray28
1165 71 71 71 grey28
1166 74 74 74 gray29
1167 74 74 74 grey29
1168 77 77 77 gray30
1169 77 77 77 grey30
1170 79 79 79 gray31
1171 79 79 79 grey31
1172 82 82 82 gray32
1173 82 82 82 grey32
1174 84 84 84 gray33
1175 84 84 84 grey33
1176 87 87 87 gray34
1177 87 87 87 grey34
1178 89 89 89 gray35
1179 89 89 89 grey35
1180 92 92 92 gray36
1181 92 92 92 grey36
1182 94 94 94 gray37
1183 94 94 94 grey37
1184 97 97 97 gray38
1185 97 97 97 grey38
1186 99 99 99 gray39
1187 99 99 99 grey39
1188 102 102 102 gray40
1189 102 102 102 grey40
1190 105 105 105 gray41
1191 105 105 105 grey41
1192 107 107 107 gray42
1193 107 107 107 grey42
1194 110 110 110 gray43
1195 110 110 110 grey43
1196 112 112 112 gray44
1197 112 112 112 grey44
1198 115 115 115 gray45
1199 115 115 115 grey45
1200 117 117 117 gray46
1201 117 117 117 grey46
1202 120 120 120 gray47
1203 120 120 120 grey47
1204 122 122 122 gray48
1205 122 122 122 grey48
1206 125 125 125 gray49
1207 125 125 125 grey49
1208 127 127 127 gray50
1209 127 127 127 grey50
1210 130 130 130 gray51
1211 130 130 130 grey51
1212 133 133 133 gray52
1213 133 133 133 grey52
1214 135 135 135 gray53
1215 135 135 135 grey53
1216 138 138 138 gray54
1217 138 138 138 grey54
1218 140 140 140 gray55
1219 140 140 140 grey55
1220 143 143 143 gray56
1221 143 143 143 grey56
1222 145 145 145 gray57
1223 145 145 145 grey57
1224 148 148 148 gray58
1225 148 148 148 grey58
1226 150 150 150 gray59
1227 150 150 150 grey59
1228 153 153 153 gray60
1229 153 153 153 grey60
1230 156 156 156 gray61
1231 156 156 156 grey61
1232 158 158 158 gray62
1233 158 158 158 grey62
1234 161 161 161 gray63
1235 161 161 161 grey63
1236 163 163 163 gray64
1237 163 163 163 grey64
1238 166 166 166 gray65
1239 166 166 166 grey65
1240 168 168 168 gray66
1241 168 168 168 grey66
1242 171 171 171 gray67
1243 171 171 171 grey67
1244 173 173 173 gray68
1245 173 173 173 grey68
1246 176 176 176 gray69
1247 176 176 176 grey69
1248 179 179 179 gray70
1249 179 179 179 grey70
1250 181 181 181 gray71
1251 181 181 181 grey71
1252 184 184 184 gray72
1253 184 184 184 grey72
1254 186 186 186 gray73
1255 186 186 186 grey73
1256 189 189 189 gray74
1257 189 189 189 grey74
1258 191 191 191 gray75
1259 191 191 191 grey75
1260 194 194 194 gray76
1261 194 194 194 grey76
1262 196 196 196 gray77
1263 196 196 196 grey77
1264 199 199 199 gray78
1265 199 199 199 grey78
1266 201 201 201 gray79
1267 201 201 201 grey79
1268 204 204 204 gray80
1269 204 204 204 grey80
1270 207 207 207 gray81
1271 207 207 207 grey81
1272 209 209 209 gray82
1273 209 209 209 grey82
1274 212 212 212 gray83
1275 212 212 212 grey83
1276 214 214 214 gray84
1277 214 214 214 grey84
1278 217 217 217 gray85
1279 217 217 217 grey85
1280 219 219 219 gray86
1281 219 219 219 grey86
1282 222 222 222 gray87
1283 222 222 222 grey87
1284 224 224 224 gray88
1285 224 224 224 grey88
1286 227 227 227 gray89
1287 227 227 227 grey89
1288 229 229 229 gray90
1289 229 229 229 grey90
1290 232 232 232 gray91
1291 232 232 232 grey91
1292 235 235 235 gray92
1293 235 235 235 grey92
1294 237 237 237 gray93
1295 237 237 237 grey93
1296 240 240 240 gray94
1297 240 240 240 grey94
1298 242 242 242 gray95
1299 242 242 242 grey95
1300 245 245 245 gray96
1301 245 245 245 grey96
1302 247 247 247 gray97
1303 247 247 247 grey97
1304 250 250 250 gray98
1305 250 250 250 grey98
1306 252 252 252 gray99
1307 252 252 252 grey99
1308 255 255 255 gray100
1309 255 255 255 grey100
1310 169 169 169 darkgrey
1311 169 169 169 darkgray
1312 0 0 139 darkblue
1313 0 139 139 darkcyan
1314 139 0 139 darkmagenta
1315 139 0 0 darkred
1316 144 238 144 lightgreen
1317 220 20 60 crimson
1318 75 0 130 indigo
1319 128 128 0 olive
1320 102 51 153 rebeccapurple
1321 192 192 192 silver
1322 0 128 128 teal
1323 # css differences
1324 128 128 128 css-gray
1325 128 128 128 css-grey
1326 0 128 0 css-green
1327 128 0 0 css-maroon
1328 128 0 128 css-purple