Skip to main content

material_colors/scheme/variant/
expressive.rs

1use crate::{
2    dynamic_color::{DynamicScheme, Variant},
3    hct::Hct,
4    palette::{Palette, TonalPalette},
5    utils::math::sanitize_degrees_double,
6};
7
8/// A Dynamic Color theme that is intentionally detached from the input color.
9pub struct SchemeExpressive {
10    pub scheme: DynamicScheme,
11}
12
13impl SchemeExpressive {
14    /// Hues used at breakpoints such that designers can specify a hue rotation
15    /// that occurs at a given break point.
16    pub const HUES: [f64; 9] = [0.0, 21.0, 51.0, 121.0, 151.0, 191.0, 271.0, 321.0, 360.0];
17
18    /// Hue rotations of the Secondary [`TonalPalette`], corresponding to the
19    /// breakpoints in `hues`.
20    pub const SECONDARY_ROTATIONS: [f64; 9] =
21        [45.0, 95.0, 45.0, 20.0, 45.0, 90.0, 45.0, 45.0, 45.0];
22
23    /// Hue rotations of the Tertiary [`TonalPalette`], corresponding to the
24    /// breakpoints in `hues`.
25    pub const TERTIARY_ROTATIONS: [f64; 9] =
26        [120.0, 120.0, 20.0, 45.0, 20.0, 15.0, 20.0, 120.0, 120.0];
27
28    pub fn new(source_color_hct: Hct, is_dark: bool, contrast_level: Option<f64>) -> Self {
29        Self {
30            scheme: DynamicScheme::new(
31                source_color_hct.into(),
32                None,
33                Variant::Expressive,
34                is_dark,
35                contrast_level,
36                Self::palette(&source_color_hct, &Palette::Primary),
37                Self::palette(&source_color_hct, &Palette::Secondary),
38                Self::palette(&source_color_hct, &Palette::Tertiary),
39                Self::palette(&source_color_hct, &Palette::Neutral),
40                Self::palette(&source_color_hct, &Palette::NeutralVariant),
41                None,
42            ),
43        }
44    }
45
46    pub fn palette(source_color_hct: &Hct, variant: &Palette) -> TonalPalette {
47        match variant {
48            Palette::Primary => TonalPalette::of(
49                sanitize_degrees_double(source_color_hct.get_hue() + 240.0),
50                40.0,
51            ),
52            Palette::Secondary => TonalPalette::of(
53                DynamicScheme::get_rotated_hue(
54                    source_color_hct.get_hue(),
55                    &Self::HUES,
56                    &Self::SECONDARY_ROTATIONS,
57                ),
58                24.0,
59            ),
60            Palette::Tertiary => TonalPalette::of(
61                DynamicScheme::get_rotated_hue(
62                    source_color_hct.get_hue(),
63                    &Self::HUES,
64                    &Self::TERTIARY_ROTATIONS,
65                ),
66                32.0,
67            ),
68            Palette::Error => TonalPalette::of(25.0, 84.0),
69            Palette::Neutral => TonalPalette::of(source_color_hct.get_hue() + 15.0, 8.0),
70            Palette::NeutralVariant => TonalPalette::of(source_color_hct.get_hue() + 15.0, 12.0),
71        }
72    }
73}