image_effects/colour/
gradient.rs

1use palette::{IntoColor, Lch, Hsl, FromColor, Oklch};
2
3// gradient logic
4pub enum GradientMethod {
5    LCH,
6    HSL,
7    OKLCH,
8}
9
10/// Defines a colour that can generate a gradient through Lch.
11/// 
12/// Should be auto-implemented by having a colour satisfy the trait bounds.
13pub trait IntoGradientLch: Sized + IntoColor<Lch> + FromColor<Lch> + Copy {
14    fn build_gradient_lch(self, shades: u16) -> Vec<Self> {
15        let step_size = 100.0 / (shades+1) as f32;
16
17        (1..shades)
18            .into_iter()
19            .map(|i| {
20                let mut color: Lch = self.into_color();
21                color.l = i as f32 * step_size;
22                Self::from_color(color)
23            })
24            .collect()
25    }
26}
27
28/// Defines a colour that can generate a gradient through Hsl.
29/// 
30/// Should be auto-implemented by having a colour satisfy the trait bounds.
31pub trait IntoGradientHsl: Sized + IntoColor<Hsl> + FromColor<Hsl> + Copy {
32    fn build_gradient_hsl(self, shades: u16) -> Vec<Self> {
33        let step_size = 1.0 / (shades+1) as f32;
34
35        (1..shades)
36            .into_iter()
37            .map(|i| {
38                let mut color: Hsl = self.into_color();
39                color.lightness = i as f32 * step_size;
40                Self::from_color(color)
41            })
42            .collect()
43    }
44}
45
46/// Defines a colour that can generate a gradient through Oklch. Tends to distort hues... unknown why.
47/// 
48/// Should be auto-implemented by having a colour satisfy the trait bounds.
49pub trait IntoGradientOklch: Sized + IntoColor<Oklch> + FromColor<Oklch> + Copy {
50    fn build_gradient_oklch(self, shades: u16) -> Vec<Self> {
51        let step_size = 1.0 / (shades+1) as f32;
52
53        (1..shades)
54            .into_iter()
55            .map(|i| {
56                let mut color: Oklch = self.into_color();
57                color.l = i as f32 * step_size;
58                Self::from_color(color)
59            })
60            .collect()
61    }
62}
63
64/// Defines a colour that can generate a gradient through all supported gradient methods.
65/// 
66/// Should be auto-implemented by having a colour satisfy the trait bounds.
67pub trait IntoGradient: IntoGradientHsl + IntoGradientLch + IntoGradientOklch {
68    fn build_gradient(self, shades: u16, method: GradientMethod) -> Vec<Self> {
69        match method {
70            GradientMethod::HSL => self.build_gradient_hsl(shades),
71            GradientMethod::LCH => self.build_gradient_lch(shades),
72            GradientMethod::OKLCH => self.build_gradient_oklch(shades),
73        }
74    }
75}
76
77// general implementations
78impl<C> IntoGradientHsl for C where 
79    C: Sized + IntoColor<Hsl> + FromColor<Hsl> + Copy {}
80
81impl<C> IntoGradientLch for C where 
82    C: Sized + IntoColor<Lch> + FromColor<Lch> + Copy {}
83
84impl<C> IntoGradientOklch for C where 
85    C: Sized + IntoColor<Oklch> + FromColor<Oklch> + Copy {}
86
87impl<C> IntoGradient for C where
88    C: IntoGradientHsl + IntoGradientLch + IntoGradientOklch {}