use crate::dynamic::dynamic_color::DynamicColor;
use crate::dynamic::dynamic_scheme::DynamicScheme;
use crate::dynamic::variant::Variant;
use crate::hct::hct_color::Hct;
use crate::palettes::tonal_palette::TonalPalette;
use std::sync::Arc;
macro_rules! cached_color {
($spec:expr, $init:expr) => {{
static CACHE_2021: std::sync::OnceLock<std::sync::Arc<DynamicColor>> =
std::sync::OnceLock::new();
static CACHE_2025: std::sync::OnceLock<std::sync::Arc<DynamicColor>> =
std::sync::OnceLock::new();
static CACHE_2026: std::sync::OnceLock<std::sync::Arc<DynamicColor>> =
std::sync::OnceLock::new();
match $spec {
SpecVersion::Spec2021 => CACHE_2021.get_or_init(|| $init).clone(),
SpecVersion::Spec2025 => CACHE_2025.get_or_init(|| $init).clone(),
SpecVersion::Spec2026 => CACHE_2026.get_or_init(|| $init).clone(),
}
}};
}
macro_rules! cached_color_opt {
($spec:expr, $init:expr) => {{
static CACHE_2021: std::sync::OnceLock<Option<std::sync::Arc<DynamicColor>>> =
std::sync::OnceLock::new();
static CACHE_2025: std::sync::OnceLock<Option<std::sync::Arc<DynamicColor>>> =
std::sync::OnceLock::new();
static CACHE_2026: std::sync::OnceLock<Option<std::sync::Arc<DynamicColor>>> =
std::sync::OnceLock::new();
match $spec {
SpecVersion::Spec2021 => CACHE_2021.get_or_init(|| $init).clone(),
SpecVersion::Spec2025 => CACHE_2025.get_or_init(|| $init).clone(),
SpecVersion::Spec2026 => CACHE_2026.get_or_init(|| $init).clone(),
}
}};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SpecVersion {
Spec2021,
Spec2025,
Spec2026,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Platform {
Phone,
Watch,
}
pub trait ColorSpec: Send + Sync {
fn primary_palette_key_color(&self) -> Arc<DynamicColor>;
fn secondary_palette_key_color(&self) -> Arc<DynamicColor>;
fn tertiary_palette_key_color(&self) -> Arc<DynamicColor>;
fn neutral_palette_key_color(&self) -> Arc<DynamicColor>;
fn neutral_variant_palette_key_color(&self) -> Arc<DynamicColor>;
fn error_palette_key_color(&self) -> Arc<DynamicColor>;
fn background(&self) -> Arc<DynamicColor>;
fn on_background(&self) -> Arc<DynamicColor>;
fn surface(&self) -> Arc<DynamicColor>;
fn surface_dim(&self) -> Arc<DynamicColor>;
fn surface_bright(&self) -> Arc<DynamicColor>;
fn surface_container_lowest(&self) -> Arc<DynamicColor>;
fn surface_container_low(&self) -> Arc<DynamicColor>;
fn surface_container(&self) -> Arc<DynamicColor>;
fn surface_container_high(&self) -> Arc<DynamicColor>;
fn surface_container_highest(&self) -> Arc<DynamicColor>;
fn on_surface(&self) -> Arc<DynamicColor>;
fn surface_variant(&self) -> Arc<DynamicColor>;
fn on_surface_variant(&self) -> Arc<DynamicColor>;
fn inverse_surface(&self) -> Arc<DynamicColor>;
fn inverse_on_surface(&self) -> Arc<DynamicColor>;
fn outline(&self) -> Arc<DynamicColor>;
fn outline_variant(&self) -> Arc<DynamicColor>;
fn shadow(&self) -> Arc<DynamicColor>;
fn scrim(&self) -> Arc<DynamicColor>;
fn surface_tint(&self) -> Arc<DynamicColor>;
fn primary(&self) -> Arc<DynamicColor>;
fn primary_dim(&self) -> Option<Arc<DynamicColor>>;
fn on_primary(&self) -> Arc<DynamicColor>;
fn primary_container(&self) -> Arc<DynamicColor>;
fn on_primary_container(&self) -> Arc<DynamicColor>;
fn inverse_primary(&self) -> Arc<DynamicColor>;
fn secondary(&self) -> Arc<DynamicColor>;
fn secondary_dim(&self) -> Option<Arc<DynamicColor>>;
fn on_secondary(&self) -> Arc<DynamicColor>;
fn secondary_container(&self) -> Arc<DynamicColor>;
fn on_secondary_container(&self) -> Arc<DynamicColor>;
fn tertiary(&self) -> Arc<DynamicColor>;
fn tertiary_dim(&self) -> Option<Arc<DynamicColor>>;
fn on_tertiary(&self) -> Arc<DynamicColor>;
fn tertiary_container(&self) -> Arc<DynamicColor>;
fn on_tertiary_container(&self) -> Arc<DynamicColor>;
fn error(&self) -> Arc<DynamicColor>;
fn error_dim(&self) -> Option<Arc<DynamicColor>>;
fn on_error(&self) -> Arc<DynamicColor>;
fn error_container(&self) -> Arc<DynamicColor>;
fn on_error_container(&self) -> Arc<DynamicColor>;
fn primary_fixed(&self) -> Arc<DynamicColor>;
fn primary_fixed_dim(&self) -> Arc<DynamicColor>;
fn on_primary_fixed(&self) -> Arc<DynamicColor>;
fn on_primary_fixed_variant(&self) -> Arc<DynamicColor>;
fn secondary_fixed(&self) -> Arc<DynamicColor>;
fn secondary_fixed_dim(&self) -> Arc<DynamicColor>;
fn on_secondary_fixed(&self) -> Arc<DynamicColor>;
fn on_secondary_fixed_variant(&self) -> Arc<DynamicColor>;
fn tertiary_fixed(&self) -> Arc<DynamicColor>;
fn tertiary_fixed_dim(&self) -> Arc<DynamicColor>;
fn on_tertiary_fixed(&self) -> Arc<DynamicColor>;
fn on_tertiary_fixed_variant(&self) -> Arc<DynamicColor>;
fn highest_surface(&self, scheme: &DynamicScheme) -> Arc<DynamicColor>;
fn get_hct(&self, scheme: &DynamicScheme, color: &DynamicColor) -> Hct;
fn get_tone(&self, scheme: &DynamicScheme, color: &DynamicColor) -> f64;
fn get_primary_palette(
&self,
variant: Variant,
source_color_hct: &Hct,
is_dark: bool,
platform: Platform,
contrast_level: f64,
) -> TonalPalette;
fn get_secondary_palette(
&self,
variant: Variant,
source_color_hct: &Hct,
is_dark: bool,
platform: Platform,
contrast_level: f64,
) -> TonalPalette;
fn get_tertiary_palette(
&self,
variant: Variant,
source_color_hct: &Hct,
is_dark: bool,
platform: Platform,
contrast_level: f64,
) -> TonalPalette;
fn get_neutral_palette(
&self,
variant: Variant,
source_color_hct: &Hct,
is_dark: bool,
platform: Platform,
contrast_level: f64,
) -> TonalPalette;
fn get_neutral_variant_palette(
&self,
variant: Variant,
source_color_hct: &Hct,
is_dark: bool,
platform: Platform,
contrast_level: f64,
) -> TonalPalette;
fn get_error_palette(
&self,
variant: Variant,
source_color_hct: &Hct,
is_dark: bool,
platform: Platform,
contrast_level: f64,
) -> TonalPalette;
}