palette/blend/
blend_with.rs

1use crate::{stimulus::Stimulus, Alpha};
2
3use super::{BlendFunction, PreAlpha, Premultiply};
4
5/// Blending with a custom blend function.
6///
7/// This is a convenience trait that makes it possible to use [`BlendFunction`]
8/// via a method on the source color. This makes custom blending more similar to
9/// how the [`Compose`][super::Compose] and [`Blend`][super::Blend] are used,
10/// including automatic pre-multiplication.
11pub trait BlendWith {
12    /// The base color type of `Self`.
13    type Color: Premultiply;
14
15    /// Blend self, as the source color, with `destination`, using
16    /// `blend_function`. Anything that implements [`BlendFunction`] is
17    /// acceptable, including functions and closures.
18    ///
19    /// ```
20    /// use palette::{LinSrgb, LinSrgba};
21    /// use palette::blend::{BlendWith, PreAlpha};
22    ///
23    /// type PreRgba = PreAlpha<LinSrgb<f32>>;
24    ///
25    /// fn blend_mode(a: PreRgba, b: PreRgba) -> PreRgba {
26    ///    PreAlpha {
27    ///        color: LinSrgb::new(a.red * b.green, a.green * b.blue, a.blue * b.red),
28    ///        alpha: a.alpha * b.alpha,
29    ///    }
30    /// }
31    ///
32    /// let a = LinSrgba::new(0.2, 0.5, 0.1, 0.8);
33    /// let b = LinSrgba::new(0.6, 0.3, 0.5, 0.1);
34    /// let c = a.blend_with(b, blend_mode);
35    /// ```
36    #[must_use]
37    fn blend_with<F>(self, destination: Self, blend_function: F) -> Self
38    where
39        F: BlendFunction<Self::Color>;
40}
41
42impl<C> BlendWith for PreAlpha<C>
43where
44    C: Premultiply,
45{
46    type Color = C;
47
48    #[inline]
49    fn blend_with<F>(self, other: Self, blend_function: F) -> Self
50    where
51        F: BlendFunction<Self::Color>,
52    {
53        blend_function.apply_to(self, other)
54    }
55}
56
57impl<C> BlendWith for Alpha<C, C::Scalar>
58where
59    C: Premultiply,
60{
61    type Color = C;
62
63    fn blend_with<F>(self, destination: Self, blend_function: F) -> Self
64    where
65        F: crate::blend::BlendFunction<Self::Color>,
66    {
67        self.premultiply()
68            .blend_with(destination.premultiply(), blend_function)
69            .unpremultiply()
70    }
71}
72
73impl<C> BlendWith for C
74where
75    C: Premultiply,
76    C::Scalar: Stimulus,
77{
78    type Color = C;
79
80    fn blend_with<F>(self, other: Self, blend_function: F) -> Self
81    where
82        F: BlendFunction<Self::Color>,
83    {
84        PreAlpha::new_opaque(self)
85            .blend_with(PreAlpha::new_opaque(other), blend_function)
86            .unpremultiply()
87            .color
88    }
89}