add legend
[sgn.git] / js / MochiKit / Color.js
blob37cb43ba2287b4b501631ab7b4b2385b92018a9b
1 /***
3 MochiKit.Color 1.4
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito and others.  All rights Reserved.
9 ***/
11 if (typeof(dojo) != 'undefined') {
12     dojo.provide('MochiKit.Color');
13     dojo.require('MochiKit.Base');
14     dojo.require('MochiKit.DOM');
15     dojo.require('MochiKit.Style');
18 if (typeof(JSAN) != 'undefined') {
19     JSAN.use("MochiKit.Base", []);
20     JSAN.use("MochiKit.DOM", []);
21     JSAN.use("MochiKit.Style", []);
24 try {
25     if (typeof(MochiKit.Base) == 'undefined') {
26         throw "";
27     }
28 } catch (e) {
29     throw "MochiKit.Color depends on MochiKit.Base";
32 try {
33     if (typeof(MochiKit.DOM) == 'undefined') {
34         throw "";
35     }
36 } catch (e) {
37     throw "MochiKit.Color depends on MochiKit.DOM";
40 try {
41     if (typeof(MochiKit.Style) == 'undefined') {
42         throw "";
43     }
44 } catch (e) {
45     throw "MochiKit.Color depends on MochiKit.Style";
48 if (typeof(MochiKit.Color) == "undefined") {
49     MochiKit.Color = {};
52 MochiKit.Color.NAME = "MochiKit.Color";
53 MochiKit.Color.VERSION = "1.4";
55 MochiKit.Color.__repr__ = function () {
56     return "[" + this.NAME + " " + this.VERSION + "]";
59 MochiKit.Color.toString = function () {
60     return this.__repr__();
64 /** @id MochiKit.Color.Color */
65 MochiKit.Color.Color = function (red, green, blue, alpha) {
66     if (typeof(alpha) == 'undefined' || alpha === null) {
67         alpha = 1.0;
68     }
69     this.rgb = {
70         r: red,
71         g: green,
72         b: blue,
73         a: alpha
74     };
78 // Prototype methods
80 MochiKit.Color.Color.prototype = {
82     __class__: MochiKit.Color.Color,
84     /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
85     colorWithAlpha: function (alpha) {
86         var rgb = this.rgb;
87         var m = MochiKit.Color;
88         return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
89     },
91     /** @id MochiKit.Color.Color.prototype.colorWithHue */
92     colorWithHue: function (hue) {
93         // get an HSL model, and set the new hue...
94         var hsl = this.asHSL();
95         hsl.h = hue;
96         var m = MochiKit.Color;
97         // convert back to RGB...
98         return m.Color.fromHSL(hsl);
99     },
101     /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
102     colorWithSaturation: function (saturation) {
103         // get an HSL model, and set the new hue...
104         var hsl = this.asHSL();
105         hsl.s = saturation;
106         var m = MochiKit.Color;
107         // convert back to RGB...
108         return m.Color.fromHSL(hsl);
109     },
111     /** @id MochiKit.Color.Color.prototype.colorWithLightness */
112     colorWithLightness: function (lightness) {
113         // get an HSL model, and set the new hue...
114         var hsl = this.asHSL();
115         hsl.l = lightness;
116         var m = MochiKit.Color;
117         // convert back to RGB...
118         return m.Color.fromHSL(hsl);
119     },
121     /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
122     darkerColorWithLevel: function (level) {
123         var hsl  = this.asHSL();
124         hsl.l = Math.max(hsl.l - level, 0);
125         var m = MochiKit.Color;
126         return m.Color.fromHSL(hsl);
127     },
129     /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
130     lighterColorWithLevel: function (level) {
131         var hsl  = this.asHSL();
132         hsl.l = Math.min(hsl.l + level, 1);
133         var m = MochiKit.Color;
134         return m.Color.fromHSL(hsl);
135     },
137     /** @id MochiKit.Color.Color.prototype.blendedColor */
138     blendedColor: function (other, /* optional */ fraction) {
139         if (typeof(fraction) == 'undefined' || fraction === null) {
140             fraction = 0.5;
141         }
142         var sf = 1.0 - fraction;
143         var s = this.rgb;
144         var d = other.rgb;
145         var df = fraction;
146         return MochiKit.Color.Color.fromRGB(
147             (s.r * sf) + (d.r * df),
148             (s.g * sf) + (d.g * df),
149             (s.b * sf) + (d.b * df),
150             (s.a * sf) + (d.a * df)
151         );
152     },
154     /** @id MochiKit.Color.Color.prototype.compareRGB */
155     compareRGB: function (other) {
156         var a = this.asRGB();
157         var b = other.asRGB();
158         return MochiKit.Base.compare(
159             [a.r, a.g, a.b, a.a],
160             [b.r, b.g, b.b, b.a]
161         );
162     },
164     /** @id MochiKit.Color.Color.prototype.isLight */
165     isLight: function () {
166         return this.asHSL().b > 0.5;
167     },
169     /** @id MochiKit.Color.Color.prototype.isDark */
170     isDark: function () {
171         return (!this.isLight());
172     },
174     /** @id MochiKit.Color.Color.prototype.toHSLString */
175     toHSLString: function () {
176         var c = this.asHSL();
177         var ccc = MochiKit.Color.clampColorComponent;
178         var rval = this._hslString;
179         if (!rval) {
180             var mid = (
181                 ccc(c.h, 360).toFixed(0)
182                 + "," + ccc(c.s, 100).toPrecision(4) + "%"
183                 + "," + ccc(c.l, 100).toPrecision(4) + "%"
184             );
185             var a = c.a;
186             if (a >= 1) {
187                 a = 1;
188                 rval = "hsl(" + mid + ")";
189             } else {
190                 if (a <= 0) {
191                     a = 0;
192                 }
193                 rval = "hsla(" + mid + "," + a + ")";
194             }
195             this._hslString = rval;
196         }
197         return rval;
198     },
200     /** @id MochiKit.Color.Color.prototype.toRGBString */
201     toRGBString: function () {
202         var c = this.rgb;
203         var ccc = MochiKit.Color.clampColorComponent;
204         var rval = this._rgbString;
205         if (!rval) {
206             var mid = (
207                 ccc(c.r, 255).toFixed(0)
208                 + "," + ccc(c.g, 255).toFixed(0)
209                 + "," + ccc(c.b, 255).toFixed(0)
210             );
211             if (c.a != 1) {
212                 rval = "rgba(" + mid + "," + c.a + ")";
213             } else {
214                 rval = "rgb(" + mid + ")";
215             }
216             this._rgbString = rval;
217         }
218         return rval;
219     },
221     /** @id MochiKit.Color.Color.prototype.asRGB */
222     asRGB: function () {
223         return MochiKit.Base.clone(this.rgb);
224     },
226     /** @id MochiKit.Color.Color.prototype.toHexString */
227     toHexString: function () {
228         var m = MochiKit.Color;
229         var c = this.rgb;
230         var ccc = MochiKit.Color.clampColorComponent;
231         var rval = this._hexString;
232         if (!rval) {
233             rval = ("#" +
234                 m.toColorPart(ccc(c.r, 255)) +
235                 m.toColorPart(ccc(c.g, 255)) +
236                 m.toColorPart(ccc(c.b, 255))
237             );
238             this._hexString = rval;
239         }
240         return rval;
241     },
243     /** @id MochiKit.Color.Color.prototype.asHSV */
244     asHSV: function () {
245         var hsv = this.hsv;
246         var c = this.rgb;
247         if (typeof(hsv) == 'undefined' || hsv === null) {
248             hsv = MochiKit.Color.rgbToHSV(this.rgb);
249             this.hsv = hsv;
250         }
251         return MochiKit.Base.clone(hsv);
252     },
254     /** @id MochiKit.Color.Color.prototype.asHSL */
255     asHSL: function () {
256         var hsl = this.hsl;
257         var c = this.rgb;
258         if (typeof(hsl) == 'undefined' || hsl === null) {
259             hsl = MochiKit.Color.rgbToHSL(this.rgb);
260             this.hsl = hsl;
261         }
262         return MochiKit.Base.clone(hsl);
263     },
265     /** @id MochiKit.Color.Color.prototype.toString */
266     toString: function () {
267         return this.toRGBString();
268     },
270     /** @id MochiKit.Color.Color.prototype.repr */
271     repr: function () {
272         var c = this.rgb;
273         var col = [c.r, c.g, c.b, c.a];
274         return this.__class__.NAME + "(" + col.join(", ") + ")";
275     }
279 // Constructor methods
281 MochiKit.Base.update(MochiKit.Color.Color, {
282     /** @id MochiKit.Color.Color.fromRGB */
283     fromRGB: function (red, green, blue, alpha) {
284         // designated initializer
285         var Color = MochiKit.Color.Color;
286         if (arguments.length == 1) {
287             var rgb = red;
288             red = rgb.r;
289             green = rgb.g;
290             blue = rgb.b;
291             if (typeof(rgb.a) == 'undefined') {
292                 alpha = undefined;
293             } else {
294                 alpha = rgb.a;
295             }
296         }
297         return new Color(red, green, blue, alpha);
298     },
300     /** @id MochiKit.Color.Color.fromHSL */
301     fromHSL: function (hue, saturation, lightness, alpha) {
302         var m = MochiKit.Color;
303         return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
304     },
306     /** @id MochiKit.Color.Color.fromHSV */
307     fromHSV: function (hue, saturation, value, alpha) {
308         var m = MochiKit.Color;
309         return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
310     },
312     /** @id MochiKit.Color.Color.fromName */
313     fromName: function (name) {
314         var Color = MochiKit.Color.Color;
315         // Opera 9 seems to "quote" named colors(?!)
316         if (name.charAt(0) == '"') {
317             name = name.substr(1, name.length - 2);
318         }
319         var htmlColor = Color._namedColors[name.toLowerCase()];
320         if (typeof(htmlColor) == 'string') {
321             return Color.fromHexString(htmlColor);
322         } else if (name == "transparent") {
323             return Color.transparentColor();
324         }
325         return null;
326     },
328     /** @id MochiKit.Color.Color.fromString */
329     fromString: function (colorString) {
330         var self = MochiKit.Color.Color;
331         var three = colorString.substr(0, 3);
332         if (three == "rgb") {
333             return self.fromRGBString(colorString);
334         } else if (three == "hsl") {
335             return self.fromHSLString(colorString);
336         } else if (colorString.charAt(0) == "#") {
337             return self.fromHexString(colorString);
338         }
339         return self.fromName(colorString);
340     },
343     /** @id MochiKit.Color.Color.fromHexString */
344     fromHexString: function (hexCode) {
345         if (hexCode.charAt(0) == '#') {
346             hexCode = hexCode.substring(1);
347         }
348         var components = [];
349         var i, hex;
350         if (hexCode.length == 3) {
351             for (i = 0; i < 3; i++) {
352                 hex = hexCode.substr(i, 1);
353                 components.push(parseInt(hex + hex, 16) / 255.0);
354             }
355         } else {
356             for (i = 0; i < 6; i += 2) {
357                 hex = hexCode.substr(i, 2);
358                 components.push(parseInt(hex, 16) / 255.0);
359             }
360         }
361         var Color = MochiKit.Color.Color;
362         return Color.fromRGB.apply(Color, components);
363     },
366     _fromColorString: function (pre, method, scales, colorCode) {
367         // parses either HSL or RGB
368         if (colorCode.indexOf(pre) === 0) {
369             colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
370         }
371         var colorChunks = colorCode.split(/\s*,\s*/);
372         var colorFloats = [];
373         for (var i = 0; i < colorChunks.length; i++) {
374             var c = colorChunks[i];
375             var val;
376             var three = c.substring(c.length - 3);
377             if (c.charAt(c.length - 1) == '%') {
378                 val = 0.01 * parseFloat(c.substring(0, c.length - 1));
379             } else if (three == "deg") {
380                 val = parseFloat(c) / 360.0;
381             } else if (three == "rad") {
382                 val = parseFloat(c) / (Math.PI * 2);
383             } else {
384                 val = scales[i] * parseFloat(c);
385             }
386             colorFloats.push(val);
387         }
388         return this[method].apply(this, colorFloats);
389     },
391     /** @id MochiKit.Color.Color.fromComputedStyle */
392     fromComputedStyle: function (elem, style) {
393         var d = MochiKit.DOM;
394         var cls = MochiKit.Color.Color;
395         for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
396             var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
397             if (!actualColor) {
398                 continue;
399             }
400             var color = cls.fromString(actualColor);
401             if (!color) {
402                 break;
403             }
404             if (color.asRGB().a > 0) {
405                 return color;
406             }
407         }
408         return null;
409     },
411     /** @id MochiKit.Color.Color.fromBackground */
412     fromBackground: function (elem) {
413         var cls = MochiKit.Color.Color;
414         return cls.fromComputedStyle(
415             elem, "backgroundColor", "background-color") || cls.whiteColor();
416     },
418     /** @id MochiKit.Color.Color.fromText */
419     fromText: function (elem) {
420         var cls = MochiKit.Color.Color;
421         return cls.fromComputedStyle(
422             elem, "color", "color") || cls.blackColor();
423     },
425     /** @id MochiKit.Color.Color.namedColors */
426     namedColors: function () {
427         return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
428     }
432 // Module level functions
434 MochiKit.Base.update(MochiKit.Color, {
435     /** @id MochiKit.Color.clampColorComponent */
436     clampColorComponent: function (v, scale) {
437         v *= scale;
438         if (v < 0) {
439             return 0;
440         } else if (v > scale) {
441             return scale;
442         } else {
443             return v;
444         }
445     },
447     _hslValue: function (n1, n2, hue) {
448         if (hue > 6.0) {
449             hue -= 6.0;
450         } else if (hue < 0.0) {
451             hue += 6.0;
452         }
453         var val;
454         if (hue < 1.0) {
455             val = n1 + (n2 - n1) * hue;
456         } else if (hue < 3.0) {
457             val = n2;
458         } else if (hue < 4.0) {
459             val = n1 + (n2 - n1) * (4.0 - hue);
460         } else {
461             val = n1;
462         }
463         return val;
464     },
466     /** @id MochiKit.Color.hsvToRGB */
467     hsvToRGB: function (hue, saturation, value, alpha) {
468         if (arguments.length == 1) {
469             var hsv = hue;
470             hue = hsv.h;
471             saturation = hsv.s;
472             value = hsv.v;
473             alpha = hsv.a;
474         }
475         var red;
476         var green;
477         var blue;
478         if (saturation === 0) {
479             red = 0;
480             green = 0;
481             blue = 0;
482         } else {
483             var i = Math.floor(hue * 6);
484             var f = (hue * 6) - i;
485             var p = value * (1 - saturation);
486             var q = value * (1 - (saturation * f));
487             var t = value * (1 - (saturation * (1 - f)));
488             switch (i) {
489                 case 1: red = q; green = value; blue = p; break;
490                 case 2: red = p; green = value; blue = t; break;
491                 case 3: red = p; green = q; blue = value; break;
492                 case 4: red = t; green = p; blue = value; break;
493                 case 5: red = value; green = p; blue = q; break;
494                 case 6: // fall through
495                 case 0: red = value; green = t; blue = p; break;
496             }
497         }
498         return {
499             r: red,
500             g: green,
501             b: blue,
502             a: alpha
503         };
504     },
506     /** @id MochiKit.Color.hslToRGB */
507     hslToRGB: function (hue, saturation, lightness, alpha) {
508         if (arguments.length == 1) {
509             var hsl = hue;
510             hue = hsl.h;
511             saturation = hsl.s;
512             lightness = hsl.l;
513             alpha = hsl.a;
514         }
515         var red;
516         var green;
517         var blue;
518         if (saturation === 0) {
519             red = lightness;
520             green = lightness;
521             blue = lightness;
522         } else {
523             var m2;
524             if (lightness <= 0.5) {
525                 m2 = lightness * (1.0 + saturation);
526             } else {
527                 m2 = lightness + saturation - (lightness * saturation);
528             }
529             var m1 = (2.0 * lightness) - m2;
530             var f = MochiKit.Color._hslValue;
531             var h6 = hue * 6.0;
532             red = f(m1, m2, h6 + 2);
533             green = f(m1, m2, h6);
534             blue = f(m1, m2, h6 - 2);
535         }
536         return {
537             r: red,
538             g: green,
539             b: blue,
540             a: alpha
541         };
542     },
544     /** @id MochiKit.Color.rgbToHSV */
545     rgbToHSV: function (red, green, blue, alpha) {
546         if (arguments.length == 1) {
547             var rgb = red;
548             red = rgb.r;
549             green = rgb.g;
550             blue = rgb.b;
551             alpha = rgb.a;
552         }
553         var max = Math.max(Math.max(red, green), blue);
554         var min = Math.min(Math.min(red, green), blue);
555         var hue;
556         var saturation;
557         var value = max;
558         if (min == max) {
559             hue = 0;
560             saturation = 0;
561         } else {
562             var delta = (max - min);
563             saturation = delta / max;
565             if (red == max) {
566                 hue = (green - blue) / delta;
567             } else if (green == max) {
568                 hue = 2 + ((blue - red) / delta);
569             } else {
570                 hue = 4 + ((red - green) / delta);
571             }
572             hue /= 6;
573             if (hue < 0) {
574                 hue += 1;
575             }
576             if (hue > 1) {
577                 hue -= 1;
578             }
579         }
580         return {
581             h: hue,
582             s: saturation,
583             v: value,
584             a: alpha
585         };
586     },
588     /** @id MochiKit.Color.rgbToHSL */
589     rgbToHSL: function (red, green, blue, alpha) {
590         if (arguments.length == 1) {
591             var rgb = red;
592             red = rgb.r;
593             green = rgb.g;
594             blue = rgb.b;
595             alpha = rgb.a;
596         }
597         var max = Math.max(red, Math.max(green, blue));
598         var min = Math.min(red, Math.min(green, blue));
599         var hue;
600         var saturation;
601         var lightness = (max + min) / 2.0;
602         var delta = max - min;
603         if (delta === 0) {
604             hue = 0;
605             saturation = 0;
606         } else {
607             if (lightness <= 0.5) {
608                 saturation = delta / (max + min);
609             } else {
610                 saturation = delta / (2 - max - min);
611             }
612             if (red == max) {
613                 hue = (green - blue) / delta;
614             } else if (green == max) {
615                 hue = 2 + ((blue - red) / delta);
616             } else {
617                 hue = 4 + ((red - green) / delta);
618             }
619             hue /= 6;
620             if (hue < 0) {
621                 hue += 1;
622             }
623             if (hue > 1) {
624                 hue -= 1;
625             }
627         }
628         return {
629             h: hue,
630             s: saturation,
631             l: lightness,
632             a: alpha
633         };
634     },
636     /** @id MochiKit.Color.toColorPart */
637     toColorPart: function (num) {
638         num = Math.round(num);
639         var digits = num.toString(16);
640         if (num < 16) {
641             return '0' + digits;
642         }
643         return digits;
644     },
646     __new__: function () {
647         var m = MochiKit.Base;
648         /** @id MochiKit.Color.fromRGBString */
649         this.Color.fromRGBString = m.bind(
650             this.Color._fromColorString, this.Color, "rgb", "fromRGB",
651             [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
652         );
653         /** @id MochiKit.Color.fromHSLString */
654         this.Color.fromHSLString = m.bind(
655             this.Color._fromColorString, this.Color, "hsl", "fromHSL",
656             [1.0/360.0, 0.01, 0.01, 1]
657         );
659         var third = 1.0 / 3.0;
660         /** @id MochiKit.Color.colors */
661         var colors = {
662             // NSColor colors plus transparent
663             /** @id MochiKit.Color.blackColor */
664             black: [0, 0, 0],
665             /** @id MochiKit.Color.blueColor */
666             blue: [0, 0, 1],
667             /** @id MochiKit.Color.brownColor */
668             brown: [0.6, 0.4, 0.2],
669             /** @id MochiKit.Color.cyanColor */
670             cyan: [0, 1, 1],
671             /** @id MochiKit.Color.darkGrayColor */
672             darkGray: [third, third, third],
673             /** @id MochiKit.Color.grayColor */
674             gray: [0.5, 0.5, 0.5],
675             /** @id MochiKit.Color.greenColor */
676             green: [0, 1, 0],
677             /** @id MochiKit.Color.lightGrayColor */
678             lightGray: [2 * third, 2 * third, 2 * third],
679             /** @id MochiKit.Color.magentaColor */
680             magenta: [1, 0, 1],
681             /** @id MochiKit.Color.orangeColor */
682             orange: [1, 0.5, 0],
683             /** @id MochiKit.Color.purpleColor */
684             purple: [0.5, 0, 0.5],
685             /** @id MochiKit.Color.redColor */
686             red: [1, 0, 0],
687             /** @id MochiKit.Color.transparentColor */
688             transparent: [0, 0, 0, 0],
689             /** @id MochiKit.Color.whiteColor */
690             white: [1, 1, 1],
691             /** @id MochiKit.Color.yellowColor */
692             yellow: [1, 1, 0]
693         };
695         var makeColor = function (name, r, g, b, a) {
696             var rval = this.fromRGB(r, g, b, a);
697             this[name] = function () { return rval; };
698             return rval;
699         };
701         for (var k in colors) {
702             var name = k + "Color";
703             var bindArgs = m.concat(
704                 [makeColor, this.Color, name],
705                 colors[k]
706             );
707             this.Color[name] = m.bind.apply(null, bindArgs);
708         }
710         var isColor = function () {
711             for (var i = 0; i < arguments.length; i++) {
712                 if (!(arguments[i] instanceof Color)) {
713                     return false;
714                 }
715             }
716             return true;
717         };
719         var compareColor = function (a, b) {
720             return a.compareRGB(b);
721         };
723         m.nameFunctions(this);
725         m.registerComparator(this.Color.NAME, isColor, compareColor);
727         this.EXPORT_TAGS = {
728             ":common": this.EXPORT,
729             ":all": m.concat(this.EXPORT, this.EXPORT_OK)
730         };
732     }
735 MochiKit.Color.EXPORT = [
736     "Color"
739 MochiKit.Color.EXPORT_OK = [
740     "clampColorComponent",
741     "rgbToHSL",
742     "hslToRGB",
743     "rgbToHSV",
744     "hsvToRGB",
745     "toColorPart"
748 MochiKit.Color.__new__();
750 MochiKit.Base._exportSymbols(this, MochiKit.Color);
752 // Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
754 MochiKit.Color.Color._namedColors = {
755     aliceblue: "#f0f8ff",
756     antiquewhite: "#faebd7",
757     aqua: "#00ffff",
758     aquamarine: "#7fffd4",
759     azure: "#f0ffff",
760     beige: "#f5f5dc",
761     bisque: "#ffe4c4",
762     black: "#000000",
763     blanchedalmond: "#ffebcd",
764     blue: "#0000ff",
765     blueviolet: "#8a2be2",
766     brown: "#a52a2a",
767     burlywood: "#deb887",
768     cadetblue: "#5f9ea0",
769     chartreuse: "#7fff00",
770     chocolate: "#d2691e",
771     coral: "#ff7f50",
772     cornflowerblue: "#6495ed",
773     cornsilk: "#fff8dc",
774     crimson: "#dc143c",
775     cyan: "#00ffff",
776     darkblue: "#00008b",
777     darkcyan: "#008b8b",
778     darkgoldenrod: "#b8860b",
779     darkgray: "#a9a9a9",
780     darkgreen: "#006400",
781     darkgrey: "#a9a9a9",
782     darkkhaki: "#bdb76b",
783     darkmagenta: "#8b008b",
784     darkolivegreen: "#556b2f",
785     darkorange: "#ff8c00",
786     darkorchid: "#9932cc",
787     darkred: "#8b0000",
788     darksalmon: "#e9967a",
789     darkseagreen: "#8fbc8f",
790     darkslateblue: "#483d8b",
791     darkslategray: "#2f4f4f",
792     darkslategrey: "#2f4f4f",
793     darkturquoise: "#00ced1",
794     darkviolet: "#9400d3",
795     deeppink: "#ff1493",
796     deepskyblue: "#00bfff",
797     dimgray: "#696969",
798     dimgrey: "#696969",
799     dodgerblue: "#1e90ff",
800     firebrick: "#b22222",
801     floralwhite: "#fffaf0",
802     forestgreen: "#228b22",
803     fuchsia: "#ff00ff",
804     gainsboro: "#dcdcdc",
805     ghostwhite: "#f8f8ff",
806     gold: "#ffd700",
807     goldenrod: "#daa520",
808     gray: "#808080",
809     green: "#008000",
810     greenyellow: "#adff2f",
811     grey: "#808080",
812     honeydew: "#f0fff0",
813     hotpink: "#ff69b4",
814     indianred: "#cd5c5c",
815     indigo: "#4b0082",
816     ivory: "#fffff0",
817     khaki: "#f0e68c",
818     lavender: "#e6e6fa",
819     lavenderblush: "#fff0f5",
820     lawngreen: "#7cfc00",
821     lemonchiffon: "#fffacd",
822     lightblue: "#add8e6",
823     lightcoral: "#f08080",
824     lightcyan: "#e0ffff",
825     lightgoldenrodyellow: "#fafad2",
826     lightgray: "#d3d3d3",
827     lightgreen: "#90ee90",
828     lightgrey: "#d3d3d3",
829     lightpink: "#ffb6c1",
830     lightsalmon: "#ffa07a",
831     lightseagreen: "#20b2aa",
832     lightskyblue: "#87cefa",
833     lightslategray: "#778899",
834     lightslategrey: "#778899",
835     lightsteelblue: "#b0c4de",
836     lightyellow: "#ffffe0",
837     lime: "#00ff00",
838     limegreen: "#32cd32",
839     linen: "#faf0e6",
840     magenta: "#ff00ff",
841     maroon: "#800000",
842     mediumaquamarine: "#66cdaa",
843     mediumblue: "#0000cd",
844     mediumorchid: "#ba55d3",
845     mediumpurple: "#9370db",
846     mediumseagreen: "#3cb371",
847     mediumslateblue: "#7b68ee",
848     mediumspringgreen: "#00fa9a",
849     mediumturquoise: "#48d1cc",
850     mediumvioletred: "#c71585",
851     midnightblue: "#191970",
852     mintcream: "#f5fffa",
853     mistyrose: "#ffe4e1",
854     moccasin: "#ffe4b5",
855     navajowhite: "#ffdead",
856     navy: "#000080",
857     oldlace: "#fdf5e6",
858     olive: "#808000",
859     olivedrab: "#6b8e23",
860     orange: "#ffa500",
861     orangered: "#ff4500",
862     orchid: "#da70d6",
863     palegoldenrod: "#eee8aa",
864     palegreen: "#98fb98",
865     paleturquoise: "#afeeee",
866     palevioletred: "#db7093",
867     papayawhip: "#ffefd5",
868     peachpuff: "#ffdab9",
869     peru: "#cd853f",
870     pink: "#ffc0cb",
871     plum: "#dda0dd",
872     powderblue: "#b0e0e6",
873     purple: "#800080",
874     red: "#ff0000",
875     rosybrown: "#bc8f8f",
876     royalblue: "#4169e1",
877     saddlebrown: "#8b4513",
878     salmon: "#fa8072",
879     sandybrown: "#f4a460",
880     seagreen: "#2e8b57",
881     seashell: "#fff5ee",
882     sienna: "#a0522d",
883     silver: "#c0c0c0",
884     skyblue: "#87ceeb",
885     slateblue: "#6a5acd",
886     slategray: "#708090",
887     slategrey: "#708090",
888     snow: "#fffafa",
889     springgreen: "#00ff7f",
890     steelblue: "#4682b4",
891     tan: "#d2b48c",
892     teal: "#008080",
893     thistle: "#d8bfd8",
894     tomato: "#ff6347",
895     turquoise: "#40e0d0",
896     violet: "#ee82ee",
897     wheat: "#f5deb3",
898     white: "#ffffff",
899     whitesmoke: "#f5f5f5",
900     yellow: "#ffff00",
901     yellowgreen: "#9acd32"