1use super::{
16 conversion::{calculate_channels, clamp_levels, convert_levels},
17 Color,
18};
19use std::{
20 fmt::{self, LowerHex, UpperHex},
21 hash::{Hash, Hasher},
22 ops::{Add, AddAssign, Deref, Div, DivAssign, Index, Mul, MulAssign, Sub, SubAssign},
23};
24
25impl LowerHex for Color {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 let [red, green, blue, alpha] = self.channels();
28 write!(f, "#{red:x}{green:x}{blue:x}{alpha:x}")
29 }
30}
31
32impl UpperHex for Color {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 let [red, green, blue, alpha] = self.channels();
35 write!(f, "#{red:X}{green:X}{blue:X}{alpha:X}")
36 }
37}
38
39impl Index<usize> for Color {
40 type Output = u8;
41 fn index(&self, idx: usize) -> &Self::Output {
42 &self.channels[idx]
43 }
44}
45
46impl PartialEq for Color {
47 fn eq(&self, other: &Self) -> bool {
48 self.channels.eq(&other.channels)
49 }
50}
51
52impl Eq for Color {}
53
54impl Hash for Color {
55 fn hash<H: Hasher>(&self, state: &mut H) {
56 self.channels.hash(state);
57 }
58}
59
60impl Add for Color {
61 type Output = Self;
62 fn add(self, other: Color) -> Self::Output {
63 if self.mode == other.mode {
64 let [r, g, b, a] = self.channels();
65 let [or, og, ob, _] = other.channels();
66 Self {
67 mode: self.mode,
68 channels: [
69 r.saturating_add(or),
70 g.saturating_add(og),
71 b.saturating_add(ob),
72 a,
73 ],
74 }
75 } else {
76 let [v1, v2, v3, a] = self.levels();
77 let [ov1, ov2, ov3, _] = convert_levels(other.levels(), other.mode, self.mode);
78 let levels = clamp_levels([v1 + ov1, v2 + ov2, v3 + ov3, a]);
79 Self {
80 mode: self.mode,
81 channels: calculate_channels(levels),
82 }
83 }
84 }
85}
86
87impl Add<u8> for Color {
88 type Output = Self;
89 fn add(self, val: u8) -> Self::Output {
90 let [r, g, b, _] = self.channels;
91 Self::rgb(
92 r.saturating_add(val),
93 g.saturating_add(val),
94 b.saturating_add(val),
95 )
96 }
97}
98
99impl AddAssign for Color {
100 fn add_assign(&mut self, other: Color) {
101 if self.mode == other.mode {
102 for (i, v) in self.channels.iter_mut().enumerate().take(3) {
103 *v = v.saturating_add(other[i]);
104 }
105 } else {
106 let [v1, v2, v3, a] = self.levels();
107 let [ov1, ov2, ov3, _] = convert_levels(other.levels(), other.mode, self.mode);
108 let levels = clamp_levels([v1 + ov1, v2 + ov2, v3 + ov3, a]);
109 self.update_channels(levels, self.mode);
110 }
111 }
112}
113
114impl AddAssign<u8> for Color {
115 fn add_assign(&mut self, val: u8) {
116 for v in &mut self.channels {
117 *v = v.saturating_add(val);
118 }
119 }
120}
121
122impl Sub for Color {
123 type Output = Self;
124 fn sub(self, other: Color) -> Self::Output {
125 if self.mode == other.mode {
126 let [r, g, b, a] = self.channels();
127 let [or, og, ob, _] = other.channels();
128 Self {
129 mode: self.mode,
130 channels: [
131 r.saturating_sub(or),
132 g.saturating_sub(og),
133 b.saturating_sub(ob),
134 a,
135 ],
136 }
137 } else {
138 let [v1, v2, v3, a] = self.levels();
139 let [ov1, ov2, ov3, _] = convert_levels(other.levels(), other.mode, self.mode);
140 let levels = clamp_levels([v1 - ov1, v2 - ov2, v3 - ov3, a]);
141 Self {
142 mode: self.mode,
143 channels: calculate_channels(levels),
144 }
145 }
146 }
147}
148
149impl Sub<u8> for Color {
150 type Output = Self;
151 fn sub(self, val: u8) -> Self::Output {
152 let [r, g, b, a] = self.channels;
153 Self::rgba(
154 r.saturating_sub(val),
155 g.saturating_sub(val),
156 b.saturating_sub(val),
157 a,
158 )
159 }
160}
161
162impl SubAssign for Color {
163 fn sub_assign(&mut self, other: Color) {
164 if self.mode == other.mode {
165 for (i, v) in self.channels.iter_mut().enumerate().take(3) {
166 *v = v.saturating_sub(other[i]);
167 }
168 } else {
169 let [v1, v2, v3, a] = self.levels();
170 let [ov1, ov2, ov3, _] = convert_levels(other.levels(), other.mode, self.mode);
171 let levels = clamp_levels([v1 - ov1, v2 - ov2, v3 - ov3, a]);
172 self.update_channels(levels, self.mode);
173 }
174 }
175}
176
177impl SubAssign<u8> for Color {
178 fn sub_assign(&mut self, val: u8) {
179 for v in self.channels.iter_mut().take(3) {
180 *v = v.saturating_sub(val);
181 }
182 }
183}
184
185impl Deref for Color {
186 type Target = [u8; 4];
187 fn deref(&self) -> &Self::Target {
189 &self.channels
190 }
191}
192
193macro_rules! impl_ops {
194 ($($target:ty),*) => {
195 $(
196 impl Mul<$target> for Color where $target: Into<f64> {
197 type Output = Self;
198 fn mul(self, s: $target) -> Self::Output {
199 let [v1, v2, v3, a] = self.levels();
200 let s = f64::from(s);
201 let levels = clamp_levels([v1 * s, v2 * s, v3 * s, a]);
202 Self {
203 mode: self.mode,
204 channels: calculate_channels(levels),
205 }
206 }
207 }
208
209 impl Mul<Color> for $target where $target: Into<f64> {
210 type Output = Color;
211 fn mul(self, c: Color) -> Self::Output {
212 let [v1, v2, v3, a] = c.levels();
213 let s = f64::from(self);
214 let levels = clamp_levels([v1 * s, v2 * s, v3 * s, a]);
215 Color {
216 mode: c.mode,
217 channels: calculate_channels(levels),
218 }
219 }
220 }
221
222 impl MulAssign<$target> for Color where $target: Into<f64> {
223 fn mul_assign(&mut self, s: $target) {
224 let [v1, v2, v3, a] = self.levels();
225 let s = f64::from(s);
226 let levels = clamp_levels([v1 * s, v2 * s, v3 * s, a]);
227 self.update_channels(levels, self.mode);
228 }
229 }
230
231 impl Div<$target> for Color where $target: Into<f64> {
232 type Output = Self;
233 fn div(self, s: $target) -> Self::Output {
234 let [v1, v2, v3, a] = self.levels();
235 let s = f64::from(s);
236 let levels = clamp_levels([v1 / s, v2 / s, v3 / s, a]);
237 Self {
238 mode: self.mode,
239 channels: calculate_channels(levels),
240 }
241 }
242 }
243
244 impl DivAssign<$target> for Color where $target: Into<f64> {
245 fn div_assign(&mut self, s: $target) {
246 let [v1, v2, v3, a] = self.levels();
247 let s = f64::from(s);
248 let levels = clamp_levels([v1 / s, v2 / s, v3 / s, a]);
249 self.update_channels(levels, self.mode);
250 }
251 }
252 )*
253 };
254}
255
256macro_rules! impl_as_ops {
257 ($($target:ty),*) => {
258 $(
259 impl Mul<$target> for Color {
260 type Output = Self;
261 fn mul(self, s: $target) -> Self::Output {
262 let [v1, v2, v3, a] = self.levels();
263 let s = s as f64;
264 let levels = clamp_levels([v1 * s, v2 * s, v3 * s, a]);
265 Self {
266 mode: self.mode,
267 channels: calculate_channels(levels),
268 }
269 }
270 }
271
272 impl Mul<Color> for $target {
273 type Output = Color;
274 fn mul(self, c: Color) -> Self::Output {
275 let [v1, v2, v3, a] = c.levels();
276 let s = self as f64;
277 let levels = clamp_levels([v1 * s, v2 * s, v3 * s, a]);
278 Color {
279 mode: c.mode,
280 channels: calculate_channels(levels),
281 }
282 }
283 }
284
285 impl MulAssign<$target> for Color {
286 fn mul_assign(&mut self, s: $target) {
287 let [v1, v2, v3, a] = self.levels();
288 let s = s as f64;
289 let levels = clamp_levels([v1 * s, v2 * s, v3 * s, a]);
290 self.update_channels(levels, self.mode);
291 }
292 }
293
294 impl Div<$target> for Color {
295 type Output = Self;
296 fn div(self, s: $target) -> Self::Output {
297 let [v1, v2, v3, a] = self.levels();
298 let s = s as f64;
299 let levels = clamp_levels([v1 / s, v2 / s, v3 / s, a]);
300 Self {
301 mode: self.mode,
302 channels: calculate_channels(levels),
303 }
304 }
305 }
306
307 impl DivAssign<$target> for Color {
308 fn div_assign(&mut self, s: $target) {
309 let [v1, v2, v3, a] = self.levels();
310 let s = s as f64;
311 let levels = clamp_levels([v1 / s, v2 / s, v3 / s, a]);
312 self.update_channels(levels, self.mode);
313 }
314 }
315 )*
316 }
317}
318
319impl_ops!(i8, u8, i16, u16, f32);
320impl_ops!(i32, u32, f64);
321impl_as_ops!(isize, usize, i64, u64, i128, u128);
322
323#[cfg(test)]
324mod tests {
325 use crate::prelude::*;
326
327 macro_rules! test_ops {
328 ($($val: expr),*) => {
329 $(
330 let c = color!(200, 50, 10, 100) * $val;
332 assert_eq!(c.channels(), [255, 100, 20, 100]);
333
334 let c: Color = $val * color!(200, 50, 10, 100);
336 assert_eq!(c.channels(), [255, 100, 20, 100]);
337
338 let mut c = color!(200, 50, 10, 100);
340 c *= $val;
341 assert_eq!(c.channels(), [255, 100, 20, 100]);
342
343 let c: Color = color!(100, 255, 0, 100) / $val;
345 assert_eq!(c.channels(), [50, 128, 0, 100]);
346
347 let mut c = color!(200, 50, 10, 100);
349 c /= $val;
350 assert_eq!(c.channels(), [100, 25, 5, 100]);
351 )*
352 };
353 }
354
355 #[test]
356 fn test_ops() {
357 let c1 = color!(200, 50, 10, 100);
359 let c2 = color!(100, 50, 10, 100);
360 let c3 = c1 + c2;
361 assert_eq!(c3.channels(), [255, 100, 20, 100]);
362
363 let mut c1 = color!(200, 50, 10, 100);
365 let c2 = color!(100, 50, 10, 100);
366 c1 += c2;
367 assert_eq!(c1.channels(), [255, 100, 20, 100]);
368
369 let c1 = color!(200, 100, 20, 200);
371 let c2 = color!(100, 50, 30, 100);
372 let c3 = c1 - c2;
373 assert_eq!(c3.channels(), [100, 50, 0, 200]);
374
375 let mut c1 = color!(200, 100, 20, 200);
377 let c2 = color!(100, 50, 30, 100);
378 c1 -= c2;
379 assert_eq!(c1.channels(), [100, 50, 0, 200]);
380
381 test_ops!(2i8, 2u8, 2i16, 2u16, 2i32, 2u32, 2f32, 2f64);
382 }
383}