rgb/legacy/internal/
ops.rs

1use crate::formats::gray::Gray_v08 as Gray;
2use super::pixel::ComponentMap;
3use crate::alt::GrayAlpha;
4use crate::alt::ARGB;
5use crate::alt::GRB;
6use crate::{RGB, RGBA};
7use core::iter::Sum;
8use core::ops::{Sub, SubAssign, Add, AddAssign, Mul, MulAssign, Div, DivAssign};
9
10#[cfg(feature = "checked_fns")]
11macro_rules! impl_struct_checked {
12    ($ty:ident, $field_ty:ident, => $($field:tt)+) => {
13        impl $ty<$field_ty>
14        {
15            /// `px.checked_add(px)`
16            #[inline(always)]
17            #[allow(deprecated)]
18            pub fn checked_add(self, rhs: $ty<$field_ty>) -> Option<Self> {
19                Some($ty {
20                    $(
21                        $field: self.$field.checked_add(rhs.$field)?,
22                    )+
23                })
24            }
25
26            /// `px.checked_sub(px)`
27            #[inline(always)]
28            #[allow(deprecated)]
29            pub fn checked_sub(self, rhs: $ty<$field_ty>) -> Option<Self> {
30                Some($ty {
31                    $(
32                        $field: self.$field.checked_sub(rhs.$field)?,
33                    )+
34                })
35            }
36        }
37    }
38}
39
40#[cfg(not(feature = "checked_fns"))]
41macro_rules! impl_struct_checked {
42    ($ty:ident, $field_ty:ident, => $($field:tt)+) => {};
43}
44
45macro_rules! impl_struct_ops_opaque {
46    ($ty:ident => $($field:tt)+) => {
47        /// `px + px`
48        impl<T: Add> Add for $ty<T> {
49            type Output = $ty<<T as Add>::Output>;
50
51            #[inline(always)]
52            #[allow(deprecated)]
53            fn add(self, other: $ty<T>) -> Self::Output {
54                $ty {
55                    $(
56                        $field: self.$field + other.$field,
57                    )+
58                }
59            }
60        }
61
62        /// `px + px`
63        impl<T> AddAssign for $ty<T> where
64            T: Add<Output = T> + Copy
65        {
66            #[inline(always)]
67            #[allow(deprecated)]
68            fn add_assign(&mut self, other: $ty<T>) {
69                *self = Self {
70                    $(
71                        $field: self.$field + other.$field,
72                    )+
73                };
74            }
75        }
76
77        /// `px * px`
78        impl<T: Mul> Mul for $ty<T> {
79            type Output = $ty<<T as Mul>::Output>;
80
81            #[inline(always)]
82            #[allow(deprecated)]
83            fn mul(self, other: $ty<T>) -> Self::Output {
84                $ty {
85                    $(
86                        $field: self.$field * other.$field,
87                    )+
88                }
89            }
90        }
91
92        /// `px * px`
93        impl<T> MulAssign for $ty<T> where
94            T: Mul<Output = T> + Copy
95        {
96            #[inline(always)]
97            #[allow(deprecated)]
98            fn mul_assign(&mut self, other: $ty<T>) {
99                *self = Self {
100                    $(
101                        $field: self.$field * other.$field,
102                    )+
103                };
104            }
105        }
106
107        /// `px - px`
108        impl<T: Sub> Sub for $ty<T> {
109            type Output = $ty<<T as Sub>::Output>;
110
111            #[inline(always)]
112            #[allow(deprecated)]
113            fn sub(self, other: $ty<T>) -> Self::Output {
114                $ty {
115                    $(
116                        $field: self.$field - other.$field,
117                    )+
118                }
119            }
120        }
121
122        /// `px - px`
123        impl<T> SubAssign for $ty<T> where
124            T: Sub<Output = T> + Copy
125        {
126            #[inline(always)]
127            #[allow(deprecated)]
128            fn sub_assign(&mut self, other: $ty<T>) {
129                *self = Self {
130                    $(
131                        $field: self.$field - other.$field,
132                    )+
133                };
134            }
135        }
136
137        impl<T> Sum<$ty<T>> for $ty<T> where T: Default + Add<Output=T> {
138            #[inline(always)]
139            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
140                iter.fold($ty::default(), Add::add)
141            }
142        }
143
144        impl_struct_checked!($ty, u8, => $($field)+);
145        impl_struct_checked!($ty, u16, => $($field)+);
146        impl_struct_checked!($ty, u32, => $($field)+);
147        impl_struct_checked!($ty, u64, => $($field)+);
148        impl_struct_checked!($ty, i8, => $($field)+);
149        impl_struct_checked!($ty, i16, => $($field)+);
150        impl_struct_checked!($ty, i32, => $($field)+);
151        impl_struct_checked!($ty, i64, => $($field)+);
152    };
153}
154
155macro_rules! impl_struct_ops_alpha {
156    ($ty:ident => $($field:tt)+) => {
157        /// `px + px`
158        impl<T: Add, A: Add> Add for $ty<T, A> {
159            type Output = $ty<<T as Add>::Output, <A as Add>::Output>;
160
161            #[inline(always)]
162            #[allow(deprecated)]
163            fn add(self, other: $ty<T, A>) -> Self::Output {
164                $ty {
165                    $(
166                        $field: self.$field + other.$field,
167                    )+
168                }
169            }
170        }
171
172        /// `px + px`
173        impl<T, A> AddAssign for $ty<T, A> where
174            T: Add<Output = T> + Copy,
175            A: Add<Output = A> + Copy
176        {
177            #[inline(always)]
178            #[allow(deprecated)]
179            fn add_assign(&mut self, other: $ty<T, A>) {
180                *self = Self {
181                    $(
182                        $field: self.$field + other.$field,
183                    )+
184                };
185            }
186        }
187
188        /// `px - px`
189        impl<T: Sub, A: Sub> Sub for $ty<T, A> {
190            type Output = $ty<<T as Sub>::Output, <A as Sub>::Output>;
191
192            #[inline(always)]
193            #[allow(deprecated)]
194            fn sub(self, other: $ty<T, A>) -> Self::Output {
195                $ty {
196                    $(
197                        $field: self.$field - other.$field,
198                    )+
199                }
200            }
201        }
202
203        /// `px - px`
204        impl<T, A> SubAssign for $ty<T, A> where
205            T: Sub<Output = T> + Copy,
206            A: Sub<Output = A> + Copy
207        {
208            #[inline(always)]
209            #[allow(deprecated)]
210            fn sub_assign(&mut self, other: $ty<T, A>) {
211                *self = Self {
212                    $(
213                        $field: self.$field - other.$field,
214                    )+
215                };
216            }
217        }
218
219        impl<T, A> Sum<$ty<T, A>> for $ty<T, A> where T: Default + Add<Output=T>, A: Default + Add<Output=A> {
220            #[inline(always)]
221            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
222                iter.fold($ty::default(), Add::add)
223            }
224        }
225
226        impl_struct_checked!($ty, u8, => $($field)+);
227        impl_struct_checked!($ty, u16, => $($field)+);
228        impl_struct_checked!($ty, u32, => $($field)+);
229        impl_struct_checked!($ty, u64, => $($field)+);
230        impl_struct_checked!($ty, i8, => $($field)+);
231        impl_struct_checked!($ty, i16, => $($field)+);
232        impl_struct_checked!($ty, i32, => $($field)+);
233        impl_struct_checked!($ty, i64, => $($field)+);
234    };
235}
236
237macro_rules! impl_scalar {
238    ($ty:ident) => {
239        /// `px - 1`
240        impl<T> Sub<T> for $ty<T>
241        where T: Copy + Sub<Output = T>
242        {
243            type Output = $ty<<T as Sub>::Output>;
244
245            #[inline(always)]
246            fn sub(self, r: T) -> Self::Output {
247                self.map(|l| l - r)
248            }
249        }
250
251        /// `px - 1`
252        impl<T> SubAssign<T> for $ty<T>
253        where T: Copy + Sub<Output = T>
254        {
255            #[inline(always)]
256            fn sub_assign(&mut self, r: T) {
257                *self = self.map(|l| l - r);
258            }
259        }
260
261        /// `px + 1`
262        impl<T> Add<T> for $ty<T>
263        where T: Copy + Add<Output = T>
264        {
265            type Output = $ty<T>;
266
267            #[inline(always)]
268            fn add(self, r: T) -> Self::Output {
269                self.map(|l| l + r)
270            }
271        }
272
273        /// `px + 1`
274        impl<T> AddAssign<T> for $ty<T>
275        where T: Copy + Add<Output = T>
276        {
277            #[inline(always)]
278            fn add_assign(&mut self, r: T) {
279                *self = self.map(|l| l + r);
280            }
281        }
282
283        /// `px * 1`
284        impl<T> Mul<T> for $ty<T>
285        where T: Copy + Mul<Output = T>
286        {
287            type Output = $ty<T>;
288
289            #[inline(always)]
290            fn mul(self, r: T) -> Self::Output {
291                self.map(|l| l * r)
292            }
293        }
294
295        /// `px * 1`
296        impl<T> MulAssign<T> for $ty<T>
297        where T: Copy + Mul<Output = T>
298        {
299            #[inline(always)]
300            fn mul_assign(&mut self, r: T) {
301                *self = self.map(|l| l * r);
302            }
303        }
304
305        /// `px / 1`
306        impl<T> Div<T> for $ty<T>
307        where T: Copy + Div<Output = T>
308        {
309            type Output = $ty<T>;
310
311            #[inline(always)]
312            fn div(self, r: T) -> Self::Output {
313                self.map(|l| l / r)
314            }
315        }
316
317        /// `px * 1`
318        impl<T> DivAssign<T> for $ty<T>
319        where T: Copy + Div<Output = T>
320        {
321            #[inline(always)]
322            fn div_assign(&mut self, r: T) {
323                *self = self.map(|l| l / r);
324            }
325        }
326    };
327}
328
329impl_scalar! {RGB}
330impl_scalar! {RGBA}
331impl_scalar! {ARGB}
332impl_scalar! {GRB}
333impl_scalar! {Gray}
334impl_scalar! {GrayAlpha}
335
336impl_struct_ops_opaque! {RGB => r g b}
337impl_struct_ops_opaque! {GRB => g r b}
338impl_struct_ops_opaque! {Gray => 0}
339
340impl_struct_ops_alpha! {RGBA => r g b a}
341impl_struct_ops_alpha! {ARGB => a r g b}
342impl_struct_ops_alpha! {GrayAlpha => 0 1}