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