1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Color Data Class |
4
|
|
|
* ================ |
5
|
|
|
* Stores data about a particular color in multiple formats. |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace projectcleverweb\color\data; |
9
|
|
|
|
10
|
|
|
use \projectcleverweb\color\regulate; |
11
|
|
|
use \projectcleverweb\color\css; |
12
|
|
|
use \projectcleverweb\color\hsl; |
13
|
|
|
use \projectcleverweb\color\error; |
14
|
|
|
use \projectcleverweb\color\convert; // namespace |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Color Data Class |
18
|
|
|
* ================ |
19
|
|
|
* Stores data about a particular color in multiple formats. |
20
|
|
|
*/ |
21
|
|
|
class store2 implements \Serializable, \JsonSerializable { |
22
|
|
|
|
23
|
|
|
protected $color_spaces = array(); |
24
|
|
|
|
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* The current color as a hexadecimal string |
28
|
|
|
* @var string |
29
|
|
|
*/ |
30
|
|
|
public $hex; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* The current color as a RGB array |
34
|
|
|
* @var array |
35
|
|
|
*/ |
36
|
|
|
public $rgb; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* The current color as an instance of hsl (which implements ArrayAccess) |
40
|
|
|
* @var hsl |
41
|
|
|
*/ |
42
|
|
|
public $hsl; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* $the current colors alpha channel (Opacity) |
46
|
|
|
* @var float |
47
|
|
|
*/ |
48
|
|
|
protected $alpha = 100.0; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Takes an input color and imports it as its respective type. |
52
|
|
|
* |
53
|
|
|
* @param mixed $color An RGB (array), HSL (array), Hex (string), Integer (hex), or CMYK (array) representation of a color. |
54
|
|
|
* @param string $type (optional) The type to try to import it as |
55
|
|
|
*/ |
56
|
|
|
public function __construct($color, string $type = '') { |
57
|
|
|
if (is_a($color, __CLASS__)) { |
58
|
|
|
$type = 'color'; |
59
|
|
|
} elseif (empty($type) || !is_callable([__CLASS__, 'import_'.$type])) { |
60
|
|
|
$type = static::get_type($color); |
61
|
|
|
} |
62
|
|
|
call_user_func([__CLASS__, 'import_'.$type], $color); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Shortcut for invoking into an HSL array |
67
|
|
|
* |
68
|
|
|
* @return array The HSL array |
69
|
|
|
*/ |
70
|
|
|
public function hsl() { |
71
|
|
|
return ($this->hsl)(); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Serializes this object. |
76
|
|
|
* |
77
|
|
|
* @return string The serialized object |
78
|
|
|
*/ |
79
|
|
|
public function serialize() :string { |
80
|
|
|
return json_encode($this->rgb + ['a' => $this->alpha]); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Unserializes this object. |
85
|
|
|
* |
86
|
|
|
* @param string $serialized The object as a serialized string |
87
|
|
|
* @return void |
88
|
|
|
*/ |
89
|
|
|
public function unserialize($serialized) { |
90
|
|
|
$unserialized = (array) json_decode((string) $serialized); |
91
|
|
|
regulate::rgb_array($unserialized); |
92
|
|
|
$this->import_rgb($unserialized); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Serializes this object into JSON. |
97
|
|
|
* |
98
|
|
|
* @return string The serialized object |
|
|
|
|
99
|
|
|
*/ |
100
|
|
|
public function jsonSerialize() :array { |
101
|
|
|
return $this->rgb + ['a' => $this->alpha]; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Determine the type of color being used. |
106
|
|
|
* |
107
|
|
|
* @param mized $color The color in question |
108
|
|
|
* @return string The color type as a string, returns 'error' if $color is invalid |
109
|
|
|
*/ |
110
|
|
View Code Duplication |
public static function get_type($color) :string { |
|
|
|
|
111
|
|
|
if (is_array($color)) { |
112
|
|
|
return static::_get_array_type($color); |
113
|
|
|
} elseif (is_string($color)) { |
114
|
|
|
// return static::_get_str_type($color); |
|
|
|
|
115
|
|
|
return 'str'; |
116
|
|
|
} elseif (is_int($color)) { |
117
|
|
|
return 'int'; |
118
|
|
|
} |
119
|
|
|
return 'error'; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
protected function _get_str_type(string $color) { |
123
|
|
|
$color = strtolower(str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', $color)); |
124
|
|
|
if (regulate::_validate_hex_str($color, TRUE)) { |
125
|
|
|
return 'hex'; |
126
|
|
|
} elseif (css::get($color, FALSE)) { |
127
|
|
|
return 'css'; |
128
|
|
|
} elseif (x11::get($color)) { |
129
|
|
|
return 'x11'; |
130
|
|
|
} |
131
|
|
|
return 'error'; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Determine the type of color being used if it is an array. |
136
|
|
|
* |
137
|
|
|
* @param array $color The color in question |
138
|
|
|
* @return string The color type as a string, returns 'error' if $color is invalid |
139
|
|
|
*/ |
140
|
|
View Code Duplication |
protected static function _get_array_type(array $color) :string { |
|
|
|
|
141
|
|
|
$color = array_change_key_case($color); |
142
|
|
|
unset($color['a']); // ignore alpha channel |
143
|
|
|
ksort($color); |
144
|
|
|
$type = implode('', array_keys($color)); |
145
|
|
|
$types = [ |
146
|
|
|
'bgr' => 'rgb', |
147
|
|
|
'hls' => 'hsl', |
148
|
|
|
'bhs' => 'hsb', |
149
|
|
|
'ckmy' => 'cmyk' |
150
|
|
|
]; |
151
|
|
|
if (isset($types[$type])) { |
152
|
|
|
return $types[$type]; |
153
|
|
|
} |
154
|
|
|
return 'error'; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Get (and set) the alpha channel |
159
|
|
|
* |
160
|
|
|
* @param mixed $new_alpha If numeric, the alpha channel is set to this value |
161
|
|
|
* @return float The current alpha value |
162
|
|
|
*/ |
163
|
|
|
public function alpha($new_alpha = NULL) :float { |
164
|
|
|
if (is_numeric($new_alpha)) { |
165
|
|
|
$this->alpha = (float) $new_alpha; |
166
|
|
|
} |
167
|
|
|
return $this->alpha; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Handles general errors when importing, and forces the input to be valid. |
172
|
|
|
* |
173
|
|
|
* @return void |
174
|
|
|
*/ |
175
|
|
View Code Duplication |
protected function import_error() { |
|
|
|
|
176
|
|
|
error::trigger(error::INVALID_COLOR, sprintf( |
177
|
|
|
'The color supplied to %s\'s constructor was not valid', |
178
|
|
|
__CLASS__ |
179
|
|
|
)); |
180
|
|
|
$this->import_rgb([0, 0, 0]); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Import the alpha channel from a color array, or create one if it doesn't exist |
185
|
|
|
* |
186
|
|
|
* @param array $color The color array to check |
187
|
|
|
* @return void |
188
|
|
|
*/ |
189
|
|
View Code Duplication |
protected function import_alpha(array $color) { |
|
|
|
|
190
|
|
|
if (isset($color['a'])) { |
191
|
|
|
$this->alpha = regulate::max((float) $color['a'], 100); |
192
|
|
|
} else { |
193
|
|
|
$this->alpha = 100.0; |
194
|
|
|
} |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Handles importing of another instance of color |
199
|
|
|
* |
200
|
|
|
* @return void |
201
|
|
|
*/ |
202
|
|
|
protected function import_color(data $color) { |
203
|
|
|
$this->rgb = $color->rgb; |
204
|
|
|
$this->hex = $color->hex; |
205
|
|
|
$this->hsl = clone $color->hsl; |
206
|
|
|
$this->alpha = $color->alpha; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Imports a RGB array. |
211
|
|
|
* |
212
|
|
|
* @param array $color Array with offsets 'r', 'g', 'b' |
213
|
|
|
* @return void |
214
|
|
|
*/ |
215
|
|
|
public function import_rgb(array $color) { |
216
|
|
|
regulate::rgb_array($color); |
217
|
|
|
$this->rgb = array_intersect_key($color, ['r' => 0, 'g' => 0, 'b' => 0]); |
218
|
|
|
$this->hex = convert\rgb::to_hex($this->rgb); |
219
|
|
|
$this->hsl = new hsl($this->rgb); |
220
|
|
|
$this->import_alpha($color); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Imports a hsl array. |
225
|
|
|
* |
226
|
|
|
* @param array $color Array with offsets 'h', 's', 'l' |
227
|
|
|
* @return void |
228
|
|
|
*/ |
229
|
|
View Code Duplication |
public function import_hsl(array $color) { |
|
|
|
|
230
|
|
|
regulate::hsl_array($color); |
231
|
|
|
$this->rgb = convert\hsl::to_rgb($color); |
232
|
|
|
$this->hsl = new hsl($this->rgb); // [todo] This should taken from input |
|
|
|
|
233
|
|
|
$this->hex = convert\rgb::to_hex($this->rgb); |
234
|
|
|
$this->import_alpha($color); |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* Imports a hsb array. |
239
|
|
|
* |
240
|
|
|
* @param array $color Array with offsets 'h', 's', 'b' |
241
|
|
|
* @return void |
242
|
|
|
*/ |
243
|
|
View Code Duplication |
public function import_hsb(array $color) { |
|
|
|
|
244
|
|
|
regulate::hsb_array($color); |
245
|
|
|
$this->rgb = convert\hsb::to_rgb($color); |
246
|
|
|
$this->hsl = new hsl($this->rgb); |
247
|
|
|
$this->hex = convert\rgb::to_hex($this->rgb); |
248
|
|
|
$this->import_alpha($color); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* Converts a hexadecimal string into an RGB array and imports it. |
253
|
|
|
* |
254
|
|
|
* @param string $color Hexadecimal string |
255
|
|
|
* @return void |
256
|
|
|
*/ |
257
|
|
|
public function import_hex(string $color) { |
258
|
|
|
regulate::hex($color); |
259
|
|
|
$this->import_rgb(convert\hex::to_rgb($color)); |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
public function import_str(string $color) { |
263
|
|
|
$color = strtolower(str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', $color)); |
264
|
|
|
if (regulate::_validate_hex_str($color, TRUE)) { |
265
|
|
|
$this->import_hex($color); |
266
|
|
|
return; |
267
|
|
|
} elseif (preg_match('/\A(rgb|hsl)a?\((\d+),(\d+),(\d+)(?:,(\d|\d\.\d?|\.\d+))?\)\Z/i', $color, $match)) { |
268
|
|
|
$this->import_regex($match); |
269
|
|
|
return; |
270
|
|
|
} elseif ($x11 = x11::get($color)) { |
271
|
|
|
$this->import_rgb($x11); |
272
|
|
|
return; |
273
|
|
|
} |
274
|
|
|
$this->import_error(); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
public function import_regex(array $match) { |
278
|
|
|
$alpha = 100; |
279
|
|
|
if (isset($match[5])) { |
280
|
|
|
$alpha = (float) $match[5] * 100; |
281
|
|
|
} |
282
|
|
|
$color = array_combine(str_split($match[1].'a'), [$match[2], $match[3], $match[4], $alpha]); |
283
|
|
|
call_user_func([__CLASS__, 'import_'.$match[1]], $color); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Converts an integer to a hexadecimal string and imports it. |
288
|
|
|
* |
289
|
|
|
* @param int $color An integer |
290
|
|
|
* @return void |
291
|
|
|
*/ |
292
|
|
|
public function import_int(int $color) { |
293
|
|
|
regulate::hex_int($color); |
294
|
|
|
$this->import_hex(str_pad(base_convert($color, 10, 16), 6, '0', STR_PAD_LEFT)); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Imports a CMYK array |
299
|
|
|
* |
300
|
|
|
* @param array $color Array with offsets 'c', 'm', 'y', 'k' |
301
|
|
|
* @return void |
302
|
|
|
*/ |
303
|
|
|
public function import_cmyk(array $color) { |
304
|
|
|
regulate::cmyk_array($color); |
305
|
|
|
$this->import_rgb(convert\cmyk::to_rgb($color['c'], $color['m'], $color['y'], $color['k'])); |
|
|
|
|
306
|
|
|
$this->import_alpha($color); |
307
|
|
|
} |
308
|
|
|
} |
309
|
|
|
|
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.