Initial check-in
[dygraphs.git] / mochikit_v14 / MochiKit / Color.js
1 /***
2
3 MochiKit.Color 1.4
4
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7 (c) 2005 Bob Ippolito and others. All rights Reserved.
8
9 ***/
10
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');
16 }
17
18 if (typeof(JSAN) != 'undefined') {
19 JSAN.use("MochiKit.Base", []);
20 JSAN.use("MochiKit.DOM", []);
21 JSAN.use("MochiKit.Style", []);
22 }
23
24 try {
25 if (typeof(MochiKit.Base) == 'undefined') {
26 throw "";
27 }
28 } catch (e) {
29 throw "MochiKit.Color depends on MochiKit.Base";
30 }
31
32 try {
33 if (typeof(MochiKit.DOM) == 'undefined') {
34 throw "";
35 }
36 } catch (e) {
37 throw "MochiKit.Color depends on MochiKit.DOM";
38 }
39
40 try {
41 if (typeof(MochiKit.Style) == 'undefined') {
42 throw "";
43 }
44 } catch (e) {
45 throw "MochiKit.Color depends on MochiKit.Style";
46 }
47
48 if (typeof(MochiKit.Color) == "undefined") {
49 MochiKit.Color = {};
50 }
51
52 MochiKit.Color.NAME = "MochiKit.Color";
53 MochiKit.Color.VERSION = "1.4";
54
55 MochiKit.Color.__repr__ = function () {
56 return "[" + this.NAME + " " + this.VERSION + "]";
57 };
58
59 MochiKit.Color.toString = function () {
60 return this.__repr__();
61 };
62
63
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 };
75 };
76
77
78 // Prototype methods
79
80 MochiKit.Color.Color.prototype = {
81
82 __class__: MochiKit.Color.Color,
83
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 },
90
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 },
100
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 },
110
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 },
120
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 },
128
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 },
136
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 },
153
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 },
163
164 /** @id MochiKit.Color.Color.prototype.isLight */
165 isLight: function () {
166 return this.asHSL().b > 0.5;
167 },
168
169 /** @id MochiKit.Color.Color.prototype.isDark */
170 isDark: function () {
171 return (!this.isLight());
172 },
173
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 },
199
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 },
220
221 /** @id MochiKit.Color.Color.prototype.asRGB */
222 asRGB: function () {
223 return MochiKit.Base.clone(this.rgb);
224 },
225
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 },
242
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 },
253
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 },
264
265 /** @id MochiKit.Color.Color.prototype.toString */
266 toString: function () {
267 return this.toRGBString();
268 },
269
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 }
276
277 };
278
279 // Constructor methods
280
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 },
299
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 },
305
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 },
311
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 },
327
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 },
341
342
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 },
364
365
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 },
390
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 },
410
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 },
417
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 },
424
425 /** @id MochiKit.Color.Color.namedColors */
426 namedColors: function () {
427 return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
428 }
429 });
430
431
432 // Module level functions
433
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 },
446
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 },
465
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 = value;
480 green = value;
481 blue = value;
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 },
505
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 },
543
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;
564
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 },
587
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 }
626
627 }
628 return {
629 h: hue,
630 s: saturation,
631 l: lightness,
632 a: alpha
633 };
634 },
635
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 },
645
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 );
658
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 };
694
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 };
700
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 }
709
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 };
718
719 var compareColor = function (a, b) {
720 return a.compareRGB(b);
721 };
722
723 m.nameFunctions(this);
724
725 m.registerComparator(this.Color.NAME, isColor, compareColor);
726
727 this.EXPORT_TAGS = {
728 ":common": this.EXPORT,
729 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
730 };
731
732 }
733 });
734
735 MochiKit.Color.EXPORT = [
736 "Color"
737 ];
738
739 MochiKit.Color.EXPORT_OK = [
740 "clampColorComponent",
741 "rgbToHSL",
742 "hslToRGB",
743 "rgbToHSV",
744 "hsvToRGB",
745 "toColorPart"
746 ];
747
748 MochiKit.Color.__new__();
749
750 MochiKit.Base._exportSymbols(this, MochiKit.Color);
751
752 // Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
753
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"
902 };