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