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    * @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   /* 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   /* 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 /* Creates a Color specified in the HSV Color space, with an optional alpha
430  * component. The parameters are:
431  *
432  * h - the hue component, wrapped to the range [0,360)
433  * s - the saturation component, clipped to the range [0,100]
434  * v - the value component, clipped to the range [0,100]
435  * a - the alpha component, clipped to the range [0,1] - this parameter is
436  *     optional and defaults to 1
437  */
438 Roo.lib.HSVColor = function (h, s, v, a){
439
440   // store the alpha component after clipping it if necessary
441   var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
442
443   // store the HSV components after clipping or wrapping them if necessary
444   var hsv =
445       {
446         'h' : (h % 360 + 360) % 360,
447         's' : Math.max(0, Math.min(100, s)),
448         'v' : Math.max(0, Math.min(100, v))
449       };
450
451   // initialise the RGB and HSL components to null
452   var rgb = null;
453   var hsl = null;
454
455   /* Calculates and stores the RGB components of this HSVColor so that they can
456    * be returned be the getRGB function.
457    */
458   function calculateRGB(){
459
460     // check whether the saturation is zero
461     if (hsv.s == 0){
462
463       // set the Color to the appropriate shade of grey
464       var r = hsv.v;
465       var g = hsv.v;
466       var b = hsv.v;
467
468     }else{
469
470       // set some temporary values
471       var f  = hsv.h / 60 - Math.floor(hsv.h / 60);
472       var p  = hsv.v * (1 - hsv.s / 100);
473       var q  = hsv.v * (1 - hsv.s / 100 * f);
474       var t  = hsv.v * (1 - hsv.s / 100 * (1 - f));
475
476       // set the RGB Color components to their temporary values
477       switch (Math.floor(hsv.h / 60)){
478         case 0: var r = hsv.v; var g = t; var b = p; break;
479         case 1: var r = q; var g = hsv.v; var b = p; break;
480         case 2: var r = p; var g = hsv.v; var b = t; break;
481         case 3: var r = p; var g = q; var b = hsv.v; break;
482         case 4: var r = t; var g = p; var b = hsv.v; break;
483         case 5: var r = hsv.v; var g = p; var b = q; break;
484       }
485
486     }
487
488     // store the RGB components
489     rgb =
490         {
491           'r' : r * 2.55,
492           'g' : g * 2.55,
493           'b' : b * 2.55
494         };
495
496   }
497
498   /* Calculates and stores the HSL components of this HSVColor so that they can
499    * be returned be the getHSL function.
500    */
501   function calculateHSL(){
502
503     // determine the lightness in the range [0,100]
504     var l = (2 - hsv.s / 100) * hsv.v / 2;
505
506     // store the HSL components
507     hsl =
508         {
509           'h' : hsv.h,
510           's' : hsv.s * hsv.v / (l < 50 ? l * 2 : 200 - l * 2),
511           'l' : l
512         };
513
514     // correct a division-by-zero error
515     if (isNaN(hsl.s)) hsl.s = 0;
516
517   }
518
519   /**
520    * @returns the RGB and alpha components of this HSVColor as an object with r,
521    * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
522    * the range [0,1].
523    */
524   this.getRGB = function(){
525
526     // calculate the RGB components if necessary
527     if (rgb == null) calculateRGB();
528
529     // return the RGB components
530     return {
531       'r' : rgb.r,
532       'g' : rgb.g,
533       'b' : rgb.b,
534       'a' : alpha
535     };
536
537   };
538
539   /**
540    * @returns the HSV and alpha components of this HSVColor as an object with h,
541    * s, v, and a properties. h is in the range [0,360), s and v are in the range
542    * [0,100], and a is in the range [0,1].
543    */
544   this.getHSV = function(){
545
546     // return the HSV components
547     return {
548       'h' : hsv.h,
549       's' : hsv.s,
550       'v' : hsv.v,
551       'a' : alpha
552     };
553
554   };
555
556   /**
557    * @returns the HSL and alpha components of this HSVColor as an object with h,
558    * s, l, and a properties. h is in the range [0,360), s and l are in the range
559    * [0,100], and a is in the range [0,1].
560    */
561   this.getHSL = function(){
562
563     // calculate the HSL components if necessary
564     if (hsl == null) calculateHSL();
565
566     // return the HSL components
567     return {
568       'h' : hsl.h,
569       's' : hsl.s,
570       'l' : hsl.l,
571       'a' : alpha
572     };
573
574   };
575
576 }
577 Roo.lib.HSVColor.prototype = new Roo.lib.Color();
578
579
580 /* Creates a Color specified in the HSL Color space, with an optional alpha
581  * component. The parameters are:
582  *
583  * h - the hue component, wrapped to the range [0,360)
584  * s - the saturation component, clipped to the range [0,100]
585  * l - the lightness component, clipped to the range [0,100]
586  * a - the alpha component, clipped to the range [0,1] - this parameter is
587  *     optional and defaults to 1
588  */
589
590 Roo.lib.HSLColor = function(h, s, l, a){
591
592   // store the alpha component after clipping it if necessary
593   var alpha = (a === undefined ? 1 : Math.max(0, Math.min(1, a)));
594
595   // store the HSL components after clipping or wrapping them if necessary
596   var hsl =
597       {
598         'h' : (h % 360 + 360) % 360,
599         's' : Math.max(0, Math.min(100, s)),
600         'l' : Math.max(0, Math.min(100, l))
601       };
602
603   // initialise the RGB and HSV components to null
604   var rgb = null;
605   var hsv = null;
606
607   /* Calculates and stores the RGB components of this HSLColor so that they can
608    * be returned be the getRGB function.
609    */
610   function calculateRGB(){
611
612     // check whether the saturation is zero
613     if (hsl.s == 0){
614
615       // store the RGB components representing the appropriate shade of grey
616       rgb =
617           {
618             'r' : hsl.l * 2.55,
619             'g' : hsl.l * 2.55,
620             'b' : hsl.l * 2.55
621           };
622
623     }else{
624
625       // set some temporary values
626       var p = hsl.l < 50
627             ? hsl.l * (1 + hsl.s / 100)
628             : hsl.l + hsl.s - hsl.l * hsl.s / 100;
629       var q = 2 * hsl.l - p;
630
631       // initialise the RGB components
632       rgb =
633           {
634             'r' : (h + 120) / 60 % 6,
635             'g' : h / 60,
636             'b' : (h + 240) / 60 % 6
637           };
638
639       // loop over the RGB components
640       for (var key in rgb){
641
642         // ensure that the property is not inherited from the root object
643         if (rgb.hasOwnProperty(key)){
644
645           // set the component to its value in the range [0,100]
646           if (rgb[key] < 1){
647             rgb[key] = q + (p - q) * rgb[key];
648           }else if (rgb[key] < 3){
649             rgb[key] = p;
650           }else if (rgb[key] < 4){
651             rgb[key] = q + (p - q) * (4 - rgb[key]);
652           }else{
653             rgb[key] = q;
654           }
655
656           // set the component to its value in the range [0,255]
657           rgb[key] *= 2.55;
658
659         }
660
661       }
662
663     }
664
665   }
666
667   /* Calculates and stores the HSV components of this HSLColor so that they can
668    * be returned be the getHSL function.
669    */
670   function calculateHSV(){
671
672     // set a temporary value
673     var t = hsl.s * (hsl.l < 50 ? hsl.l : 100 - hsl.l) / 100;
674
675     // store the HSV components
676     hsv =
677         {
678           'h' : hsl.h,
679           's' : 200 * t / (hsl.l + t),
680           'v' : t + hsl.l
681         };
682
683     // correct a division-by-zero error
684     if (isNaN(hsv.s)) hsv.s = 0;
685
686   }
687
688   /**
689    * @returns the RGB and alpha components of this HSLColor as an object with r,
690    * g, b, and a properties. r, g, and b are in the range [0,255] and a is in
691    * the range [0,1].
692    */
693   this.getRGB = function(){
694
695     // calculate the RGB components if necessary
696     if (rgb == null) calculateRGB();
697
698     // return the RGB components
699     return {
700       'r' : rgb.r,
701       'g' : rgb.g,
702       'b' : rgb.b,
703       'a' : alpha
704     };
705
706   };
707
708   /**
709    * @returns the HSV and alpha components of this HSLColor as an object with h,
710    * s, v, and a properties. h is in the range [0,360), s and v are in the range
711    * [0,100], and a is in the range [0,1].
712    */
713   this.getHSV = function(){
714
715     // calculate the HSV components if necessary
716     if (hsv == null) calculateHSV();
717
718     // return the HSV components
719     return {
720       'h' : hsv.h,
721       's' : hsv.s,
722       'v' : hsv.v,
723       'a' : alpha
724     };
725
726   };
727
728   /**
729    * @returns the HSL and alpha components of this HSLColor as an object with h,
730    * s, l, and a properties. h is in the range [0,360), s and l are in the range
731    * [0,100], and a is in the range [0,1].
732    */
733   this.getHSL = function(){
734
735     // return the HSL components
736     return {
737       'h' : hsl.h,
738       's' : hsl.s,
739       'l' : hsl.l,
740       'a' : alpha
741     };
742
743   };
744
745 }
746 Roo.lib.HSLColor.prototype = new Roo.lib.Color();