palette/macros/
blend.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
macro_rules! impl_premultiply {
    ($ty: ident {$($component: ident),+} $(phantom: $phantom: ident)? $(where $($where: tt)+)?) => {
        impl_premultiply!($ty<> {$($component),+} $(phantom: $phantom)? $(where $($where)+)?);
    };
    ($ty: ident <$($ty_param: ident),*> {$($component: ident),+} $(phantom: $phantom: ident)? $(where $($where: tt)+)?) => {
        impl<$($ty_param,)* T> crate::blend::Premultiply for $ty<$($ty_param,)* T>
        where
            T: crate::num::Real
                + crate::stimulus::Stimulus
                + crate::num::Zero
                + crate::num::IsValidDivisor
                + core::ops::Mul<T, Output = T>
                + core::ops::Div<T, Output = T>
                + Clone,
            T::Mask: crate::bool_mask::LazySelect<T> + Clone,
            $($($where)+)?
        {
            type Scalar = T;

            #[inline]
            fn premultiply(self, alpha: T) -> crate::blend::PreAlpha<Self> {
                crate::blend::PreAlpha {
                    color: self * alpha.clone(),
                    alpha
                }
            }

            #[inline]
            fn unpremultiply(premultiplied: crate::blend::PreAlpha<Self>) -> (Self, T) {
                let crate::blend::PreAlpha {
                    color: $ty { $($component,)+ .. },
                    alpha,
                } = premultiplied;

                let is_valid_divisor = alpha.is_valid_divisor();

                let color = Self {
                    $(
                        $component: lazy_select! {
                            if is_valid_divisor.clone() => $component / alpha.clone(),
                            else => T::zero()
                        },
                    )+
                    $($phantom: core::marker::PhantomData,)?
                };

                (color, alpha)
            }
        }

        impl<$($ty_param,)* T> From<crate::blend::PreAlpha<Self>> for $ty<$($ty_param,)* T>
        where
            Self: crate::blend::Premultiply<Scalar = T>,
        {
            fn from(premultiplied: crate::blend::PreAlpha<Self>) -> Self {
                use crate::blend::Premultiply;

                Self::unpremultiply(premultiplied).0
            }
        }
    };
}