material_color_utilities_rs/
scheme.rs

1use crate::palettes::core::CorePalette;
2#[cfg(feature = "serde")]
3use crate::util::color::format_argb_as_rgb;
4#[cfg(feature = "serde")]
5use serde::{ser::SerializeStruct, Serialize};
6
7/// Represents a Material color scheme, a mapping of color roles to colors.
8#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
9pub struct Scheme {
10    pub primary: [u8; 4],
11    pub on_primary: [u8; 4],
12    pub primary_container: [u8; 4],
13    pub on_primary_container: [u8; 4],
14    pub secondary: [u8; 4],
15    pub on_secondary: [u8; 4],
16    pub secondary_container: [u8; 4],
17    pub on_secondary_container: [u8; 4],
18    pub tertiary: [u8; 4],
19    pub on_tertiary: [u8; 4],
20    pub tertiary_container: [u8; 4],
21    pub on_tertiary_container: [u8; 4],
22    pub error: [u8; 4],
23    pub on_error: [u8; 4],
24    pub error_container: [u8; 4],
25    pub on_error_container: [u8; 4],
26    pub background: [u8; 4],
27    pub on_background: [u8; 4],
28    pub surface: [u8; 4],
29    pub on_surface: [u8; 4],
30    pub surface_variant: [u8; 4],
31    pub on_surface_variant: [u8; 4],
32    pub outline: [u8; 4],
33    pub outline_variant: [u8; 4],
34    pub shadow: [u8; 4],
35    pub scrim: [u8; 4],
36    pub inverse_surface: [u8; 4],
37    pub inverse_on_surface: [u8; 4],
38    pub inverse_primary: [u8; 4],
39}
40
41#[cfg(feature = "serde")]
42impl Serialize for Scheme {
43    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44    where
45        S: serde::Serializer,
46    {
47        let mut state = serializer.serialize_struct("Scheme", 29)?;
48
49        // Macro to serialize an ARGB field to its RGB representation, and reduce
50        // the risk of a typo between a field name and it's name in the output.
51        macro_rules! ser {
52            ($key:ident) => {
53                state.serialize_field(stringify!($key), &format_argb_as_rgb(self.$key))?;
54            };
55        }
56
57        ser!(primary);
58        ser!(on_primary);
59        ser!(primary_container);
60        ser!(on_primary_container);
61        ser!(secondary);
62        ser!(on_secondary);
63        ser!(secondary_container);
64        ser!(on_secondary_container);
65        ser!(tertiary);
66        ser!(on_tertiary);
67        ser!(tertiary_container);
68        ser!(on_tertiary_container);
69        ser!(error);
70        ser!(on_error);
71        ser!(error_container);
72        ser!(on_error_container);
73        ser!(background);
74        ser!(on_background);
75        ser!(surface);
76        ser!(on_surface);
77        ser!(surface_variant);
78        ser!(on_surface_variant);
79        ser!(outline);
80        ser!(outline_variant);
81        ser!(shadow);
82        ser!(scrim);
83        ser!(inverse_surface);
84        ser!(inverse_on_surface);
85        ser!(inverse_primary);
86
87        state.end()
88    }
89}
90
91impl Scheme {
92    pub fn light_from_core_palette(core: &mut CorePalette) -> Scheme {
93        Scheme {
94            primary: core.a1.tone(40),
95            on_primary: core.a1.tone(100),
96            primary_container: core.a1.tone(90),
97            on_primary_container: core.a1.tone(10),
98            secondary: core.a2.tone(40),
99            on_secondary: core.a2.tone(100),
100            secondary_container: core.a2.tone(90),
101            on_secondary_container: core.a2.tone(10),
102            tertiary: core.a3.tone(40),
103            on_tertiary: core.a3.tone(100),
104            tertiary_container: core.a3.tone(90),
105            on_tertiary_container: core.a3.tone(10),
106            error: core.error.tone(40),
107            on_error: core.error.tone(100),
108            error_container: core.error.tone(90),
109            on_error_container: core.error.tone(10),
110            background: core.n1.tone(99),
111            on_background: core.n1.tone(10),
112            surface: core.n1.tone(99),
113            on_surface: core.n1.tone(10),
114            surface_variant: core.n2.tone(90),
115            on_surface_variant: core.n2.tone(30),
116            outline: core.n2.tone(50),
117            outline_variant: core.n2.tone(80),
118            shadow: core.n1.tone(0),
119            scrim: core.n1.tone(0),
120            inverse_surface: core.n1.tone(20),
121            inverse_on_surface: core.n1.tone(95),
122            inverse_primary: core.a1.tone(80),
123        }
124    }
125
126    pub fn dark_from_core_palette(core: &mut CorePalette) -> Scheme {
127        Scheme {
128            primary: core.a1.tone(80),
129            on_primary: core.a1.tone(20),
130            primary_container: core.a1.tone(30),
131            on_primary_container: core.a1.tone(90),
132            secondary: core.a2.tone(80),
133            on_secondary: core.a2.tone(20),
134            secondary_container: core.a2.tone(30),
135            on_secondary_container: core.a2.tone(90),
136            tertiary: core.a3.tone(80),
137            on_tertiary: core.a3.tone(20),
138            tertiary_container: core.a3.tone(30),
139            on_tertiary_container: core.a3.tone(90),
140            error: core.error.tone(80),
141            on_error: core.error.tone(20),
142            error_container: core.error.tone(30),
143            on_error_container: core.error.tone(80),
144            background: core.n1.tone(10),
145            on_background: core.n1.tone(90),
146            surface: core.n1.tone(10),
147            on_surface: core.n1.tone(90),
148            surface_variant: core.n2.tone(30),
149            on_surface_variant: core.n2.tone(80),
150            outline: core.n2.tone(60),
151            outline_variant: core.n2.tone(30),
152            shadow: core.n1.tone(0),
153            scrim: core.n1.tone(0),
154            inverse_surface: core.n1.tone(90),
155            inverse_on_surface: core.n1.tone(20),
156            inverse_primary: core.a1.tone(40),
157        }
158    }
159}