PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
← All changes | _inc/lib/class.color.php +763 -759 13.5.216.3-a.1 View file →
@@ -15,886 +15,890 @@
15 15 */
16 16
17 17 // phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
18 18
19 -/**
20 - * Color utilities
21 - */
22 -class Jetpack_Color {
19 +if ( ! class_exists( 'Jetpack_Color' ) ) {
23 20 /**
24 - * Color code (later array or string, depending on type)
25 - *
26 - * @var int|array|string
21 + * Color utilities
27 22 */
28 - protected $color = 0;
23 + class Jetpack_Color {
24 + /**
25 + * Color code (later array or string, depending on type)
26 + *
27 + * @var int|array|string
28 + */
29 + protected $color = 0;
29 30
30 - /**
31 - * Initialize object
32 - *
33 - * @param string|array $color A color of the type $type.
34 - * @param string $type The type of color we will construct from.
35 - * One of hex (default), rgb, hsl, int.
36 - */
37 - public function __construct( $color = null, $type = 'hex' ) {
38 - if ( $color ) {
39 - switch ( $type ) {
40 - case 'hex':
41 - $this->fromHex( $color );
42 - break;
43 - case 'rgb':
44 - if ( is_array( $color ) && count( $color ) === 3 ) {
45 - list( $r, $g, $b ) = array_values( $color );
46 - $this->fromRgbInt( $r, $g, $b );
47 - }
48 - break;
49 - case 'hsl':
50 - if ( is_array( $color ) && count( $color ) === 3 ) {
51 - list( $h, $s, $l ) = array_values( $color );
52 - $this->fromHsl( $h, $s, $l );
53 - }
54 - break;
55 - case 'int':
56 - $this->fromInt( $color );
57 - break;
58 - default:
59 - // there is no default.
60 - break;
31 + /**
32 + * Initialize object
33 + *
34 + * @param string|array $color A color of the type $type.
35 + * @param string $type The type of color we will construct from.
36 + * One of hex (default), rgb, hsl, int.
37 + */
38 + public function __construct( $color = null, $type = 'hex' ) {
39 + _deprecated_function( 'Jetpack_Color::__construct', 'jetpack-13.8' );
40 +
41 + if ( $color ) {
42 + switch ( $type ) {
43 + case 'hex':
44 + $this->fromHex( $color );
45 + break;
46 + case 'rgb':
47 + if ( is_array( $color ) && count( $color ) === 3 ) {
48 + list( $r, $g, $b ) = array_values( $color );
49 + $this->fromRgbInt( $r, $g, $b );
50 + }
51 + break;
52 + case 'hsl':
53 + if ( is_array( $color ) && count( $color ) === 3 ) {
54 + list( $h, $s, $l ) = array_values( $color );
55 + $this->fromHsl( $h, $s, $l );
56 + }
57 + break;
58 + case 'int':
59 + $this->fromInt( $color );
60 + break;
61 + default:
62 + // there is no default.
63 + break;
64 + }
61 65 }
62 66 }
63 - }
64 67
65 - /**
66 - * Init color from hex value
67 - *
68 - * @param string $hex_value Color hex value.
69 - *
70 - * @return $this
71 - * @throws RangeException Invalid color code range error.
72 - */
73 - public function fromHex( $hex_value ) {
74 - $hex_value = str_replace( '#', '', $hex_value );
75 - // handle short hex codes like #fff.
76 - if ( 3 === strlen( $hex_value ) ) {
77 - $hex_value = $hex_value[0] . $hex_value[0] . $hex_value[1] . $hex_value[1] . $hex_value[2] . $hex_value[2];
68 + /**
69 + * Init color from hex value
70 + *
71 + * @param string $hex_value Color hex value.
72 + *
73 + * @return $this
74 + * @throws RangeException Invalid color code range error.
75 + */
76 + public function fromHex( $hex_value ) {
77 + $hex_value = str_replace( '#', '', $hex_value );
78 + // handle short hex codes like #fff.
79 + if ( 3 === strlen( $hex_value ) ) {
80 + $hex_value = $hex_value[0] . $hex_value[0] . $hex_value[1] . $hex_value[1] . $hex_value[2] . $hex_value[2];
81 + }
82 + return $this->fromInt( hexdec( $hex_value ) );
78 83 }
79 - return $this->fromInt( hexdec( $hex_value ) );
80 - }
81 84
82 - /**
83 - * Init color from integer RGB values
84 - *
85 - * @param int $red Red color code.
86 - * @param int $green Green color code.
87 - * @param int $blue Blue color code.
88 - *
89 - * @return $this
90 - * @throws RangeException Invalid color code range error.
91 - */
92 - public function fromRgbInt( $red, $green, $blue ) {
93 - if ( $red < 0 || $red > 255 ) {
94 - throw new RangeException( 'Red value ' . $red . ' out of valid color code range' );
95 - }
85 + /**
86 + * Init color from integer RGB values
87 + *
88 + * @param int $red Red color code.
89 + * @param int $green Green color code.
90 + * @param int $blue Blue color code.
91 + *
92 + * @return $this
93 + * @throws RangeException Invalid color code range error.
94 + */
95 + public function fromRgbInt( $red, $green, $blue ) {
96 + if ( $red < 0 || $red > 255 ) {
97 + throw new RangeException( 'Red value ' . $red . ' out of valid color code range' );
98 + }
96 99
97 - if ( $green < 0 || $green > 255 ) {
98 - throw new RangeException( 'Green value ' . $green . ' out of valid color code range' );
100 + if ( $green < 0 || $green > 255 ) {
101 + throw new RangeException( 'Green value ' . $green . ' out of valid color code range' );
102 + }
103 +
104 + if ( $blue < 0 || $blue > 255 ) {
105 + throw new RangeException( 'Blue value ' . $blue . ' out of valid color code range' );
106 + }
107 +
108 + $this->color = ( intval( $red ) << 16 ) + ( intval( $green ) << 8 ) + intval( $blue );
109 +
110 + return $this;
99 111 }
100 112
101 - if ( $blue < 0 || $blue > 255 ) {
102 - throw new RangeException( 'Blue value ' . $blue . ' out of valid color code range' );
113 + /**
114 + * Init color from hex RGB values
115 + *
116 + * @param string $red Red color code.
117 + * @param string $green Green color code.
118 + * @param string $blue Blue color code.
119 + *
120 + * @return $this
121 + */
122 + public function fromRgbHex( $red, $green, $blue ) {
123 + return $this->fromRgbInt( hexdec( $red ), hexdec( $green ), hexdec( $blue ) );
103 124 }
104 125
105 - $this->color = ( intval( $red ) << 16 ) + ( intval( $green ) << 8 ) + intval( $blue );
126 + /**
127 + * Converts an HSL color value to RGB. Conversion formula
128 + * adapted from https://en.wikipedia.org/wiki/HSL_color_space.
129 + *
130 + * @param int $h Hue. [0-360].
131 + * @param int $s Saturation [0, 100].
132 + * @param int $l Lightness [0, 100].
133 + */
134 + public function fromHsl( $h, $s, $l ) {
135 + $h /= 360;
136 + $s /= 100;
137 + $l /= 100;
106 138
107 - return $this;
108 - }
139 + if ( 0 === $s ) {
140 + // achromatic.
141 + $r = $l;
142 + $g = $l;
143 + $b = $l;
144 + } else {
145 + $q = $l < 0.5 ? $l * ( 1 + $s ) : $l + $s - $l * $s;
146 + $p = 2 * $l - $q;
147 + $r = $this->hue2rgb( $p, $q, $h + 1 / 3 );
148 + $g = $this->hue2rgb( $p, $q, $h );
149 + $b = $this->hue2rgb( $p, $q, $h - 1 / 3 );
150 + }
109 151
110 - /**
111 - * Init color from hex RGB values
112 - *
113 - * @param string $red Red color code.
114 - * @param string $green Green color code.
115 - * @param string $blue Blue color code.
116 - *
117 - * @return $this
118 - */
119 - public function fromRgbHex( $red, $green, $blue ) {
120 - return $this->fromRgbInt( hexdec( $red ), hexdec( $green ), hexdec( $blue ) );
121 - }
152 + return $this->fromRgbInt( $r * 255, $g * 255, $b * 255 );
153 + }
122 154
123 - /**
124 - * Converts an HSL color value to RGB. Conversion formula
125 - * adapted from https://en.wikipedia.org/wiki/HSL_color_space.
126 - *
127 - * @param int $h Hue. [0-360].
128 - * @param int $s Saturation [0, 100].
129 - * @param int $l Lightness [0, 100].
130 - */
131 - public function fromHsl( $h, $s, $l ) {
132 - $h /= 360;
133 - $s /= 100;
134 - $l /= 100;
155 + /**
156 + * Helper function for Jetpack_Color::fromHsl()
157 + *
158 + * @param float $p Minimum of R/G/B [0, 1].
159 + * @param float $q Maximum of R/G/B [0, 1].
160 + * @param float $t Adjusted hue [0, 1].
161 + */
162 + private function hue2rgb( $p, $q, $t ) {
163 + if ( $t < 0 ) {
164 + ++$t;
165 + }
166 + if ( $t > 1 ) {
167 + --$t;
168 + }
169 + if ( $t < 1 / 6 ) {
170 + return $p + ( $q - $p ) * 6 * $t;
171 + }
172 + if ( $t < 1 / 2 ) {
173 + return $q;
174 + }
175 + if ( $t < 2 / 3 ) {
176 + return $p + ( $q - $p ) * ( 2 / 3 - $t ) * 6;
177 + }
178 + return $p;
179 + }
135 180
136 - if ( 0 === $s ) {
137 - // achromatic.
138 - $r = $l;
139 - $g = $l;
140 - $b = $l;
141 - } else {
142 - $q = $l < 0.5 ? $l * ( 1 + $s ) : $l + $s - $l * $s;
143 - $p = 2 * $l - $q;
144 - $r = $this->hue2rgb( $p, $q, $h + 1 / 3 );
145 - $g = $this->hue2rgb( $p, $q, $h );
146 - $b = $this->hue2rgb( $p, $q, $h - 1 / 3 );
147 - }
181 + /**
182 + * Init color from integer value
183 + *
184 + * @param int $int_value Color code.
185 + *
186 + * @return $this
187 + * @throws RangeException Invalid color code range error.
188 + */
189 + public function fromInt( $int_value ) {
190 + if ( $int_value < 0 || $int_value > 16777215 ) {
191 + throw new RangeException( $int_value . ' out of valid color code range' );
192 + }
148 193
149 - return $this->fromRgbInt( $r * 255, $g * 255, $b * 255 );
150 - }
194 + $this->color = $int_value;
151 195
152 - /**
153 - * Helper function for Jetpack_Color::fromHsl()
154 - *
155 - * @param float $p Minimum of R/G/B [0, 1].
156 - * @param float $q Maximum of R/G/B [0, 1].
157 - * @param float $t Adjusted hue [0, 1].
158 - */
159 - private function hue2rgb( $p, $q, $t ) {
160 - if ( $t < 0 ) {
161 - ++$t;
196 + return $this;
162 197 }
163 - if ( $t > 1 ) {
164 - --$t;
198 +
199 + /**
200 + * Convert color to hex
201 + *
202 + * @return string
203 + */
204 + public function toHex() {
205 + return sprintf( '%06x', $this->color );
165 206 }
166 - if ( $t < 1 / 6 ) {
167 - return $p + ( $q - $p ) * 6 * $t;
207 +
208 + /**
209 + * Convert color to RGB array (integer values)
210 + *
211 + * @return array
212 + */
213 + public function toRgbInt() {
214 + return array(
215 + 'red' => (int) ( 255 & ( $this->color >> 16 ) ),
216 + 'green' => (int) ( 255 & ( $this->color >> 8 ) ),
217 + 'blue' => (int) ( 255 & ( $this->color ) ),
218 + );
168 219 }
169 - if ( $t < 1 / 2 ) {
170 - return $q;
171 - }
172 - if ( $t < 2 / 3 ) {
173 - return $p + ( $q - $p ) * ( 2 / 3 - $t ) * 6;
174 - }
175 - return $p;
176 - }
177 220
178 - /**
179 - * Init color from integer value
180 - *
181 - * @param int $int_value Color code.
182 - *
183 - * @return $this
184 - * @throws RangeException Invalid color code range error.
185 - */
186 - public function fromInt( $int_value ) {
187 - if ( $int_value < 0 || $int_value > 16777215 ) {
188 - throw new RangeException( $int_value . ' out of valid color code range' );
221 + /**
222 + * Convert color to RGB array (hex values)
223 + *
224 + * @return array
225 + */
226 + public function toRgbHex() {
227 + $r = array();
228 + foreach ( $this->toRgbInt() as $item ) {
229 + $r[] = dechex( $item );
230 + }
231 + return $r;
189 232 }
190 233
191 - $this->color = $int_value;
234 + /**
235 + * Get Hue/Saturation/Value for the current color
236 + * (float values, slow but accurate)
237 + *
238 + * @return array
239 + */
240 + public function toHsvFloat() {
241 + $rgb = $this->toRgbInt();
192 242
193 - return $this;
194 - }
243 + $rgb_min = min( $rgb );
244 + $rgb_max = max( $rgb );
195 245
196 - /**
197 - * Convert color to hex
198 - *
199 - * @return string
200 - */
201 - public function toHex() {
202 - return sprintf( '%06x', $this->color );
203 - }
246 + $hsv = array(
247 + 'hue' => 0,
248 + 'sat' => 0,
249 + 'val' => $rgb_max,
250 + );
204 251
205 - /**
206 - * Convert color to RGB array (integer values)
207 - *
208 - * @return array
209 - */
210 - public function toRgbInt() {
211 - return array(
212 - 'red' => (int) ( 255 & ( $this->color >> 16 ) ),
213 - 'green' => (int) ( 255 & ( $this->color >> 8 ) ),
214 - 'blue' => (int) ( 255 & ( $this->color ) ),
215 - );
216 - }
252 + // If v is 0, color is black.
253 + if ( 0 === $hsv['val'] ) {
254 + return $hsv;
255 + }
217 256
218 - /**
219 - * Convert color to RGB array (hex values)
220 - *
221 - * @return array
222 - */
223 - public function toRgbHex() {
224 - $r = array();
225 - foreach ( $this->toRgbInt() as $item ) {
226 - $r[] = dechex( $item );
227 - }
228 - return $r;
229 - }
257 + // Normalize RGB values to 1.
258 + $rgb['red'] /= $hsv['val'];
259 + $rgb['green'] /= $hsv['val'];
260 + $rgb['blue'] /= $hsv['val'];
261 + $rgb_min = min( $rgb );
262 + $rgb_max = max( $rgb );
230 263
231 - /**
232 - * Get Hue/Saturation/Value for the current color
233 - * (float values, slow but accurate)
234 - *
235 - * @return array
236 - */
237 - public function toHsvFloat() {
238 - $rgb = $this->toRgbInt();
264 + // Calculate saturation.
265 + $hsv['sat'] = $rgb_max - $rgb_min;
266 + if ( 0 === $hsv['sat'] ) {
267 + $hsv['hue'] = 0;
268 + return $hsv;
269 + }
239 270
240 - $rgb_min = min( $rgb );
241 - $rgb_max = max( $rgb );
271 + // Normalize saturation to 1.
272 + $rgb['red'] = ( $rgb['red'] - $rgb_min ) / ( $rgb_max - $rgb_min );
273 + $rgb['green'] = ( $rgb['green'] - $rgb_min ) / ( $rgb_max - $rgb_min );
274 + $rgb['blue'] = ( $rgb['blue'] - $rgb_min ) / ( $rgb_max - $rgb_min );
275 + $rgb_min = min( $rgb );
276 + $rgb_max = max( $rgb );
242 277
243 - $hsv = array(
244 - 'hue' => 0,
245 - 'sat' => 0,
246 - 'val' => $rgb_max,
247 - );
278 + // Calculate hue.
279 + if ( $rgb_max === $rgb['red'] ) {
280 + $hsv['hue'] = 0.0 + 60 * ( $rgb['green'] - $rgb['blue'] );
281 + if ( $hsv['hue'] < 0 ) {
282 + $hsv['hue'] += 360;
283 + }
284 + } elseif ( $rgb_max === $rgb['green'] ) {
285 + $hsv['hue'] = 120 + ( 60 * ( $rgb['blue'] - $rgb['red'] ) );
286 + } else {
287 + $hsv['hue'] = 240 + ( 60 * ( $rgb['red'] - $rgb['green'] ) );
288 + }
248 289
249 - // If v is 0, color is black.
250 - if ( 0 === $hsv['val'] ) {
251 290 return $hsv;
252 291 }
253 292
254 - // Normalize RGB values to 1.
255 - $rgb['red'] /= $hsv['val'];
256 - $rgb['green'] /= $hsv['val'];
257 - $rgb['blue'] /= $hsv['val'];
258 - $rgb_min = min( $rgb );
259 - $rgb_max = max( $rgb );
293 + /**
294 + * Get HSV values for color
295 + * (integer values from 0-255, fast but less accurate)
296 + *
297 + * @return array
298 + */
299 + public function toHsvInt() {
300 + $rgb = $this->toRgbInt();
260 301
261 - // Calculate saturation.
262 - $hsv['sat'] = $rgb_max - $rgb_min;
263 - if ( 0 === $hsv['sat'] ) {
264 - $hsv['hue'] = 0;
265 - return $hsv;
266 - }
302 + $rgb_min = min( $rgb );
303 + $rgb_max = max( $rgb );
267 304
268 - // Normalize saturation to 1.
269 - $rgb['red'] = ( $rgb['red'] - $rgb_min ) / ( $rgb_max - $rgb_min );
270 - $rgb['green'] = ( $rgb['green'] - $rgb_min ) / ( $rgb_max - $rgb_min );
271 - $rgb['blue'] = ( $rgb['blue'] - $rgb_min ) / ( $rgb_max - $rgb_min );
272 - $rgb_min = min( $rgb );
273 - $rgb_max = max( $rgb );
305 + $hsv = array(
306 + 'hue' => 0,
307 + 'sat' => 0,
308 + 'val' => $rgb_max,
309 + );
274 310
275 - // Calculate hue.
276 - if ( $rgb_max === $rgb['red'] ) {
277 - $hsv['hue'] = 0.0 + 60 * ( $rgb['green'] - $rgb['blue'] );
278 - if ( $hsv['hue'] < 0 ) {
279 - $hsv['hue'] += 360;
311 + // If value is 0, color is black.
312 + if ( 0 === $hsv['val'] ) {
313 + return $hsv;
280 314 }
281 - } elseif ( $rgb_max === $rgb['green'] ) {
282 - $hsv['hue'] = 120 + ( 60 * ( $rgb['blue'] - $rgb['red'] ) );
283 - } else {
284 - $hsv['hue'] = 240 + ( 60 * ( $rgb['red'] - $rgb['green'] ) );
285 - }
286 315
287 - return $hsv;
288 - }
316 + // Calculate saturation.
317 + $hsv['sat'] = round( 255 * ( $rgb_max - $rgb_min ) / $hsv['val'] );
318 + if ( 0 === $hsv['sat'] ) {
319 + $hsv['hue'] = 0;
320 + return $hsv;
321 + }
289 322
290 - /**
291 - * Get HSV values for color
292 - * (integer values from 0-255, fast but less accurate)
293 - *
294 - * @return array
295 - */
296 - public function toHsvInt() {
297 - $rgb = $this->toRgbInt();
323 + // Calculate hue.
324 + if ( $rgb_max === $rgb['red'] ) {
325 + $hsv['hue'] = round( 0 + 43 * ( $rgb['green'] - $rgb['blue'] ) / ( $rgb_max - $rgb_min ) );
326 + } elseif ( $rgb_max === $rgb['green'] ) {
327 + $hsv['hue'] = round( 85 + 43 * ( $rgb['blue'] - $rgb['red'] ) / ( $rgb_max - $rgb_min ) );
328 + } else {
329 + $hsv['hue'] = round( 171 + 43 * ( $rgb['red'] - $rgb['green'] ) / ( $rgb_max - $rgb_min ) );
330 + }
331 + if ( $hsv['hue'] < 0 ) {
332 + $hsv['hue'] += 255;
333 + }
298 334
299 - $rgb_min = min( $rgb );
300 - $rgb_max = max( $rgb );
301 -
302 - $hsv = array(
303 - 'hue' => 0,
304 - 'sat' => 0,
305 - 'val' => $rgb_max,
306 - );
307 -
308 - // If value is 0, color is black.
309 - if ( 0 === $hsv['val'] ) {
310 335 return $hsv;
311 336 }
312 337
313 - // Calculate saturation.
314 - $hsv['sat'] = round( 255 * ( $rgb_max - $rgb_min ) / $hsv['val'] );
315 - if ( 0 === $hsv['sat'] ) {
316 - $hsv['hue'] = 0;
317 - return $hsv;
338 + /**
339 + * Converts an RGB color value to HSL. Conversion formula
340 + * adapted from https://en.wikipedia.org/wiki/HSL_color_space.
341 + * Assumes r, g, and b are contained in the set [0, 255] and
342 + * returns h in [0, 360], s in [0, 100], l in [0, 100]
343 + *
344 + * @return Array The HSL representation
345 + */
346 + public function toHsl() {
347 + list( $r, $g, $b ) = array_values( $this->toRgbInt() );
348 + $r /= 255;
349 + $g /= 255;
350 + $b /= 255;
351 + $max = max( $r, $g, $b );
352 + $min = min( $r, $g, $b );
353 + $l = ( $max + $min ) / 2;
354 +
355 + if ( $max === $min ) {
356 + // achromatic.
357 + $s = 0;
358 + $h = 0;
359 + } else {
360 + $d = $max - $min;
361 + $s = $l > 0.5 ? $d / ( 2 - $max - $min ) : $d / ( $max + $min );
362 + switch ( $max ) {
363 + case $r:
364 + $h = ( $g - $b ) / $d + ( $g < $b ? 6 : 0 );
365 + break;
366 + case $g:
367 + $h = ( $b - $r ) / $d + 2;
368 + break;
369 + case $b:
370 + $h = ( $r - $g ) / $d + 4;
371 + break;
372 + }
373 + $h /= 6;
374 + }
375 + $h = (int) round( $h * 360 );
376 + $s = (int) round( $s * 100 );
377 + $l = (int) round( $l * 100 );
378 + return compact( 'h', 's', 'l' );
318 379 }
319 380
320 - // Calculate hue.
321 - if ( $rgb_max === $rgb['red'] ) {
322 - $hsv['hue'] = round( 0 + 43 * ( $rgb['green'] - $rgb['blue'] ) / ( $rgb_max - $rgb_min ) );
323 - } elseif ( $rgb_max === $rgb['green'] ) {
324 - $hsv['hue'] = round( 85 + 43 * ( $rgb['blue'] - $rgb['red'] ) / ( $rgb_max - $rgb_min ) );
325 - } else {
326 - $hsv['hue'] = round( 171 + 43 * ( $rgb['red'] - $rgb['green'] ) / ( $rgb_max - $rgb_min ) );
381 + /**
382 + * From a color code to a string to be used in CSS declaration.
383 + *
384 + * @param string $type Color code type.
385 + * @param int $alpha Transparency.
386 + *
387 + * @return string
388 + */
389 + public function toCSS( $type = 'hex', $alpha = 1 ) {
390 + switch ( $type ) {
391 + case 'hex':
392 + return $this->toString();
393 + case 'rgb':
394 + case 'rgba':
395 + list( $r, $g, $b ) = array_values( $this->toRgbInt() );
396 + if ( is_numeric( $alpha ) && $alpha < 1 ) {
397 + return "rgba( {$r}, {$g}, {$b}, $alpha )";
398 + } else {
399 + return "rgb( {$r}, {$g}, {$b} )";
400 + }
401 + case 'hsl':
402 + case 'hsla':
403 + list( $h, $s, $l ) = array_values( $this->toHsl() );
404 + if ( is_numeric( $alpha ) && $alpha < 1 ) {
405 + return "hsla( {$h}, {$s}, {$l}, $alpha )";
406 + } else {
407 + return "hsl( {$h}, {$s}, {$l} )";
408 + }
409 + default:
410 + return $this->toString();
411 + }
327 412 }
328 - if ( $hsv['hue'] < 0 ) {
329 - $hsv['hue'] += 255;
330 - }
331 413
332 - return $hsv;
333 - }
414 + /**
415 + * Get current color in XYZ format
416 + *
417 + * @return array
418 + */
419 + public function toXyz() {
420 + $rgb = $this->toRgbInt();
334 421
335 - /**
336 - * Converts an RGB color value to HSL. Conversion formula
337 - * adapted from https://en.wikipedia.org/wiki/HSL_color_space.
338 - * Assumes r, g, and b are contained in the set [0, 255] and
339 - * returns h in [0, 360], s in [0, 100], l in [0, 100]
340 - *
341 - * @return Array The HSL representation
342 - */
343 - public function toHsl() {
344 - list( $r, $g, $b ) = array_values( $this->toRgbInt() );
345 - $r /= 255;
346 - $g /= 255;
347 - $b /= 255;
348 - $max = max( $r, $g, $b );
349 - $min = min( $r, $g, $b );
350 - $l = ( $max + $min ) / 2;
351 -
352 - if ( $max === $min ) {
353 - // achromatic.
354 - $s = 0;
355 - $h = 0;
356 - } else {
357 - $d = $max - $min;
358 - $s = $l > 0.5 ? $d / ( 2 - $max - $min ) : $d / ( $max + $min );
359 - switch ( $max ) {
360 - case $r:
361 - $h = ( $g - $b ) / $d + ( $g < $b ? 6 : 0 );
362 - break;
363 - case $g:
364 - $h = ( $b - $r ) / $d + 2;
365 - break;
366 - case $b:
367 - $h = ( $r - $g ) / $d + 4;
368 - break;
422 + // Normalize RGB values to 1.
423 + $rgb_new = array();
424 + foreach ( $rgb as $item ) {
425 + $rgb_new[] = $item / 255;
369 426 }
370 - $h /= 6;
371 - }
372 - $h = (int) round( $h * 360 );
373 - $s = (int) round( $s * 100 );
374 - $l = (int) round( $l * 100 );
375 - return compact( 'h', 's', 'l' );
376 - }
427 + $rgb = $rgb_new;
377 428
378 - /**
379 - * From a color code to a string to be used in CSS declaration.
380 - *
381 - * @param string $type Color code type.
382 - * @param int $alpha Transparency.
383 - *
384 - * @return string
385 - */
386 - public function toCSS( $type = 'hex', $alpha = 1 ) {
387 - switch ( $type ) {
388 - case 'hex':
389 - return $this->toString();
390 - case 'rgb':
391 - case 'rgba':
392 - list( $r, $g, $b ) = array_values( $this->toRgbInt() );
393 - if ( is_numeric( $alpha ) && $alpha < 1 ) {
394 - return "rgba( {$r}, {$g}, {$b}, $alpha )";
429 + $rgb_new = array();
430 + foreach ( $rgb as $item ) {
431 + if ( $item > 0.04045 ) {
432 + $item = pow( ( ( $item + 0.055 ) / 1.055 ), 2.4 );
395 433 } else {
396 - return "rgb( {$r}, {$g}, {$b} )";
434 + $item = $item / 12.92;
397 435 }
398 - case 'hsl':
399 - case 'hsla':
400 - list( $h, $s, $l ) = array_values( $this->toHsl() );
401 - if ( is_numeric( $alpha ) && $alpha < 1 ) {
402 - return "hsla( {$h}, {$s}, {$l}, $alpha )";
403 - } else {
404 - return "hsl( {$h}, {$s}, {$l} )";
405 - }
406 - default:
407 - return $this->toString();
408 - }
409 - }
436 + $rgb_new[] = $item * 100;
437 + }
438 + $rgb = $rgb_new;
410 439
411 - /**
412 - * Get current color in XYZ format
413 - *
414 - * @return array
415 - */
416 - public function toXyz() {
417 - $rgb = $this->toRgbInt();
440 + // Observer. = 2°, Illuminant = D65.
441 + $xyz = array(
442 + 'x' => ( $rgb['red'] * 0.4124 ) + ( $rgb['green'] * 0.3576 ) + ( $rgb['blue'] * 0.1805 ),
443 + 'y' => ( $rgb['red'] * 0.2126 ) + ( $rgb['green'] * 0.7152 ) + ( $rgb['blue'] * 0.0722 ),
444 + 'z' => ( $rgb['red'] * 0.0193 ) + ( $rgb['green'] * 0.1192 ) + ( $rgb['blue'] * 0.9505 ),
445 + );
418 446
419 - // Normalize RGB values to 1.
420 - $rgb_new = array();
421 - foreach ( $rgb as $item ) {
422 - $rgb_new[] = $item / 255;
447 + return $xyz;
423 448 }
424 - $rgb = $rgb_new;
425 449
426 - $rgb_new = array();
427 - foreach ( $rgb as $item ) {
428 - if ( $item > 0.04045 ) {
429 - $item = pow( ( ( $item + 0.055 ) / 1.055 ), 2.4 );
430 - } else {
431 - $item = $item / 12.92;
432 - }
433 - $rgb_new[] = $item * 100;
434 - }
435 - $rgb = $rgb_new;
450 + /**
451 + * Get color CIE-Lab values
452 + *
453 + * @return array
454 + */
455 + public function toLabCie() {
456 + $xyz = $this->toXyz();
436 457
437 - // Observer. = 2°, Illuminant = D65.
438 - $xyz = array(
439 - 'x' => ( $rgb['red'] * 0.4124 ) + ( $rgb['green'] * 0.3576 ) + ( $rgb['blue'] * 0.1805 ),
440 - 'y' => ( $rgb['red'] * 0.2126 ) + ( $rgb['green'] * 0.7152 ) + ( $rgb['blue'] * 0.0722 ),
441 - 'z' => ( $rgb['red'] * 0.0193 ) + ( $rgb['green'] * 0.1192 ) + ( $rgb['blue'] * 0.9505 ),
442 - );
458 + // Ovserver = 2*, Iluminant=D65.
459 + $xyz['x'] /= 95.047;
460 + $xyz['y'] /= 100;
461 + $xyz['z'] /= 108.883;
443 462
444 - return $xyz;
445 - }
463 + $xyz_new = array();
464 + foreach ( $xyz as $item ) {
465 + if ( $item > 0.008856 ) {
466 + $xyz_new[] = pow( $item, 1 / 3 );
467 + } else {
468 + $xyz_new[] = ( 7.787 * $item ) + ( 16 / 116 );
469 + }
470 + }
471 + $xyz = $xyz_new;
446 472
447 - /**
448 - * Get color CIE-Lab values
449 - *
450 - * @return array
451 - */
452 - public function toLabCie() {
453 - $xyz = $this->toXyz();
473 + $lab = array(
474 + 'l' => ( 116 * $xyz['y'] ) - 16,
475 + 'a' => 500 * ( $xyz['x'] - $xyz['y'] ),
476 + 'b' => 200 * ( $xyz['y'] - $xyz['z'] ),
477 + );
454 478
455 - // Ovserver = 2*, Iluminant=D65.
456 - $xyz['x'] /= 95.047;
457 - $xyz['y'] /= 100;
458 - $xyz['z'] /= 108.883;
479 + return $lab;
480 + }
459 481
460 - $xyz_new = array();
461 - foreach ( $xyz as $item ) {
462 - if ( $item > 0.008856 ) {
463 - $xyz_new[] = pow( $item, 1 / 3 );
464 - } else {
465 - $xyz_new[] = ( 7.787 * $item ) + ( 16 / 116 );
466 - }
482 + /**
483 + * Convert color to integer
484 + *
485 + * @return int
486 + */
487 + public function toInt() {
488 + return $this->color;
467 489 }
468 - $xyz = $xyz_new;
469 490
470 - $lab = array(
471 - 'l' => ( 116 * $xyz['y'] ) - 16,
472 - 'a' => 500 * ( $xyz['x'] - $xyz['y'] ),
473 - 'b' => 200 * ( $xyz['y'] - $xyz['z'] ),
474 - );
491 + /**
492 + * Alias of toString()
493 + *
494 + * @return string
495 + */
496 + public function __toString() {
497 + return $this->toString();
498 + }
475 499
476 - return $lab;
477 - }
500 + /**
501 + * Get color as string
502 + *
503 + * @return string
504 + */
505 + public function toString() {
506 + $str = $this->toHex();
507 + return strtoupper( "#{$str}" );
508 + }
478 509
479 - /**
480 - * Convert color to integer
481 - *
482 - * @return int
483 - */
484 - public function toInt() {
485 - return $this->color;
486 - }
510 + /**
511 + * Get the distance between this color and the given color
512 + *
513 + * @param Jetpack_Color $color Color code.
514 + *
515 + * @return int
516 + */
517 + public function getDistanceRgbFrom( Jetpack_Color $color ) {
518 + $rgb1 = $this->toRgbInt();
519 + $rgb2 = $color->toRgbInt();
487 520
488 - /**
489 - * Alias of toString()
490 - *
491 - * @return string
492 - */
493 - public function __toString() {
494 - return $this->toString();
495 - }
521 + $r_diff = abs( $rgb1['red'] - $rgb2['red'] );
522 + $g_diff = abs( $rgb1['green'] - $rgb2['green'] );
523 + $b_diff = abs( $rgb1['blue'] - $rgb2['blue'] );
496 524
497 - /**
498 - * Get color as string
499 - *
500 - * @return string
501 - */
502 - public function toString() {
503 - $str = $this->toHex();
504 - return strtoupper( "#{$str}" );
505 - }
525 + // Sum of RGB differences.
526 + $diff = $r_diff + $g_diff + $b_diff;
527 + return $diff;
528 + }
506 529
507 - /**
508 - * Get the distance between this color and the given color
509 - *
510 - * @param Jetpack_Color $color Color code.
511 - *
512 - * @return int
513 - */
514 - public function getDistanceRgbFrom( Jetpack_Color $color ) {
515 - $rgb1 = $this->toRgbInt();
516 - $rgb2 = $color->toRgbInt();
530 + /**
531 + * Get distance from the given color using the Delta E method
532 + *
533 + * @param Jetpack_Color $color Color code.
534 + *
535 + * @return float
536 + */
537 + public function getDistanceLabFrom( Jetpack_Color $color ) {
538 + $lab1 = $this->toLabCie();
539 + $lab2 = $color->toLabCie();
517 540
518 - $r_diff = abs( $rgb1['red'] - $rgb2['red'] );
519 - $g_diff = abs( $rgb1['green'] - $rgb2['green'] );
520 - $b_diff = abs( $rgb1['blue'] - $rgb2['blue'] );
541 + $l_diff = abs( $lab2['l'] - $lab1['l'] );
542 + $a_diff = abs( $lab2['a'] - $lab1['a'] );
543 + $b_diff = abs( $lab2['b'] - $lab1['b'] );
521 544
522 - // Sum of RGB differences.
523 - $diff = $r_diff + $g_diff + $b_diff;
524 - return $diff;
525 - }
545 + $delta = sqrt( $l_diff + $a_diff + $b_diff );
526 546
527 - /**
528 - * Get distance from the given color using the Delta E method
529 - *
530 - * @param Jetpack_Color $color Color code.
531 - *
532 - * @return float
533 - */
534 - public function getDistanceLabFrom( Jetpack_Color $color ) {
535 - $lab1 = $this->toLabCie();
536 - $lab2 = $color->toLabCie();
547 + return $delta;
548 + }
537 549
538 - $l_diff = abs( $lab2['l'] - $lab1['l'] );
539 - $a_diff = abs( $lab2['a'] - $lab1['a'] );
540 - $b_diff = abs( $lab2['b'] - $lab1['b'] );
550 + /**
551 + * Calculate luminosity.
552 + *
553 + * @return float
554 + */
555 + public function toLuminosity() {
556 + $lum = array();
557 + foreach ( $this->toRgbInt() as $slot => $value ) {
558 + $chan = $value / 255;
559 + $lum[ $slot ] = ( $chan <= 0.03928 ) ? $chan / 12.92 : pow( ( ( $chan + 0.055 ) / 1.055 ), 2.4 );
560 + }
561 + return 0.2126 * $lum['red'] + 0.7152 * $lum['green'] + 0.0722 * $lum['blue'];
562 + }
541 563
542 - $delta = sqrt( $l_diff + $a_diff + $b_diff );
564 + /**
565 + * Get distance between colors using luminance.
566 + * Should be more than 5 for readable contrast
567 + *
568 + * @param Jetpack_Color $color Another color.
569 + * @return float
570 + */
571 + public function getDistanceLuminosityFrom( Jetpack_Color $color ) {
572 + $l1 = $this->toLuminosity();
573 + $l2 = $color->toLuminosity();
574 + if ( $l1 > $l2 ) {
575 + return ( $l1 + 0.05 ) / ( $l2 + 0.05 );
576 + } else {
577 + return ( $l2 + 0.05 ) / ( $l1 + 0.05 );
578 + }
579 + }
543 580
544 - return $delta;
545 - }
546 -
547 - /**
548 - * Calculate luminosity.
549 - *
550 - * @return float
551 - */
552 - public function toLuminosity() {
553 - $lum = array();
554 - foreach ( $this->toRgbInt() as $slot => $value ) {
555 - $chan = $value / 255;
556 - $lum[ $slot ] = ( $chan <= 0.03928 ) ? $chan / 12.92 : pow( ( ( $chan + 0.055 ) / 1.055 ), 2.4 );
581 + /**
582 + * Get maximum contrast color.
583 + *
584 + * @return $this
585 + */
586 + public function getMaxContrastColor() {
587 + $with_black = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#000' ) );
588 + $with_white = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#fff' ) );
589 + $color = new Jetpack_Color();
590 + $hex = ( $with_black >= $with_white ) ? '#000000' : '#ffffff';
591 + return $color->fromHex( $hex );
557 592 }
558 - return 0.2126 * $lum['red'] + 0.7152 * $lum['green'] + 0.0722 * $lum['blue'];
559 - }
560 593
561 - /**
562 - * Get distance between colors using luminance.
563 - * Should be more than 5 for readable contrast
564 - *
565 - * @param Jetpack_Color $color Another color.
566 - * @return float
567 - */
568 - public function getDistanceLuminosityFrom( Jetpack_Color $color ) {
569 - $l1 = $this->toLuminosity();
570 - $l2 = $color->toLuminosity();
571 - if ( $l1 > $l2 ) {
572 - return ( $l1 + 0.05 ) / ( $l2 + 0.05 );
573 - } else {
574 - return ( $l2 + 0.05 ) / ( $l1 + 0.05 );
575 - }
576 - }
594 + /**
595 + * Get grayscale contrasting color.
596 + *
597 + * @param bool|int $contrast Contrast.
598 + *
599 + * @return $this
600 + */
601 + public function getGrayscaleContrastingColor( $contrast = false ) {
602 + if ( ! $contrast ) {
603 + return $this->getMaxContrastColor();
604 + }
605 + // don't allow less than 5.
606 + $target_contrast = ( $contrast < 5 ) ? 5 : $contrast;
607 + $color = $this->getMaxContrastColor();
608 + $contrast = $color->getDistanceLuminosityFrom( $this );
577 609
578 - /**
579 - * Get maximum contrast color.
580 - *
581 - * @return $this
582 - */
583 - public function getMaxContrastColor() {
584 - $with_black = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#000' ) );
585 - $with_white = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#fff' ) );
586 - $color = new Jetpack_Color();
587 - $hex = ( $with_black >= $with_white ) ? '#000000' : '#ffffff';
588 - return $color->fromHex( $hex );
589 - }
610 + // if current max contrast is less than the target contrast, we had wishful thinking.
611 + if ( $contrast <= $target_contrast ) {
612 + return $color;
613 + }
590 614
591 - /**
592 - * Get grayscale contrasting color.
593 - *
594 - * @param bool|int $contrast Contrast.
595 - *
596 - * @return $this
597 - */
598 - public function getGrayscaleContrastingColor( $contrast = false ) {
599 - if ( ! $contrast ) {
600 - return $this->getMaxContrastColor();
601 - }
602 - // don't allow less than 5.
603 - $target_contrast = ( $contrast < 5 ) ? 5 : $contrast;
604 - $color = $this->getMaxContrastColor();
605 - $contrast = $color->getDistanceLuminosityFrom( $this );
615 + $incr = ( '#000000' === $color->toString() ) ? 1 : -1;
616 + while ( $contrast > $target_contrast ) {
617 + $color = $color->incrementLightness( $incr );
618 + $contrast = $color->getDistanceLuminosityFrom( $this );
619 + }
606 620
607 - // if current max contrast is less than the target contrast, we had wishful thinking.
608 - if ( $contrast <= $target_contrast ) {
609 621 return $color;
610 622 }
611 623
612 - $incr = ( '#000000' === $color->toString() ) ? 1 : -1;
613 - while ( $contrast > $target_contrast ) {
614 - $color = $color->incrementLightness( $incr );
615 - $contrast = $color->getDistanceLuminosityFrom( $this );
616 - }
624 + /**
625 + * Gets a readable contrasting color. $this is assumed to be the text and $color the background color.
626 + *
627 + * @param object $bg_color A Color object that will be compared against $this.
628 + * @param integer $min_contrast The minimum contrast to achieve, if possible.
629 + * @return object A Color object, an increased contrast $this compared against $bg_color
630 + */
631 + public function getReadableContrastingColor( $bg_color = false, $min_contrast = 5 ) {
632 + if ( ! $bg_color || ! is_a( $bg_color, 'Jetpack_Color' ) ) {
633 + return $this;
634 + }
635 + // you shouldn't use less than 5, but you might want to.
636 + $target_contrast = $min_contrast;
637 + // working things.
638 + $contrast = $bg_color->getDistanceLuminosityFrom( $this );
639 + $max_contrast_color = $bg_color->getMaxContrastColor();
640 + $max_contrast = $max_contrast_color->getDistanceLuminosityFrom( $bg_color );
617 641
618 - return $color;
619 - }
642 + // if current max contrast is less than the target contrast, we had wishful thinking.
643 + // still, go max.
644 + if ( $max_contrast <= $target_contrast ) {
645 + return $max_contrast_color;
646 + }
647 + // or, we might already have sufficient contrast.
648 + if ( $contrast >= $target_contrast ) {
649 + return $this;
650 + }
620 651
621 - /**
622 - * Gets a readable contrasting color. $this is assumed to be the text and $color the background color.
623 - *
624 - * @param object $bg_color A Color object that will be compared against $this.
625 - * @param integer $min_contrast The minimum contrast to achieve, if possible.
626 - * @return object A Color object, an increased contrast $this compared against $bg_color
627 - */
628 - public function getReadableContrastingColor( $bg_color = false, $min_contrast = 5 ) {
629 - if ( ! $bg_color || ! is_a( $bg_color, 'Jetpack_Color' ) ) {
652 + $incr = ( 0 === $max_contrast_color->toInt() ) ? -1 : 1;
653 + while ( $contrast < $target_contrast ) {
654 + $this->incrementLightness( $incr );
655 + $contrast = $bg_color->getDistanceLuminosityFrom( $this );
656 + // infininite loop prevention: you never know.
657 + if ( 0 === $this->color || 16777215 === $this->color ) {
658 + break;
659 + }
660 + }
661 +
630 662 return $this;
631 663 }
632 - // you shouldn't use less than 5, but you might want to.
633 - $target_contrast = $min_contrast;
634 - // working things.
635 - $contrast = $bg_color->getDistanceLuminosityFrom( $this );
636 - $max_contrast_color = $bg_color->getMaxContrastColor();
637 - $max_contrast = $max_contrast_color->getDistanceLuminosityFrom( $bg_color );
638 664
639 - // if current max contrast is less than the target contrast, we had wishful thinking.
640 - // still, go max.
641 - if ( $max_contrast <= $target_contrast ) {
642 - return $max_contrast_color;
665 + /**
666 + * Detect if color is grayscale
667 + *
668 + * @param int $threshold Max difference between colors.
669 + *
670 + * @return bool
671 + */
672 + public function isGrayscale( $threshold = 16 ) {
673 + $rgb = $this->toRgbInt();
674 +
675 + // Get min and max rgb values, then difference between them.
676 + $rgb_min = min( $rgb );
677 + $rgb_max = max( $rgb );
678 + $diff = $rgb_max - $rgb_min;
679 +
680 + return $diff < $threshold;
643 681 }
644 - // or, we might already have sufficient contrast.
645 - if ( $contrast >= $target_contrast ) {
646 - return $this;
647 - }
648 682
649 - $incr = ( 0 === $max_contrast_color->toInt() ) ? -1 : 1;
650 - while ( $contrast < $target_contrast ) {
651 - $this->incrementLightness( $incr );
652 - $contrast = $bg_color->getDistanceLuminosityFrom( $this );
653 - // infininite loop prevention: you never know.
654 - if ( 0 === $this->color || 16777215 === $this->color ) {
655 - break;
683 + /**
684 + * Get the closest matching color from the given array of colors
685 + *
686 + * @param array $colors array of integers or Jetpack_Color objects.
687 + *
688 + * @return mixed the array key of the matched color
689 + */
690 + public function getClosestMatch( array $colors ) {
691 + $match_dist = 10000;
692 + $match_key = null;
693 + foreach ( $colors as $key => $color ) {
694 + if ( false === ( $color instanceof Jetpack_Color ) ) {
695 + $c = new Jetpack_Color( $color );
696 + }
697 + $dist = $this->getDistanceLabFrom( $c );
698 + if ( $dist < $match_dist ) {
699 + $match_dist = $dist;
700 + $match_key = $key;
701 + }
656 702 }
703 +
704 + return $match_key;
657 705 }
658 706
659 - return $this;
660 - }
707 + /* TRANSFORMS */
661 708
662 - /**
663 - * Detect if color is grayscale
664 - *
665 - * @param int $threshold Max difference between colors.
666 - *
667 - * @return bool
668 - */
669 - public function isGrayscale( $threshold = 16 ) {
670 - $rgb = $this->toRgbInt();
709 + /**
710 + * Transform -- Darken color.
711 + *
712 + * @param int $amount Amount. Default to 5.
713 + *
714 + * @return $this
715 + */
716 + public function darken( $amount = 5 ) {
717 + return $this->incrementLightness( - $amount );
718 + }
671 719
672 - // Get min and max rgb values, then difference between them.
673 - $rgb_min = min( $rgb );
674 - $rgb_max = max( $rgb );
675 - $diff = $rgb_max - $rgb_min;
720 + /**
721 + * Transform -- Lighten color.
722 + *
723 + * @param int $amount Amount. Default to 5.
724 + *
725 + * @return $this
726 + */
727 + public function lighten( $amount = 5 ) {
728 + return $this->incrementLightness( $amount );
729 + }
676 730
677 - return $diff < $threshold;
678 - }
731 + /**
732 + * Transform -- Increment lightness.
733 + *
734 + * @param int $amount Amount.
735 + *
736 + * @return $this
737 + */
738 + public function incrementLightness( $amount ) {
739 + $hsl = $this->toHsl();
679 740
680 - /**
681 - * Get the closest matching color from the given array of colors
682 - *
683 - * @param array $colors array of integers or Jetpack_Color objects.
684 - *
685 - * @return mixed the array key of the matched color
686 - */
687 - public function getClosestMatch( array $colors ) {
688 - $match_dist = 10000;
689 - $match_key = null;
690 - foreach ( $colors as $key => $color ) {
691 - if ( false === ( $color instanceof Jetpack_Color ) ) {
692 - $c = new Jetpack_Color( $color );
741 + $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
742 + $s = isset( $hsl['s'] ) ? $hsl['s'] : 0;
743 + $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
744 +
745 + $l += $amount;
746 + if ( $l < 0 ) {
747 + $l = 0;
693 748 }
694 - $dist = $this->getDistanceLabFrom( $c );
695 - if ( $dist < $match_dist ) {
696 - $match_dist = $dist;
697 - $match_key = $key;
749 + if ( $l > 100 ) {
750 + $l = 100;
698 751 }
752 + return $this->fromHsl( $h, $s, $l );
699 753 }
700 754
701 - return $match_key;
702 - }
755 + /**
756 + * Transform -- Saturate color.
757 + *
758 + * @param int $amount Amount. Default to 15.
759 + *
760 + * @return $this
761 + */
762 + public function saturate( $amount = 15 ) {
763 + return $this->incrementSaturation( $amount );
764 + }
703 765
704 - /* TRANSFORMS */
766 + /**
767 + * Transform -- Desaturate color.
768 + *
769 + * @param int $amount Amount. Default to 15.
770 + *
771 + * @return $this
772 + */
773 + public function desaturate( $amount = 15 ) {
774 + return $this->incrementSaturation( - $amount );
775 + }
705 776
706 - /**
707 - * Transform -- Darken color.
708 - *
709 - * @param int $amount Amount. Default to 5.
710 - *
711 - * @return $this
712 - */
713 - public function darken( $amount = 5 ) {
714 - return $this->incrementLightness( - $amount );
715 - }
777 + /**
778 + * Transform -- Increment saturation.
779 + *
780 + * @param int $amount Amount.
781 + *
782 + * @return $this
783 + */
784 + public function incrementSaturation( $amount ) {
785 + $hsl = $this->toHsl();
716 786
717 - /**
718 - * Transform -- Lighten color.
719 - *
720 - * @param int $amount Amount. Default to 5.
721 - *
722 - * @return $this
723 - */
724 - public function lighten( $amount = 5 ) {
725 - return $this->incrementLightness( $amount );
726 - }
787 + $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
788 + $s = isset( $hsl['s'] ) ? $hsl['s'] : 0;
789 + $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
727 790
728 - /**
729 - * Transform -- Increment lightness.
730 - *
731 - * @param int $amount Amount.
732 - *
733 - * @return $this
734 - */
735 - public function incrementLightness( $amount ) {
736 - $hsl = $this->toHsl();
737 -
738 - $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
739 - $s = isset( $hsl['s'] ) ? $hsl['s'] : 0;
740 - $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
741 -
742 - $l += $amount;
743 - if ( $l < 0 ) {
744 - $l = 0;
791 + $s += $amount;
792 + if ( $s < 0 ) {
793 + $s = 0;
794 + }
795 + if ( $s > 100 ) {
796 + $s = 100;
797 + }
798 + return $this->fromHsl( $h, $s, $l );
745 799 }
746 - if ( $l > 100 ) {
747 - $l = 100;
748 - }
749 - return $this->fromHsl( $h, $s, $l );
750 - }
751 800
752 - /**
753 - * Transform -- Saturate color.
754 - *
755 - * @param int $amount Amount. Default to 15.
756 - *
757 - * @return $this
758 - */
759 - public function saturate( $amount = 15 ) {
760 - return $this->incrementSaturation( $amount );
761 - }
801 + /**
802 + * Transform -- To grayscale.
803 + *
804 + * @return $this
805 + */
806 + public function toGrayscale() {
807 + $hsl = $this->toHsl();
762 808
763 - /**
764 - * Transform -- Desaturate color.
765 - *
766 - * @param int $amount Amount. Default to 15.
767 - *
768 - * @return $this
769 - */
770 - public function desaturate( $amount = 15 ) {
771 - return $this->incrementSaturation( - $amount );
772 - }
809 + $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
810 + $s = 0;
811 + $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
773 812
774 - /**
775 - * Transform -- Increment saturation.
776 - *
777 - * @param int $amount Amount.
778 - *
779 - * @return $this
780 - */
781 - public function incrementSaturation( $amount ) {
782 - $hsl = $this->toHsl();
813 + return $this->fromHsl( $h, $s, $l );
814 + }
783 815
784 - $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
785 - $s = isset( $hsl['s'] ) ? $hsl['s'] : 0;
786 - $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
816 + /**
817 + * Transform -- To the complementary color.
818 + *
819 + * The complement is the color on the opposite side of the color wheel, 180° away.
820 + *
821 + * @return $this
822 + */
823 + public function getComplement() {
824 + return $this->incrementHue( 180 );
825 + }
787 826
788 - $s += $amount;
789 - if ( $s < 0 ) {
790 - $s = 0;
827 + /**
828 + * Transform -- To an analogous color of the complement.
829 + *
830 + * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
831 + *
832 + * @return $this
833 + */
834 + public function getSplitComplement( $step = 1 ) {
835 + $incr = 180 + ( $step * 30 );
836 + return $this->incrementHue( $incr );
791 837 }
792 - if ( $s > 100 ) {
793 - $s = 100;
838 +
839 + /**
840 + * Transform -- To an analogous color.
841 + *
842 + * Analogous colors are those adjacent on the color wheel, separated by 30°.
843 + *
844 + * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
845 + *
846 + * @return $this
847 + */
848 + public function getAnalog( $step = 1 ) {
849 + $incr = $step * 30;
850 + return $this->incrementHue( $incr );
794 851 }
795 - return $this->fromHsl( $h, $s, $l );
796 - }
797 852
798 - /**
799 - * Transform -- To grayscale.
800 - *
801 - * @return $this
802 - */
803 - public function toGrayscale() {
804 - $hsl = $this->toHsl();
853 + /**
854 + * Transform -- To a tetradic (rectangular) color.
855 + *
856 + * A rectangular color scheme uses a color, its complement, and the colors 60° from each.
857 + * This transforms the color to its 60° "tetrad".
858 + *
859 + * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
860 + *
861 + * @return $this
862 + */
863 + public function getTetrad( $step = 1 ) {
864 + $incr = $step * 60;
865 + return $this->incrementHue( $incr );
866 + }
805 867
806 - $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
807 - $s = 0;
808 - $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
868 + /**
869 + * Transform -- To a triadic color.
870 + *
871 + * A triadic color scheme uses three colors evenly spaced (120°) around the color wheel.
872 + * This transforms the color to one of its triadic colors.
873 + *
874 + * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
875 + *
876 + * @return $this
877 + */
878 + public function getTriad( $step = 1 ) {
879 + $incr = $step * 120;
880 + return $this->incrementHue( $incr );
881 + }
809 882
810 - return $this->fromHsl( $h, $s, $l );
811 - }
883 + /**
884 + * Transform -- Increment hue.
885 + *
886 + * @param int $amount Amount.
887 + *
888 + * @return $this
889 + */
890 + public function incrementHue( $amount ) {
891 + $hsl = $this->toHsl();
812 892
813 - /**
814 - * Transform -- To the complementary color.
815 - *
816 - * The complement is the color on the opposite side of the color wheel, 180° away.
817 - *
818 - * @return $this
819 - */
820 - public function getComplement() {
821 - return $this->incrementHue( 180 );
822 - }
893 + $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
894 + $s = isset( $hsl['s'] ) ? $hsl['s'] : 0;
895 + $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
823 896
824 - /**
825 - * Transform -- To an analogous color of the complement.
826 - *
827 - * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
828 - *
829 - * @return $this
830 - */
831 - public function getSplitComplement( $step = 1 ) {
832 - $incr = 180 + ( $step * 30 );
833 - return $this->incrementHue( $incr );
834 - }
835 -
836 - /**
837 - * Transform -- To an analogous color.
838 - *
839 - * Analogous colors are those adjacent on the color wheel, separated by 30°.
840 - *
841 - * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
842 - *
843 - * @return $this
844 - */
845 - public function getAnalog( $step = 1 ) {
846 - $incr = $step * 30;
847 - return $this->incrementHue( $incr );
848 - }
849 -
850 - /**
851 - * Transform -- To a tetradic (rectangular) color.
852 - *
853 - * A rectangular color scheme uses a color, its complement, and the colors 60° from each.
854 - * This transforms the color to its 60° "tetrad".
855 - *
856 - * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
857 - *
858 - * @return $this
859 - */
860 - public function getTetrad( $step = 1 ) {
861 - $incr = $step * 60;
862 - return $this->incrementHue( $incr );
863 - }
864 -
865 - /**
866 - * Transform -- To a triadic color.
867 - *
868 - * A triadic color scheme uses three colors evenly spaced (120°) around the color wheel.
869 - * This transforms the color to one of its triadic colors.
870 - *
871 - * @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
872 - *
873 - * @return $this
874 - */
875 - public function getTriad( $step = 1 ) {
876 - $incr = $step * 120;
877 - return $this->incrementHue( $incr );
878 - }
879 -
880 - /**
881 - * Transform -- Increment hue.
882 - *
883 - * @param int $amount Amount.
884 - *
885 - * @return $this
886 - */
887 - public function incrementHue( $amount ) {
888 - $hsl = $this->toHsl();
889 -
890 - $h = isset( $hsl['h'] ) ? $hsl['h'] : 0;
891 - $s = isset( $hsl['s'] ) ? $hsl['s'] : 0;
892 - $l = isset( $hsl['l'] ) ? $hsl['l'] : 0;
893 -
894 - $h = ( $h + $amount ) % 360;
895 - if ( $h < 0 ) {
896 - $h += 360;
897 + $h = ( $h + $amount ) % 360;
898 + if ( $h < 0 ) {
899 + $h += 360;
900 + }
901 + return $this->fromHsl( $h, $s, $l );
897 902 }
898 - return $this->fromHsl( $h, $s, $l );
899 903 }
900 904 }