|
1 /** |
|
2 * Color.js |
|
3 * |
|
4 * Copyright, Moxiecode Systems AB |
|
5 * Released under LGPL License. |
|
6 * |
|
7 * License: http://www.tinymce.com/license |
|
8 * Contributing: http://www.tinymce.com/contributing |
|
9 */ |
|
10 |
|
11 /** |
|
12 * This class lets you parse/serialize colors and convert rgb/hsb. |
|
13 * |
|
14 * @class tinymce.util.Color |
|
15 * @example |
|
16 * var white = new tinymce.util.Color({r: 255, g: 255, b: 255}); |
|
17 * var red = new tinymce.util.Color('#FF0000'); |
|
18 * |
|
19 * console.log(white.toHex(), red.toHsv()); |
|
20 */ |
|
21 define("tinymce/util/Color", [], function() { |
|
22 var min = Math.min, max = Math.max, round = Math.round; |
|
23 |
|
24 /** |
|
25 * Constructs a new color instance. |
|
26 * |
|
27 * @constructor |
|
28 * @method Color |
|
29 * @param {String} value Optional initial value to parse. |
|
30 */ |
|
31 function Color(value) { |
|
32 var self = this, r = 0, g = 0, b = 0; |
|
33 |
|
34 function rgb2hsv(r, g, b) { |
|
35 var h, s, v, d, minRGB, maxRGB; |
|
36 |
|
37 h = 0; |
|
38 s = 0; |
|
39 v = 0; |
|
40 r = r / 255; |
|
41 g = g / 255; |
|
42 b = b / 255; |
|
43 |
|
44 minRGB = min(r, min(g, b)); |
|
45 maxRGB = max(r, max(g, b)); |
|
46 |
|
47 if (minRGB == maxRGB) { |
|
48 v = minRGB; |
|
49 |
|
50 return { |
|
51 h: 0, |
|
52 s: 0, |
|
53 v: v * 100 |
|
54 }; |
|
55 } |
|
56 |
|
57 /*eslint no-nested-ternary:0 */ |
|
58 d = (r == minRGB) ? g - b : ((b == minRGB) ? r - g : b - r); |
|
59 h = (r == minRGB) ? 3 : ((b == minRGB) ? 1 : 5); |
|
60 h = 60 * (h - d / (maxRGB - minRGB)); |
|
61 s = (maxRGB - minRGB) / maxRGB; |
|
62 v = maxRGB; |
|
63 |
|
64 return { |
|
65 h: round(h), |
|
66 s: round(s * 100), |
|
67 v: round(v * 100) |
|
68 }; |
|
69 } |
|
70 |
|
71 function hsvToRgb(hue, saturation, brightness) { |
|
72 var side, chroma, x, match; |
|
73 |
|
74 hue = (parseInt(hue, 10) || 0) % 360; |
|
75 saturation = parseInt(saturation, 10) / 100; |
|
76 brightness = parseInt(brightness, 10) / 100; |
|
77 saturation = max(0, min(saturation, 1)); |
|
78 brightness = max(0, min(brightness, 1)); |
|
79 |
|
80 if (saturation === 0) { |
|
81 r = g = b = round(255 * brightness); |
|
82 return; |
|
83 } |
|
84 |
|
85 side = hue / 60; |
|
86 chroma = brightness * saturation; |
|
87 x = chroma * (1 - Math.abs(side % 2 - 1)); |
|
88 match = brightness - chroma; |
|
89 |
|
90 switch (Math.floor(side)) { |
|
91 case 0: |
|
92 r = chroma; |
|
93 g = x; |
|
94 b = 0; |
|
95 break; |
|
96 |
|
97 case 1: |
|
98 r = x; |
|
99 g = chroma; |
|
100 b = 0; |
|
101 break; |
|
102 |
|
103 case 2: |
|
104 r = 0; |
|
105 g = chroma; |
|
106 b = x; |
|
107 break; |
|
108 |
|
109 case 3: |
|
110 r = 0; |
|
111 g = x; |
|
112 b = chroma; |
|
113 break; |
|
114 |
|
115 case 4: |
|
116 r = x; |
|
117 g = 0; |
|
118 b = chroma; |
|
119 break; |
|
120 |
|
121 case 5: |
|
122 r = chroma; |
|
123 g = 0; |
|
124 b = x; |
|
125 break; |
|
126 |
|
127 default: |
|
128 r = g = b = 0; |
|
129 } |
|
130 |
|
131 r = round(255 * (r + match)); |
|
132 g = round(255 * (g + match)); |
|
133 b = round(255 * (b + match)); |
|
134 } |
|
135 |
|
136 /** |
|
137 * Returns the hex string of the current color. For example: #ff00ff |
|
138 * |
|
139 * @method toHex |
|
140 * @return {String} Hex string of current color. |
|
141 */ |
|
142 function toHex() { |
|
143 function hex(val) { |
|
144 val = parseInt(val, 10).toString(16); |
|
145 |
|
146 return val.length > 1 ? val : '0' + val; |
|
147 } |
|
148 |
|
149 return '#' + hex(r) + hex(g) + hex(b); |
|
150 } |
|
151 |
|
152 /** |
|
153 * Returns the r, g, b values of the color. Each channel has a range from 0-255. |
|
154 * |
|
155 * @method toRgb |
|
156 * @return {Object} Object with r, g, b fields. |
|
157 */ |
|
158 function toRgb() { |
|
159 return { |
|
160 r: r, |
|
161 g: g, |
|
162 b: b |
|
163 }; |
|
164 } |
|
165 |
|
166 /** |
|
167 * Returns the h, s, v values of the color. Ranges: h=0-360, s=0-100, v=0-100. |
|
168 * |
|
169 * @method toHsv |
|
170 * @return {Object} Object with h, s, v fields. |
|
171 */ |
|
172 function toHsv() { |
|
173 return rgb2hsv(r, g, b); |
|
174 } |
|
175 |
|
176 /** |
|
177 * Parses the specified value and populates the color instance. |
|
178 * |
|
179 * Supported format examples: |
|
180 * * rbg(255,0,0) |
|
181 * * #ff0000 |
|
182 * * #fff |
|
183 * * {r: 255, g: 0, b: 0} |
|
184 * * {h: 360, s: 100, v: 100} |
|
185 * |
|
186 * @method parse |
|
187 * @param {Object/String} value Color value to parse. |
|
188 * @return {tinymce.util.Color} Current color instance. |
|
189 */ |
|
190 function parse(value) { |
|
191 var matches; |
|
192 |
|
193 if (typeof value == 'object') { |
|
194 if ("r" in value) { |
|
195 r = value.r; |
|
196 g = value.g; |
|
197 b = value.b; |
|
198 } else if ("v" in value) { |
|
199 hsvToRgb(value.h, value.s, value.v); |
|
200 } |
|
201 } else { |
|
202 if ((matches = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(value))) { |
|
203 r = parseInt(matches[1], 10); |
|
204 g = parseInt(matches[2], 10); |
|
205 b = parseInt(matches[3], 10); |
|
206 } else if ((matches = /#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(value))) { |
|
207 r = parseInt(matches[1], 16); |
|
208 g = parseInt(matches[2], 16); |
|
209 b = parseInt(matches[3], 16); |
|
210 } else if ((matches = /#([0-F])([0-F])([0-F])/gi.exec(value))) { |
|
211 r = parseInt(matches[1] + matches[1], 16); |
|
212 g = parseInt(matches[2] + matches[2], 16); |
|
213 b = parseInt(matches[3] + matches[3], 16); |
|
214 } |
|
215 } |
|
216 |
|
217 r = r < 0 ? 0 : (r > 255 ? 255 : r); |
|
218 g = g < 0 ? 0 : (g > 255 ? 255 : g); |
|
219 b = b < 0 ? 0 : (b > 255 ? 255 : b); |
|
220 |
|
221 return self; |
|
222 } |
|
223 |
|
224 if (value) { |
|
225 parse(value); |
|
226 } |
|
227 |
|
228 self.toRgb = toRgb; |
|
229 self.toHsv = toHsv; |
|
230 self.toHex = toHex; |
|
231 self.parse = parse; |
|
232 } |
|
233 |
|
234 return Color; |
|
235 }); |