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}