1 /*global one*/
  2 one.include('js:one/color.js');
  3 
  4 one.include('js:one/color-installColorSpace.js');
  5 one.include('js:one/color/RGB.js');
  6 
  7 /**
  8  * @name one.color.HSV
  9  * @class
 10  * <p>A color in the HSV colorspace, with an optional alpha value.</p>
 11  * <p>one.color.(RGB|HSL|HSV|CMYK) objects are designed to be
 12  * immutable; all the conversion, set, and adjust methods return new
 13  * objects.</p>
 14  * <p>one.color.(RGB|HSL|HSV|CMYK) objects automatically get the set
 15  * and adjust methods from all other installed colorspaces, so
 16  * although you can use the explicit conversion methods ({@link
 17  * one.color.HSV#toRGB}, {@link one.color.HSV#toHSL}...), the below
 18  * will work just fine:</p><pre><code>
 19 one.include('jslib:one/color/HSV.js');
 20 one.include('jslib:one/color/RGB.js');
 21 one.include('jslib:one/color/CMYK.js');
 22 
 23 new one.color.HSV(.9, .2, .4).
 24     adjustBlue(-.4). // Implicit conversion to RGB
 25     setCyan(-.1). // Implicit conversion to CMYK
 26     toHex(); // "#665200"
 27 </code></pre>
 28  *
 29  * @constructor
 30  * Create a new one.color.HSV object. Component values outside the
 31  * supported range, [0..1], will be adjusted automatically.
 32  * @param {Number} h The hue component, range: [0..1]
 33  * @param {Number} s The saturation component, range: [0..1]
 34  * @param {Number} v The value component, range: [0..1]
 35  * @param {Number} [a] The alpha value, range: [0..1],
 36  * defaults to 1
 37  */
 38 
 39 /**
 40  * @name one.color.HSV.prototype.h
 41  * @property
 42  * @type Number
 43  * @description The hue component, range: [0..1]
 44  */
 45 
 46 /**
 47  * @name one.color.HSV.prototype.s
 48  * @property
 49  * @type Number
 50  * @description The saturation component, range: [0..1]
 51  */
 52 
 53 /**
 54  * @name one.color.HSV.prototype.v
 55  * @property
 56  * @type Number
 57  * @description The value component, range: [0..1]
 58  */
 59 
 60 /**
 61  * @name one.color.HSV.prototype.a
 62  * @property
 63  * @type Number
 64  * @description The alpha value, range: [0..1]
 65  */
 66 
 67 /**
 68  * @name one.color.HSV.prototype.setHue
 69  * @function
 70  * @param {Number} h The new hue component, range: [0..1]
 71  * @return {one.color.HSV} New color object with the changed value.
 72  */
 73 
 74 /**
 75  * @name one.color.HSV.prototype.setSaturation
 76  * @function
 77  * @param {Number} s The new saturation component, range: [0..1]
 78  * @return {one.color.HSV} New color object with the changed value.
 79  */
 80 
 81 /**
 82  * @name one.color.HSV.prototype.setValue
 83  * @function
 84  * @param {Number} l The new value component, range: [0..1]
 85  * @return {one.color.HSV} New color object with the changed value.
 86  */
 87 
 88 /**
 89  * @name one.color.HSV.prototype.setAlpha
 90  * @function
 91  * @param {Number} a The new alpha value, range: [0..1]
 92  * @return {one.color.HSV} New color object with the changed value.
 93  */
 94 
 95 /**
 96  * @name one.color.HSV.prototype.adjustHue
 97  * @function
 98  * @param {Number} h The value to add to the hue component. If the resulting
 99  * value falls outside the supported range, [0..1], it will be
100  * adjusted automatically.
101  * @return {one.color.HSV} New color object with the changed value.
102  */
103 
104 /**
105  * @name one.color.HSV.prototype.adjustSaturation
106  * @function
107  * @param {Number} s The value to add to the saturation component. If the
108  * resulting value falls outside the supported range, [0..1], it will
109  * be adjusted automatically.
110  * @return {one.color.HSV} New color object with the changed value.
111  */
112 
113 /**
114  * @name one.color.HSV.prototype.adjustValue
115  * @function
116  * @param {Number} v The value to add to the value component. If the resulting
117  * value falls outside the supported range, [0..1], it will be
118  * adjusted automatically.
119  * @return {one.color.HSV} New color object with the changed value.
120  */
121 
122 /**
123  * @name one.color.HSV.prototype.adjustAlpha
124  * @function
125  * @param {Number} a The value to add to the alpha value. If the resulting
126  * value falls outside the supported range, [0..1], it will be
127  * adjusted automatically.
128  * @return {one.color.HSV} New color object with the changed value.
129  */
130 
131 /**
132  * @name one.color.HSV.prototype.toJSON
133  * @description Convert the color to a JSON representation.
134  * @function
135  * @return {Array}
136  */
137 
138 /**
139  * @name one.color.HSV.prototype.toRGB
140  * @description Convert the color to a {@link one.color.RGB} object.
141  * @function
142  * @return {one.color.RGB}
143  */
144 
145 /**
146  * @name one.color.HSV.prototype.toHSV
147  * @description Convert the color to a {@link one.color.HSV} object, ie. return the object itself.
148  * @function
149  * @return {one.color.HSV}
150  */
151 
152 /**
153  * @name one.color.HSV.prototype.toHSL
154  * @description Convert the color to a {@link one.color.HSL} object.
155  * @function
156  * @requires one.color.HSL
157  * @return {one.color.HSL}
158  */
159 
160 /**
161  * @name one.color.HSV.prototype.toCMYK
162  * @description Convert the color to a {@link one.color.CMYK} object.
163  * @function
164  * @include one.color.CMYK
165  * @return {one.color.CMYK}
166  */
167 
168 /**
169  * @name one.color.HSV.prototype.toHex
170  * @description Get the standard RGB hex representation of the color.
171  * @function
172  * @return {String} The hex string, e.g. "#f681df"
173  */
174 
175 /**
176  * @name one.color.HSV.prototype.toCSS
177  * @description Get a valid CSS color representation of the color without an alpha value.
178  * @function
179  * @return {String} The CSS color string, e.g. "rgb(123, 2, 202)"
180  */
181 
182 /**
183  * @name one.color.HSV.prototype.toCSSWithAlpha
184  * @description Get a valid CSS color representation of the color, including the alpha value.
185  * @function
186  * @return {String} The CSS color string, e.g. "rgba(123, 2, 202, 0.253)"
187  */
188 one.color.installColorSpace('HSV', ['Hue', 'Saturation', 'Value', 'Alpha'], {
189     toRGB: function () {
190         var r, g, b,
191             i = Math.min(5, Math.floor(this.h * 6)),
192             f = this.h * 6 - i,
193             p = this.v * (1 - this.s),
194             q = this.v * (1 - f * this.s),
195             t = this.v * (1 - (1 - f) * this.s);
196         switch (i) {
197         case 0:
198             r = this.v;
199             g = t;
200             b = p;
201             break;
202         case 1:
203             r = q;
204             g = this.v;
205             b = p;
206             break;
207         case 2:
208             r = p;
209             g = this.v;
210             b = t;
211             break;
212         case 3:
213             r = p;
214             g = q;
215             b = this.v;
216             break;
217         case 4:
218             r = t;
219             g = p;
220             b = this.v;
221             break;
222         case 5:
223             r = this.v;
224             g = p;
225             b = q;
226             break;
227         }
228         return new one.color.RGB(r, g, b, this.a);
229     },
230 
231     toHSL: function () {
232         // Algorithm adapted from http://wiki.secondlife.com/wiki/Color_conversion_scripts
233         var s = this.s * this.v,
234             l = (2 - this.s) * this.v;
235         return new one.color.HSL(this.h, s / (l <= 1 ? l : (2 - l)), l / 2, this.a);
236     },
237 
238     fromRGB: function () { // Becomes one.color.RGB.prototype.toHSV
239         var max = Math.max(this.r, this.g, this.b),
240             min = Math.min(this.r, this.g, this.b),
241             delta = max - min,
242             h,
243             s = (max === 0) ? 0 : (delta / max),
244             v = max;
245         if (delta === 0) {
246             h = 0;
247         } else {
248             switch (max) {
249             case this.r:
250                 h = (this.g - this.b) / delta / 6 + (this.g < this.b ? 1 : 0);
251                 break;
252             case this.g:
253                 h = (this.b - this.r) / delta / 6 + 1 / 3;
254                 break;
255             case this.b:
256                 h = (this.r - this.g) / delta / 6 + 2 / 3;
257                 break;
258             }
259         }
260         return new one.color.HSV(h, s, v, this.a);
261     }
262 });
263