use crate::{
ColorSpecDelegate, ColorSpecDelegateImpl2021, ColorSpecDelegateImpl2025, DynamicColor,
DynamicScheme, SpecVersion,
};
pub struct MaterialDynamicColors;
impl MaterialDynamicColors {
pub const CONTENT_ACCENT_TONE_DELTA: f64 = 15.0;
fn get_color_spec(scheme: &DynamicScheme) -> &'static dyn ColorSpecDelegate {
static SPEC_2021: ColorSpecDelegateImpl2021 = ColorSpecDelegateImpl2021;
static SPEC_2025: ColorSpecDelegateImpl2025 = ColorSpecDelegateImpl2025;
match scheme.spec_version {
SpecVersion::Spec2025 => &SPEC_2025,
SpecVersion::Spec2021 => &SPEC_2021,
}
}
fn get_default_color_spec() -> &'static ColorSpecDelegateImpl2021 {
static SPEC: ColorSpecDelegateImpl2021 = ColorSpecDelegateImpl2021;
&SPEC
}
pub fn highest_surface(scheme: &DynamicScheme) -> DynamicColor {
let spec = Self::get_color_spec(scheme);
if scheme.is_dark {
spec.surface_bright()
} else {
spec.surface_dim()
}
}
pub fn primary_palette_key_color() -> DynamicColor {
Self::get_default_color_spec().primary_palette_key_color()
}
pub fn secondary_palette_key_color() -> DynamicColor {
Self::get_default_color_spec().secondary_palette_key_color()
}
pub fn tertiary_palette_key_color() -> DynamicColor {
Self::get_default_color_spec().tertiary_palette_key_color()
}
pub fn neutral_palette_key_color() -> DynamicColor {
Self::get_default_color_spec().neutral_palette_key_color()
}
pub fn neutral_variant_palette_key_color() -> DynamicColor {
Self::get_default_color_spec().neutral_variant_palette_key_color()
}
pub fn error_palette_key_color() -> DynamicColor {
Self::get_default_color_spec().error_palette_key_color()
}
pub fn background() -> DynamicColor {
Self::get_default_color_spec().background()
}
pub fn on_background() -> DynamicColor {
Self::get_default_color_spec().on_background()
}
pub fn surface() -> DynamicColor {
Self::get_default_color_spec().surface()
}
pub fn surface_dim() -> DynamicColor {
Self::get_default_color_spec().surface_dim()
}
pub fn surface_bright() -> DynamicColor {
Self::get_default_color_spec().surface_bright()
}
pub fn surface_container_lowest() -> DynamicColor {
Self::get_default_color_spec().surface_container_lowest()
}
pub fn surface_container_low() -> DynamicColor {
Self::get_default_color_spec().surface_container_low()
}
pub fn surface_container() -> DynamicColor {
Self::get_default_color_spec().surface_container()
}
pub fn surface_container_high() -> DynamicColor {
Self::get_default_color_spec().surface_container_high()
}
pub fn surface_container_highest() -> DynamicColor {
Self::get_default_color_spec().surface_container_highest()
}
pub fn on_surface() -> DynamicColor {
Self::get_default_color_spec().on_surface()
}
pub fn surface_variant() -> DynamicColor {
Self::get_default_color_spec().surface_variant()
}
pub fn on_surface_variant() -> DynamicColor {
Self::get_default_color_spec().on_surface_variant()
}
pub fn inverse_surface() -> DynamicColor {
Self::get_default_color_spec().inverse_surface()
}
pub fn inverse_on_surface() -> DynamicColor {
Self::get_default_color_spec().inverse_on_surface()
}
pub fn outline() -> DynamicColor {
Self::get_default_color_spec().outline()
}
pub fn outline_variant() -> DynamicColor {
Self::get_default_color_spec().outline_variant()
}
pub fn shadow() -> DynamicColor {
Self::get_default_color_spec().shadow()
}
pub fn scrim() -> DynamicColor {
Self::get_default_color_spec().scrim()
}
pub fn surface_tint() -> DynamicColor {
Self::get_default_color_spec().surface_tint()
}
pub fn primary() -> DynamicColor {
Self::get_default_color_spec().primary()
}
pub fn primary_dim() -> Option<DynamicColor> {
Self::get_default_color_spec().primary_dim()
}
pub fn on_primary() -> DynamicColor {
Self::get_default_color_spec().on_primary()
}
pub fn primary_container() -> DynamicColor {
Self::get_default_color_spec().primary_container()
}
pub fn on_primary_container() -> DynamicColor {
Self::get_default_color_spec().on_primary_container()
}
pub fn inverse_primary() -> DynamicColor {
Self::get_default_color_spec().inverse_primary()
}
pub fn primary_fixed() -> DynamicColor {
Self::get_default_color_spec().primary_fixed()
}
pub fn primary_fixed_dim() -> DynamicColor {
Self::get_default_color_spec().primary_fixed_dim()
}
pub fn on_primary_fixed() -> DynamicColor {
Self::get_default_color_spec().on_primary_fixed()
}
pub fn on_primary_fixed_variant() -> DynamicColor {
Self::get_default_color_spec().on_primary_fixed_variant()
}
pub fn primary_fixed_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).primary_fixed()
}
pub fn primary_fixed_dim_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).primary_fixed_dim()
}
pub fn on_primary_fixed_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_primary_fixed()
}
pub fn on_primary_fixed_variant_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_primary_fixed_variant()
}
pub fn secondary() -> DynamicColor {
Self::get_default_color_spec().secondary()
}
pub fn secondary_dim() -> Option<DynamicColor> {
Self::get_default_color_spec().secondary_dim()
}
pub fn on_secondary() -> DynamicColor {
Self::get_default_color_spec().on_secondary()
}
pub fn secondary_container() -> DynamicColor {
Self::get_default_color_spec().secondary_container()
}
pub fn on_secondary_container() -> DynamicColor {
Self::get_default_color_spec().on_secondary_container()
}
pub fn secondary_fixed() -> DynamicColor {
Self::get_default_color_spec().secondary_fixed()
}
pub fn secondary_fixed_dim() -> DynamicColor {
Self::get_default_color_spec().secondary_fixed_dim()
}
pub fn on_secondary_fixed() -> DynamicColor {
Self::get_default_color_spec().on_secondary_fixed()
}
pub fn on_secondary_fixed_variant() -> DynamicColor {
Self::get_default_color_spec().on_secondary_fixed_variant()
}
pub fn secondary_fixed_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).secondary_fixed()
}
pub fn secondary_fixed_dim_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).secondary_fixed_dim()
}
pub fn on_secondary_fixed_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_secondary_fixed()
}
pub fn on_secondary_fixed_variant_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_secondary_fixed_variant()
}
pub fn tertiary() -> DynamicColor {
Self::get_default_color_spec().tertiary()
}
pub fn tertiary_dim() -> Option<DynamicColor> {
Self::get_default_color_spec().tertiary_dim()
}
pub fn on_tertiary() -> DynamicColor {
Self::get_default_color_spec().on_tertiary()
}
pub fn tertiary_container() -> DynamicColor {
Self::get_default_color_spec().tertiary_container()
}
pub fn on_tertiary_container() -> DynamicColor {
Self::get_default_color_spec().on_tertiary_container()
}
pub fn tertiary_fixed() -> DynamicColor {
Self::get_default_color_spec().tertiary_fixed()
}
pub fn tertiary_fixed_dim() -> DynamicColor {
Self::get_default_color_spec().tertiary_fixed_dim()
}
pub fn on_tertiary_fixed() -> DynamicColor {
Self::get_default_color_spec().on_tertiary_fixed()
}
pub fn on_tertiary_fixed_variant() -> DynamicColor {
Self::get_default_color_spec().on_tertiary_fixed_variant()
}
pub fn tertiary_fixed_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).tertiary_fixed()
}
pub fn tertiary_fixed_dim_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).tertiary_fixed_dim()
}
pub fn on_tertiary_fixed_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_tertiary_fixed()
}
pub fn on_tertiary_fixed_variant_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_tertiary_fixed_variant()
}
pub fn error() -> DynamicColor {
Self::get_default_color_spec().error()
}
pub fn error_dim() -> Option<DynamicColor> {
Self::get_default_color_spec().error_dim()
}
pub fn on_error() -> DynamicColor {
Self::get_default_color_spec().on_error()
}
pub fn error_container() -> DynamicColor {
Self::get_default_color_spec().error_container()
}
pub fn on_error_container() -> DynamicColor {
Self::get_default_color_spec().on_error_container()
}
pub fn all_colors() -> Vec<DynamicColor> {
let mut colors = vec![
Self::background(),
Self::on_background(),
Self::surface(),
Self::surface_dim(),
Self::surface_bright(),
Self::surface_container_lowest(),
Self::surface_container_low(),
Self::surface_container(),
Self::surface_container_high(),
Self::surface_container_highest(),
Self::on_surface(),
Self::on_surface_variant(),
Self::outline(),
Self::outline_variant(),
Self::inverse_surface(),
Self::inverse_on_surface(),
Self::primary(),
Self::on_primary(),
Self::primary_container(),
Self::on_primary_container(),
Self::primary_fixed(),
Self::primary_fixed_dim(),
Self::on_primary_fixed(),
Self::on_primary_fixed_variant(),
Self::inverse_primary(),
Self::secondary(),
Self::on_secondary(),
Self::secondary_container(),
Self::on_secondary_container(),
Self::secondary_fixed(),
Self::secondary_fixed_dim(),
Self::on_secondary_fixed(),
Self::on_secondary_fixed_variant(),
Self::tertiary(),
Self::on_tertiary(),
Self::tertiary_container(),
Self::on_tertiary_container(),
Self::tertiary_fixed(),
Self::tertiary_fixed_dim(),
Self::on_tertiary_fixed(),
Self::on_tertiary_fixed_variant(),
Self::error(),
Self::on_error(),
Self::error_container(),
Self::on_error_container(),
];
if let Some(color) = Self::primary_dim() {
colors.push(color);
}
if let Some(color) = Self::secondary_dim() {
colors.push(color);
}
if let Some(color) = Self::tertiary_dim() {
colors.push(color);
}
if let Some(color) = Self::error_dim() {
colors.push(color);
}
colors
}
pub fn primary_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).primary()
}
pub fn on_primary_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_primary()
}
pub fn primary_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).primary_container()
}
pub fn on_primary_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_primary_container()
}
pub fn secondary_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).secondary()
}
pub fn on_secondary_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_secondary()
}
pub fn secondary_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).secondary_container()
}
pub fn on_secondary_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_secondary_container()
}
pub fn tertiary_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).tertiary()
}
pub fn on_tertiary_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_tertiary()
}
pub fn tertiary_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).tertiary_container()
}
pub fn on_tertiary_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_tertiary_container()
}
pub fn error_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).error()
}
pub fn on_error_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_error()
}
pub fn error_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).error_container()
}
pub fn on_error_container_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_error_container()
}
pub fn surface_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).surface()
}
pub fn on_surface_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_surface()
}
pub fn surface_variant_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).surface_variant()
}
pub fn on_surface_variant_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_surface_variant()
}
pub fn background_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).background()
}
pub fn on_background_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).on_background()
}
pub fn outline_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).outline()
}
pub fn outline_variant_for(scheme: &DynamicScheme) -> DynamicColor {
Self::get_color_spec(scheme).outline_variant()
}
pub fn primary_dim_for(scheme: &DynamicScheme) -> Option<DynamicColor> {
Self::get_color_spec(scheme).primary_dim()
}
pub fn secondary_dim_for(scheme: &DynamicScheme) -> Option<DynamicColor> {
Self::get_color_spec(scheme).secondary_dim()
}
pub fn tertiary_dim_for(scheme: &DynamicScheme) -> Option<DynamicColor> {
Self::get_color_spec(scheme).tertiary_dim()
}
pub fn error_dim_for(scheme: &DynamicScheme) -> Option<DynamicColor> {
Self::get_color_spec(scheme).error_dim()
}
pub fn all_colors_for(scheme: &DynamicScheme) -> Vec<DynamicColor> {
let spec = Self::get_color_spec(scheme);
let mut colors = vec![
spec.background(),
spec.on_background(),
spec.surface(),
spec.surface_dim(),
spec.surface_bright(),
spec.surface_container_lowest(),
spec.surface_container_low(),
spec.surface_container(),
spec.surface_container_high(),
spec.surface_container_highest(),
spec.on_surface(),
spec.on_surface_variant(),
spec.outline(),
spec.outline_variant(),
spec.inverse_surface(),
spec.inverse_on_surface(),
spec.primary(),
spec.on_primary(),
spec.primary_container(),
spec.on_primary_container(),
spec.primary_fixed(),
spec.primary_fixed_dim(),
spec.on_primary_fixed(),
spec.on_primary_fixed_variant(),
spec.inverse_primary(),
spec.secondary(),
spec.on_secondary(),
spec.secondary_container(),
spec.on_secondary_container(),
spec.secondary_fixed(),
spec.secondary_fixed_dim(),
spec.on_secondary_fixed(),
spec.on_secondary_fixed_variant(),
spec.tertiary(),
spec.on_tertiary(),
spec.tertiary_container(),
spec.on_tertiary_container(),
spec.tertiary_fixed(),
spec.tertiary_fixed_dim(),
spec.on_tertiary_fixed(),
spec.on_tertiary_fixed_variant(),
spec.error(),
spec.on_error(),
spec.error_container(),
spec.on_error_container(),
];
if let Some(color) = spec.primary_dim() {
colors.push(color);
}
if let Some(color) = spec.secondary_dim() {
colors.push(color);
}
if let Some(color) = spec.tertiary_dim() {
colors.push(color);
}
if let Some(color) = spec.error_dim() {
colors.push(color);
}
colors
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{DynamicSchemeOptions, Variant};
use mcu_hct::Hct;
#[test]
fn test_material_dynamic_colors_methods_exist() {
let _ = MaterialDynamicColors::primary_palette_key_color();
let _ = MaterialDynamicColors::secondary_palette_key_color();
let _ = MaterialDynamicColors::tertiary_palette_key_color();
let _ = MaterialDynamicColors::neutral_palette_key_color();
let _ = MaterialDynamicColors::neutral_variant_palette_key_color();
let _ = MaterialDynamicColors::error_palette_key_color();
}
#[test]
fn test_surface_colors_exist() {
let _ = MaterialDynamicColors::background();
let _ = MaterialDynamicColors::on_background();
let _ = MaterialDynamicColors::surface();
let _ = MaterialDynamicColors::surface_dim();
let _ = MaterialDynamicColors::surface_bright();
let _ = MaterialDynamicColors::surface_container_lowest();
let _ = MaterialDynamicColors::surface_container_low();
let _ = MaterialDynamicColors::surface_container();
let _ = MaterialDynamicColors::surface_container_high();
let _ = MaterialDynamicColors::surface_container_highest();
let _ = MaterialDynamicColors::on_surface();
let _ = MaterialDynamicColors::surface_variant();
let _ = MaterialDynamicColors::on_surface_variant();
}
#[test]
fn test_primary_colors_exist() {
let _ = MaterialDynamicColors::primary();
let _ = MaterialDynamicColors::on_primary();
let _ = MaterialDynamicColors::primary_container();
let _ = MaterialDynamicColors::on_primary_container();
let _ = MaterialDynamicColors::inverse_primary();
let _ = MaterialDynamicColors::primary_fixed();
let _ = MaterialDynamicColors::primary_fixed_dim();
let _ = MaterialDynamicColors::on_primary_fixed();
let _ = MaterialDynamicColors::on_primary_fixed_variant();
}
#[test]
fn test_secondary_colors_exist() {
let _ = MaterialDynamicColors::secondary();
let _ = MaterialDynamicColors::on_secondary();
let _ = MaterialDynamicColors::secondary_container();
let _ = MaterialDynamicColors::on_secondary_container();
let _ = MaterialDynamicColors::secondary_fixed();
let _ = MaterialDynamicColors::secondary_fixed_dim();
let _ = MaterialDynamicColors::on_secondary_fixed();
let _ = MaterialDynamicColors::on_secondary_fixed_variant();
}
#[test]
fn test_tertiary_colors_exist() {
let _ = MaterialDynamicColors::tertiary();
let _ = MaterialDynamicColors::on_tertiary();
let _ = MaterialDynamicColors::tertiary_container();
let _ = MaterialDynamicColors::on_tertiary_container();
let _ = MaterialDynamicColors::tertiary_fixed();
let _ = MaterialDynamicColors::tertiary_fixed_dim();
let _ = MaterialDynamicColors::on_tertiary_fixed();
let _ = MaterialDynamicColors::on_tertiary_fixed_variant();
}
#[test]
fn test_error_colors_exist() {
let _ = MaterialDynamicColors::error();
let _ = MaterialDynamicColors::on_error();
let _ = MaterialDynamicColors::error_container();
let _ = MaterialDynamicColors::on_error_container();
}
#[test]
fn test_utility_colors_exist() {
let _ = MaterialDynamicColors::outline();
let _ = MaterialDynamicColors::outline_variant();
let _ = MaterialDynamicColors::shadow();
let _ = MaterialDynamicColors::scrim();
let _ = MaterialDynamicColors::surface_tint();
}
#[test]
fn test_highest_surface_light_mode() {
let hct = Hct::from_int(0xFF0000FF);
let options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
let scheme = DynamicScheme::new(options);
let highest = MaterialDynamicColors::highest_surface(&scheme);
let tone = highest.get_tone(&scheme);
assert_eq!(tone, 87.0);
}
#[test]
fn test_highest_surface_dark_mode() {
let hct = Hct::from_int(0xFF0000FF);
let options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, true);
let scheme = DynamicScheme::new(options);
let highest = MaterialDynamicColors::highest_surface(&scheme);
let tone = highest.get_tone(&scheme);
assert_eq!(tone, 24.0);
}
#[test]
fn test_content_accent_tone_delta_constant() {
assert_eq!(MaterialDynamicColors::CONTENT_ACCENT_TONE_DELTA, 15.0);
}
#[test]
fn test_all_colors_returns_vector() {
let colors = MaterialDynamicColors::all_colors();
assert!(colors.len() >= 44);
}
#[test]
fn test_optional_dim_colors() {
let primary_dim = MaterialDynamicColors::primary_dim();
let secondary_dim = MaterialDynamicColors::secondary_dim();
let tertiary_dim = MaterialDynamicColors::tertiary_dim();
let error_dim = MaterialDynamicColors::error_dim();
assert!(primary_dim.is_none());
assert!(secondary_dim.is_none());
assert!(tertiary_dim.is_none());
assert!(error_dim.is_none());
}
#[test]
fn test_primary_tone_light_mode() {
let hct = Hct::from_int(0xFF0000FF);
let options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
let scheme = DynamicScheme::new(options);
let primary = MaterialDynamicColors::primary();
let tone = primary.get_tone(&scheme);
assert_eq!(tone, 40.0);
}
#[test]
fn test_primary_tone_dark_mode() {
let hct = Hct::from_int(0xFF0000FF);
let options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, true);
let scheme = DynamicScheme::new(options);
let primary = MaterialDynamicColors::primary();
let tone = primary.get_tone(&scheme);
assert_eq!(tone, 80.0);
}
#[test]
fn test_background_tone_light_mode() {
let hct = Hct::from_int(0xFF0000FF);
let options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
let scheme = DynamicScheme::new(options);
let background = MaterialDynamicColors::background();
let tone = background.get_tone(&scheme);
assert_eq!(tone, 98.0);
}
#[test]
fn test_background_tone_dark_mode() {
let hct = Hct::from_int(0xFF0000FF);
let options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, true);
let scheme = DynamicScheme::new(options);
let background = MaterialDynamicColors::background();
let tone = background.get_tone(&scheme);
assert_eq!(tone, 6.0);
}
#[test]
fn test_spec_aware_methods_route_correctly() {
let hct = Hct::from_int(0xFF0000FF);
let mut options_2021 = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options_2021.spec_version = Some(SpecVersion::Spec2021);
let scheme_2021 = DynamicScheme::new(options_2021);
let mut options_2025 = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options_2025.spec_version = Some(SpecVersion::Spec2025);
let scheme_2025 = DynamicScheme::new(options_2025);
let primary_2021 = MaterialDynamicColors::primary_for(&scheme_2021);
let primary_2025 = MaterialDynamicColors::primary_for(&scheme_2025);
let tone_2021 = primary_2021.get_tone(&scheme_2021);
let tone_2025 = primary_2025.get_tone(&scheme_2025);
assert!(tone_2021 >= 0.0 && tone_2021 <= 100.0);
assert!(tone_2025 >= 0.0 && tone_2025 <= 100.0);
}
#[test]
fn test_spec_aware_dim_colors_2025() {
let hct = Hct::from_int(0xFF0000FF);
let mut options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options.spec_version = Some(SpecVersion::Spec2025);
let scheme = DynamicScheme::new(options);
let primary_dim = MaterialDynamicColors::primary_dim_for(&scheme);
let secondary_dim = MaterialDynamicColors::secondary_dim_for(&scheme);
let tertiary_dim = MaterialDynamicColors::tertiary_dim_for(&scheme);
let error_dim = MaterialDynamicColors::error_dim_for(&scheme);
assert!(primary_dim.is_some());
assert!(secondary_dim.is_some());
assert!(tertiary_dim.is_some());
assert!(error_dim.is_some());
}
#[test]
fn test_spec_aware_dim_colors_2021() {
let hct = Hct::from_int(0xFF0000FF);
let mut options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options.spec_version = Some(SpecVersion::Spec2021);
let scheme = DynamicScheme::new(options);
let primary_dim = MaterialDynamicColors::primary_dim_for(&scheme);
let secondary_dim = MaterialDynamicColors::secondary_dim_for(&scheme);
let tertiary_dim = MaterialDynamicColors::tertiary_dim_for(&scheme);
let error_dim = MaterialDynamicColors::error_dim_for(&scheme);
assert!(primary_dim.is_none());
assert!(secondary_dim.is_none());
assert!(tertiary_dim.is_none());
assert!(error_dim.is_none());
}
#[test]
fn test_all_colors_for_2025_includes_dim() {
let hct = Hct::from_int(0xFF0000FF);
let mut options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options.spec_version = Some(SpecVersion::Spec2025);
let scheme = DynamicScheme::new(options);
let colors = MaterialDynamicColors::all_colors_for(&scheme);
assert_eq!(colors.len(), 49);
}
#[test]
fn test_all_colors_for_2021_no_dim() {
let hct = Hct::from_int(0xFF0000FF);
let mut options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options.spec_version = Some(SpecVersion::Spec2021);
let scheme = DynamicScheme::new(options);
let colors = MaterialDynamicColors::all_colors_for(&scheme);
assert_eq!(colors.len(), 45);
}
#[test]
fn test_fixed_dim_not_white_in_dark_mode_2025() {
let hct = Hct::from_int(0xFF50DCCD); let mut options = DynamicSchemeOptions::new(hct, Variant::Fidelity, 0.0, true);
options.spec_version = Some(SpecVersion::Spec2025);
let scheme = DynamicScheme::new(options);
let primary_fixed_dim = MaterialDynamicColors::primary_fixed_dim_for(&scheme);
let secondary_fixed_dim = MaterialDynamicColors::secondary_fixed_dim_for(&scheme);
let tertiary_fixed_dim = MaterialDynamicColors::tertiary_fixed_dim_for(&scheme);
let pfd_tone = primary_fixed_dim.get_tone(&scheme);
let sfd_tone = secondary_fixed_dim.get_tone(&scheme);
let tfd_tone = tertiary_fixed_dim.get_tone(&scheme);
assert!(pfd_tone < 100.0, "primary_fixed_dim tone was {pfd_tone}, expected < 100");
assert!(sfd_tone < 100.0, "secondary_fixed_dim tone was {sfd_tone}, expected < 100");
assert!(tfd_tone < 100.0, "tertiary_fixed_dim tone was {tfd_tone}, expected < 100");
assert!(pfd_tone > 50.0 && pfd_tone < 95.0,
"primary_fixed_dim tone {pfd_tone} out of expected range 50-95");
}
#[test]
fn test_fixed_for_methods_exist() {
let hct = Hct::from_int(0xFF0000FF);
let mut options = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options.spec_version = Some(SpecVersion::Spec2025);
let scheme = DynamicScheme::new(options);
let _ = MaterialDynamicColors::primary_fixed_for(&scheme);
let _ = MaterialDynamicColors::primary_fixed_dim_for(&scheme);
let _ = MaterialDynamicColors::on_primary_fixed_for(&scheme);
let _ = MaterialDynamicColors::on_primary_fixed_variant_for(&scheme);
let _ = MaterialDynamicColors::secondary_fixed_for(&scheme);
let _ = MaterialDynamicColors::secondary_fixed_dim_for(&scheme);
let _ = MaterialDynamicColors::on_secondary_fixed_for(&scheme);
let _ = MaterialDynamicColors::on_secondary_fixed_variant_for(&scheme);
let _ = MaterialDynamicColors::tertiary_fixed_for(&scheme);
let _ = MaterialDynamicColors::tertiary_fixed_dim_for(&scheme);
let _ = MaterialDynamicColors::on_tertiary_fixed_for(&scheme);
let _ = MaterialDynamicColors::on_tertiary_fixed_variant_for(&scheme);
}
#[test]
fn test_highest_surface_routes_by_spec() {
let hct = Hct::from_int(0xFF0000FF);
let mut options_2021 = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options_2021.spec_version = Some(SpecVersion::Spec2021);
let scheme_2021 = DynamicScheme::new(options_2021);
let mut options_2025 = DynamicSchemeOptions::new(hct, Variant::TonalSpot, 0.0, false);
options_2025.spec_version = Some(SpecVersion::Spec2025);
let scheme_2025 = DynamicScheme::new(options_2025);
let highest_2021 = MaterialDynamicColors::highest_surface(&scheme_2021);
let highest_2025 = MaterialDynamicColors::highest_surface(&scheme_2025);
let tone_2021 = highest_2021.get_tone(&scheme_2021);
let tone_2025 = highest_2025.get_tone(&scheme_2025);
assert!(tone_2021 >= 0.0 && tone_2021 <= 100.0);
assert!(tone_2025 >= 0.0 && tone_2025 <= 100.0);
}
}