Roo/lib/Color.js
[roojs1] / Roo / lib / Color.js
1 /*
2
3 Color.js
4
5 Functions for Color handling and processing.
6
7 http://www.safalra.com/web-design/javascript/Color-handling-and-processing/
8
9 The author of this program, Safalra (Stephen Morley), irrevocably releases all
10 rights to this program, with the intention of it becoming part of the public
11 domain. Because this program is released into the public domain, it comes with
12 no warranty either expressed or implied, to the extent permitted by law.
13
14 For more free and public domain JavaScript code by the same author, visit:
15 http://www.safalra.com/web-design/javascript/
16
17 */
18
19
20 /*
21  * @class Roo.lib.Color
22  * An abstract Color implementation. Concrete Color implementations should use
23  * an instance of this function as their prototype, and implement the getRGB and
24  * getHSL functions. getRGB should return an object representing the RGB
25  * components of this Color, with the red, green, and blue components in the
26  * range [0,255] and the alpha component in the range [0,100]. getHSL should
27  * return an object representing the HSL components of this Color, with the hue
28  * component in the range [0,360), the saturation and lightness components in
29  * the range [0,100], and the alpha component in the range [0,1].
30  */
31 Roo.lib.Color = function(){
32
33   /**
34    * @returns an object representing the RGBA components of this Color. The red,
35    * green, and blue components are converted to integers in the range [0,255].
36    * The alpha is a value in the range [0,1].
37    */
38   this.getIntegerRGB = function(){
39
40     // get the RGB components of this Color
41     var rgb = this.getRGB();
42
43     // return the integer components
44     return {
45       'r' : Math.round(rgb.r),
46       'g' : Math.round(rgb.g),
47       'b' : Math.round(rgb.b),
48       'a' : rgb.a
49     };
50
51   };
52
53   /**
54    * @returns an object representing the RGBA components of this Color. The red,
55    * green, and blue components are converted to numbers in the range [0,100].
56    * The alpha is a value in the range [0,1].
57    */
58   this.getPercentageRGB = function(){
59
60     // get the RGB components of this Color
61     var rgb = this.getRGB();
62
63     // return the percentage components
64     return {
65       'r' : 100 * rgb.r / 255,
66       'g' : 100 * rgb.g / 255,
67       'b' : 100 * rgb.b / 255,
68       'a' : rgb.a
69     };
70
71   };
72
73   /**
74    * @returns a string representing this Color as a CSS hexadecimal RGB Color
75    * value - that is, a string of the form #RRGGBB where each of RR, GG, and BB
76    * are two-digit hexadecimal numbers.
77    */
78   this.getCSSHexadecimalRGB = function(){
79
80     // get the integer RGB components
81     var rgb = this.getIntegerRGB();
82
83     // determine the hexadecimal equivalents
84     var r16 = rgb.r.toString(16);
85     var g16 = rgb.g.toString(16);
86     var b16 = rgb.b.toString(16);
87
88     // return the CSS RGB Color value
89     return '#'
90         + (r16.length == 2 ? r16 : '0' + r16)
91         + (g16.length == 2 ? g16 : '0' + g16)
92         + (b16.length == 2 ? b16 : '0' + b16);
93
94   };
95
96   /**
97    * @returns a string representing this Color as a CSS integer RGB Color
98    * value - that is, a string of the form rgb(r,g,b) where each of r, g, and b
99    * are integers in the range [0,255].
100    */
101   this.getCSSIntegerRGB = function(){
102
103     // get the integer RGB components
104     var rgb = this.getIntegerRGB();
105
106     // return the CSS RGB Color value
107     return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
108
109   };
110
111   /**
112    * @returns Returns a string representing this Color as a CSS integer RGBA Color
113    * value - that is, a string of the form rgba(r,g,b,a) where each of r, g, and
114    * b are integers in the range [0,255] and a is in the range [0,1].
115    */
116   this.getCSSIntegerRGBA = function(){
117
118     // get the integer RGB components
119     var rgb = this.getIntegerRGB();
120
121     // return the CSS integer RGBA Color value
122     return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + rgb.a + ')';
123
124   };
125
126   /**
127    * @returns a string representing this Color as a CSS percentage RGB Color
128    * value - that is, a string of the form rgb(r%,g%,b%) where each of r, g, and
129    * b are in the range [0,100].
130    */
131   this.getCSSPercentageRGB = function(){
132
133     // get the percentage RGB components
134     var rgb = this.getPercentageRGB();
135
136     // return the CSS RGB Color value
137     return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%)';
138
139   };
140
141   /**
142    * @returns a string representing this Color as a CSS percentage RGBA Color
143    * value - that is, a string of the form rgba(r%,g%,b%,a) where each of r, g,
144    * and b are in the range [0,100] and a is in the range [0,1].
145    */
146   this.getCSSPercentageRGBA = function(){
147
148     // get the percentage RGB components
149     var rgb = this.getPercentageRGB();
150
151     // return the CSS percentage RGBA Color value
152     return 'rgb(' + rgb.r + '%,' + rgb.g + '%,' + rgb.b + '%,' + rgb.a + ')';
153
154   };
155
156   /**
157    * @returns a string representing this Color as a CSS HSL Color value - that
158    * is, a string of the form hsl(h,s%,l%) where h is in the range [0,100] and
159    * s and l are in the range [0,100].
160    */
161   this.getCSSHSL = function(){
162
163     // get the HSL components
164     var hsl = this.getHSL();
165
166     // return the CSS HSL Color value
167     return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%)';
168
169   };
170
171   /**
172    * @returns a string representing this Color as a CSS HSLA Color value - that
173    * is, a string of the form hsla(h,s%,l%,a) where h is in the range [0,100],
174    * s and l are in the range [0,100], and a is in the range [0,1].
175    */
176   this.getCSSHSLA = function(){
177
178     // get the HSL components
179     var hsl = this.getHSL();
180
181     // return the CSS HSL Color value
182     return 'hsl(' + hsl.h + ',' + hsl.s + '%,' + hsl.l + '%,' + hsl.a + ')';
183
184   };
185
186   /**
187    * Sets the Color of the specified node to this Color. This functions sets
188    * the CSS 'color' property for the node. The parameter is:
189    * 
190    * @param {DomElement} node - the node whose Color should be set
191    */
192   this.setNodeColor = function(node){
193
194     // set the Color of the node
195     node.style.color = this.getCSSHexadecimalRGB();
196
197   };
198
199   /**
200    * Sets the background Color of the specified node to this Color. This
201    * functions sets the CSS 'background-color' property for the node. The
202    * parameter is:
203    *
204    * @param {DomElement} node - the node whose background Color should be set
205    */
206   this.setNodeBackgroundColor = function(node){
207
208     // set the background Color of the node
209     node.style.backgroundColor = this.getCSSHexadecimalRGB();
210
211   };
212   // convert between formats..
213   this.toRGB= function()
214   {
215     var r = this.getIntegerRGB();
216     return new Roo.lib.RGBColor(r.r,r.g,r.b,r.a);
217     
218   }
219   this.toHSL = function()
220   {
221      var hsl = this.getHSL();
222   // return the CSS HSL Color value
223     return new Roo.lib.HSLColor(hsl.h,  hsl.s, hsl.l ,  hsl.a );
224     
225   }
226   
227   this.toHSV = function()
228   {
229     var rgb = this.toRGB();
230     var hsv = rgb.getHSV();
231    // return the CSS HSL Color value
232     return new Roo.lib.HSVColor(hsv.h,  hsv.s, hsv.v ,  hsv.a );
233     
234   }
235   
236   // modify  v = 0 ... 1 (eg. 0.5)
237     this.saturate = function(v)
238     {
239         var rgb = this.toRGB();
240         var hsv = rgb.getHSV();
241         return new Roo.lib.HSVColor(hsv.h,  hsv.s * v, hsv.v ,  hsv.a );
242         
243     
244     }
245   
246    
247   
248
249 }
250
251
252 /*
253  * @class Roo.lib.RGBColor
254  * @extends Roo.lib.Color
255  * Creates a Color specified in the RGB Color space, with an optional alpha
256  * component. The parameters are:
257  *
258  * r - the red component, clipped to the range [0,255]
259  * g - the green component, clipped to the range [0,255]
260  * b - the blue component, clipped to the range [0,255]
261  * a - the alpha component, clipped to the range [0,1] - this parameter is
262  *     optional and defaults to 1
263  */
264 Roo.lib.RGBColor = function (r, g, b, a){
265
266   // store the alpha component after clipping it if necessary
267   var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
268
269   // store the RGB components after clipping them if necessary
270   var rgb =
271       {
272         'r' : Math.max(0, Math.min(255, r)),
273         'g' : Math.max(0, Math.min(255, g)),
274         'b' : Math.max(0, Math.min(255, b))
275       };
276
277   // initialise the HSV and HSL components to null
278   var hsv = null;
279   var hsl = null;
280
281   /* 
282    * //private returns the HSV or HSL hue component of this RGBColor. The hue is in the
283    * range [0,360). The parameters are:
284    *
285    * maximum - the maximum of the RGB component values
286    * range   - the range of the RGB component values
287    */
288   function getHue(maximum, range){
289
290     // check whether the range is zero
291     if (range == 0){
292
293       // set the hue to zero (any hue is acceptable as the Color is grey)
294       var hue = 0;
295
296     }else{
297
298       // determine which of the components has the highest value and set the hue
299       switch (maximum){
300
301         // red has the highest value
302         case rgb.r:
303           var hue = (rgb.g - rgb.b) / range * 60;
304           if (hue < 0) hue += 360;
305           break;
306
307         // green has the highest value
308         case rgb.g:
309           var hue = (rgb.b - rgb.r) / range * 60 + 120;
310           break;
311
312         // blue has the highest value
313         case rgb.b:
314           var hue = (rgb.r - rgb.g) / range * 60 + 240;
315           break;
316
317       }
318
319     }
320
321     // return the hue
322     return hue;
323
324   }
325
326   /* //private Calculates and stores the HSV components of this RGBColor so that they can
327    * be returned be the getHSV function.
328    */
329   function calculateHSV(){
330
331     // get the maximum and range of the RGB component values
332     var maximum = Math.max(rgb.r, rgb.g, rgb.b);
333     var range   = maximum - Math.min(rgb.r, rgb.g, rgb.b);
334
335     // store the HSV components
336     hsv =
337         {
338           'h' : getHue(maximum, range),
339           's' : (maximum == 0 ? 0 : 100 * range / maximum),
340           'v' : maximum / 2.55
341         };
342
343   }
344
345   /* //private Calculates and stores the HSL components of this RGBColor so that they can
346    * be returned be the getHSL function.
347    */
348   function calculateHSL(){
349
350     // get the maximum and range of the RGB component values
351     var maximum = Math.max(rgb.r, rgb.g, rgb.b);
352     var range   = maximum - Math.min(rgb.r, rgb.g, rgb.b);
353
354     // determine the lightness in the range [0,1]
355     var l = maximum / 255 - range / 510;
356
357     // store the HSL components
358     hsl =
359         {
360           'h' : getHue(maximum, range),
361           's' : (range == 0 ? 0 : range / 2.55 / (l < 0.5 ? l * 2 : 2 - l * 2)),
362           'l' : 100 * l
363         };
364
365   }
366
367   /**
368    * @returns the RGB and alpha components of this RGBColor as an object with r,
369    * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
370    * the range [0,1].
371    */
372   this.getRGB = function(){
373
374     // return the RGB components
375     return {
376       'r' : rgb.r,
377       'g' : rgb.g,
378       'b' : rgb.b,
379       'a' : alpha
380     };
381
382   };
383
384   /**
385    * @returns the HSV and alpha components of this RGBColor as an object with h,
386    * s, v, and a properties. h is in the range [0,360), s and v are in the range
387    * [0,100], and a is in the range [0,1].
388    */
389   this.getHSV = function(){
390
391     // calculate the HSV components if necessary
392     if (hsv == null) calculateHSV();
393
394     // return the HSV components
395     return {
396       'h' : hsv.h,
397       's' : hsv.s,
398       'v' : hsv.v,
399       'a' : alpha
400     };
401
402   };
403
404   /**
405    * @returns the HSL and alpha components of this RGBColor as an object with h,
406    * s, l, and a properties. h is in the range [0,360), s and l are in the range
407    * [0,100], and a is in the range [0,1].
408    */
409   this.getHSL = function(){
410
411     // calculate the HSV components if necessary
412     if (hsl == null) calculateHSL();
413
414     // return the HSL components
415     return {
416       'h' : hsl.h,
417       's' : hsl.s,
418       'l' : hsl.l,
419       'a' : alpha
420     };
421
422   };
423
424 }
425 // this does an 'exteds'
426 Roo.lib.RGBColor.prototype = new Roo.lib.Color();
427
428
429 /*
430  * @class Roo.lib.HSVColor
431  * @extends Roo.lib.Color
432  * Creates a Color specified in the HSV Color space, with an optional alpha
433  * component. The parameters are:
434  *
435  * h - the hue component, wrapped to the range [0,360)
436  * s - the saturation component, clipped to the range [0,100]
437  * v - the value component, clipped to the range [0,100]
438  * a - the alpha component, clipped to the range [0,1] - this parameter is
439  *     optional and defaults to 1
440  */
441 Roo.lib.HSVColor = function (h, s, v, a){
442
443   // store the alpha component after clipping it if necessary
444   var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
445
446   // store the HSV components after clipping or wrapping them if necessary
447   var hsv =
448       {
449         'h' : (h % 360 + 360) % 360,
450         's' : Math.max(0, Math.min(100, s)),
451         'v' : Math.max(0, Math.min(100, v))
452       };
453
454   // initialise the RGB and HSL components to null
455   var rgb = null;
456   var hsl = null;
457
458   /* Calculates and stores the RGB components of this HSVColor so that they can
459    * be returned be the getRGB function.
460    */
461   function calculateRGB(){
462
463     // check whether the saturation is zero
464     if (hsv.s == 0){
465
466       // set the Color to the appropriate shade of grey
467       var r = hsv.v;
468       var g = hsv.v;
469       var b = hsv.v;
470
471     }else{
472
473       // set some temporary values
474       var f  = hsv.h / 60 - Math.floor(hsv.h / 60);
475       var p  = hsv.v * (1 - hsv.s / 100);
476       var q  = hsv.v * (1 - hsv.s / 100 * f);
477       var t  = hsv.v * (1 - hsv.s / 100 * (1 - f));
478
479       // set the RGB Color components to their temporary values
480       switch (Math.floor(hsv.h / 60)){
481         case 0: var r = hsv.v; var g = t; var b = p; break;
482         case 1: var r = q; var g = hsv.v; var b = p; break;
483         case 2: var r = p; var g = hsv.v; var b = t; break;
484         case 3: var r = p; var g = q; var b = hsv.v; break;
485         case 4: var r = t; var g = p; var b = hsv.v; break;
486         case 5: var r = hsv.v; var g = p; var b = q; break;
487       }
488
489     }
490
491     // store the RGB components
492     rgb =
493         {
494           'r' : r * 2.55,
495           'g' : g * 2.55,
496           'b' : b * 2.55
497         };
498
499   }
500
501   /* Calculates and stores the HSL components of this HSVColor so that they can
502    * be returned be the getHSL function.
503    */
504   function calculateHSL(){
505
506     // determine the lightness in the range [0,100]
507     var l = (2 - hsv.s / 100) * hsv.v / 2;
508
509     // store the HSL components
510     hsl =
511         {
512           'h' : hsv.h,
513           's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
514           'l' : l
515         };
516
517     // correct a division-by-zero error
518     if (isNaN(hsl.s)) hsl.s = 0;
519
520   }
521
522   /**
523    * @returns the RGB and alpha components of this HSVColor as an object with r,
524    * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
525    * the range [0,1].
526    */
527   this.getRGB = function(){
528
529     // calculate the RGB components if necessary
530     if (rgb == null) calculateRGB();
531
532     // return the RGB components
533     return {
534       'r' : rgb.r,
535       'g' : rgb.g,
536       'b' : rgb.b,
537       'a' : alpha
538     };
539
540   };
541
542   /**
543    * @returns the HSV and alpha components of this HSVColor as an object with h,
544    * s, v, and a properties. h is in the range [0,360), s and v are in the range
545    * [0,100], and a is in the range [0,1].
546    */
547   this.getHSV = function(){
548
549     // return the HSV components
550     return {
551       'h' : hsv.h,
552       's' : hsv.s,
553       'v' : hsv.v,
554       'a' : alpha
555     };
556
557   };
558
559   /**
560    * @returns the HSL and alpha components of this HSVColor as an object with h,
561    * s, l, and a properties. h is in the range [0,360), s and l are in the range
562    * [0,100], and a is in the range [0,1].
563    */
564   this.getHSL = function(){
565
566     // calculate the HSL components if necessary
567     if (hsl == null) calculateHSL();
568
569     // return the HSL components
570     return {
571       'h' : hsl.h,
572       's' : hsl.s,
573       'l' : hsl.l,
574       'a' : alpha
575     };
576
577   };
578
579 }
580 Roo.lib.HSVColor.prototype = new Roo.lib.Color();
581
582
583 /**
584  * @class Roo.lib.HSLColor
585  * @extends Roo.lib.Color
586  * 
587  * Creates a Color specified in the HSL Color space, with an optional alpha
588  * component. The parameters are:
589  *
590  * h - the hue component, wrapped to the range [0,360)
591  * s - the saturation component, clipped to the range [0,100]
592  * l - the lightness component, clipped to the range [0,100]
593  * a - the alpha component, clipped to the range [0,1] - this parameter is
594  *     optional and defaults to 1
595  */
596
597 Roo.lib.HSLColor = function(h, s, l, a){
598
599   // store the alpha component after clipping it if necessary
600   var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
601
602   // store the HSL components after clipping or wrapping them if necessary
603   var hsl =
604       {
605         'h' : (h % 360 + 360) % 360,
606         's' : Math.max(0, Math.min(100, s)),
607         'l' : Math.max(0, Math.min(100, l))
608       };
609
610   // initialise the RGB and HSV components to null
611   var rgb = null;
612   var hsv = null;
613
614   /* Calculates and stores the RGB components of this HSLColor so that they can
615    * be returned be the getRGB function.
616    */
617   function calculateRGB(){
618
619     // check whether the saturation is zero
620     if (hsl.s == 0){
621
622       // store the RGB components representing the appropriate shade of grey
623       rgb =
624           {
625             'r' : hsl.l * 2.55,
626             'g' : hsl.l * 2.55,
627             'b' : hsl.l * 2.55
628           };
629
630     }else{
631
632       // set some temporary values
633       var p = hsl.l < 50
634             ? hsl.l * (1 + hsl.s / 100)
635             : hsl.l + hsl.s - hsl.l * hsl.s / 100;
636       var q = 2 * hsl.l - p;
637
638       // initialise the RGB components
639       rgb =
640           {
641             'r' : (h + 120) / 60 % 6,
642             'g' : h / 60,
643             'b' : (h + 240) / 60 % 6
644           };
645
646       // loop over the RGB components
647       for (var key in rgb){
648
649         // ensure that the property is not inherited from the root object
650         if (rgb.hasOwnProperty(key)){
651
652           // set the component to its value in the range [0,100]
653           if (rgb[key] < 1){
654             rgb[key] = q + (p - q) * rgb[key];
655           }else if (rgb[key] < 3){
656             rgb[key] = p;
657           }else if (rgb[key] < 4){
658             rgb[key] = q + (p - q) * (4 - rgb[key]);
659           }else{
660             rgb[key] = q;
661           }
662
663           // set the component to its value in the range [0,255]
664           rgb[key] *= 2.55;
665
666         }
667
668       }
669
670     }
671
672   }
673
674   /* Calculates and stores the HSV components of this HSLColor so that they can
675    * be returned be the getHSL function.
676    */
677   function calculateHSV(){
678
679     // set a temporary value
680     var t = hsl.s * (hsl.l < 50 ? hsl.l : 100 - hsl.l) / 100;
681
682     // store the HSV components
683     hsv =
684         {
685           'h' : hsl.h,
686           's' : 200 * t / (hsl.l + t),
687           'v' : t + hsl.l
688         };
689
690     // correct a division-by-zero error
691     if (isNaN(hsv.s)) hsv.s = 0;
692
693   }
694
695   /**
696    * @returns the RGB and alpha components of this HSLColor as an object with r,
697    * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
698    * the range [0,1].
699    */
700   this.getRGB = function(){
701
702     // calculate the RGB components if necessary
703     if (rgb == null) calculateRGB();
704
705     // return the RGB components
706     return {
707       'r' : rgb.r,
708       'g' : rgb.g,
709       'b' : rgb.b,
710       'a' : alpha
711     };
712
713   };
714
715   /**
716    * @returns the HSV and alpha components of this HSLColor as an object with h,
717    * s, v, and a properties. h is in the range [0,360), s and v are in the range
718    * [0,100], and a is in the range [0,1].
719    */
720   this.getHSV = function(){
721
722     // calculate the HSV components if necessary
723     if (hsv == null) calculateHSV();
724
725     // return the HSV components
726     return {
727       'h' : hsv.h,
728       's' : hsv.s,
729       'v' : hsv.v,
730       'a' : alpha
731     };
732
733   };
734
735   /**
736    * @returns the HSL and alpha components of this HSLColor as an object with h,
737    * s, l, and a properties. h is in the range [0,360), s and l are in the range
738    * [0,100], and a is in the range [0,1].
739    */
740   this.getHSL = function(){
741
742     // return the HSL components
743     return {
744       'h' : hsl.h,
745       's' : hsl.s,
746       'l' : hsl.l,
747       'a' : alpha
748     };
749
750   };
751
752 }
753 Roo.lib.HSLColor.prototype = new Roo.lib.Color();