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 #[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 #[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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}