Skip to main content

material_colors/scheme/variant/
content.rs

1use crate::{
2    dislike::fix_if_disliked,
3    dynamic_color::{DynamicScheme, Variant},
4    hct::Hct,
5    palette::{Palette, TonalPalette},
6    temperature::TemperatureCache,
7};
8
9pub struct SchemeContent {
10    pub scheme: DynamicScheme,
11}
12
13impl SchemeContent {
14    pub fn new(source_color_hct: Hct, is_dark: bool, contrast_level: Option<f64>) -> Self {
15        Self {
16            scheme: DynamicScheme::new(
17                source_color_hct.into(),
18                Some(source_color_hct),
19                Variant::Content,
20                is_dark,
21                contrast_level,
22                Self::palette(&source_color_hct, &Palette::Primary),
23                Self::palette(&source_color_hct, &Palette::Secondary),
24                Self::palette(&source_color_hct, &Palette::Tertiary),
25                Self::palette(&source_color_hct, &Palette::Neutral),
26                Self::palette(&source_color_hct, &Palette::NeutralVariant),
27                None,
28            ),
29        }
30    }
31
32    pub fn palette(source_color_hct: &Hct, variant: &Palette) -> TonalPalette {
33        match variant {
34            Palette::Primary => {
35                TonalPalette::of(source_color_hct.get_hue(), source_color_hct.get_chroma())
36            }
37            Palette::Secondary => TonalPalette::of(
38                source_color_hct.get_hue(),
39                (source_color_hct.get_chroma() - 32.0).max(source_color_hct.get_chroma() * 0.5),
40            ),
41            Palette::Tertiary => TonalPalette::from_hct(fix_if_disliked(
42                *TemperatureCache::new(*source_color_hct)
43                    .analogous(Some(3), Some(6))
44                    .last()
45                    .unwrap(),
46            )),
47            Palette::Error => TonalPalette::of(25.0, 84.0),
48            Palette::Neutral => TonalPalette::of(
49                source_color_hct.get_hue(),
50                source_color_hct.get_chroma() / 8.0,
51            ),
52            Palette::NeutralVariant => TonalPalette::of(
53                source_color_hct.get_hue(),
54                (source_color_hct.get_chroma() / 8.0) + 4.0,
55            ),
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use crate::color::Argb;
63    use crate::dynamic_color::MaterialDynamicColors;
64
65    use super::SchemeContent;
66
67    #[test]
68    fn test_light_theme_min_contrast_objectionabe_tertiary_container_lightens() {
69        let scheme =
70            SchemeContent::new(Argb::from_u32(0xff850096).into(), false, Some(-1.0)).scheme;
71
72        assert_eq!(
73            MaterialDynamicColors::tertiary_container().get_argb(&scheme),
74            Argb::from_u32(0xffffccd7)
75        );
76    }
77
78    #[test]
79    fn test_light_theme_standard_contrast_objectionabe_tertiary_container_lightens() {
80        let scheme = SchemeContent::new(Argb::from_u32(0xff850096).into(), false, Some(0.0)).scheme;
81
82        assert_eq!(
83            MaterialDynamicColors::tertiary_container().get_argb(&scheme),
84            Argb::from_u32(0xff980249)
85        );
86    }
87
88    #[test]
89    fn test_light_theme_max_contrast_objectionabe_tertiary_container_darkens() {
90        let scheme = SchemeContent::new(Argb::from_u32(0xff850096).into(), false, Some(1.0)).scheme;
91
92        assert_eq!(
93            MaterialDynamicColors::tertiary_container().get_argb(&scheme),
94            Argb::from_u32(0xff930046)
95        );
96    }
97}