use mcu_hct::Hct;
use crate::{DynamicColor, DynamicScheme, SpecVersion};
pub use crate::impl_calc_2021::ColorCalculationDelegate2021;
pub use crate::impl_calc_2025::ColorCalculationDelegate2025;
pub trait ColorCalculationDelegate: Send + Sync {
fn get_hct(&self, scheme: &DynamicScheme, color: &DynamicColor) -> Hct;
fn get_tone(&self, scheme: &DynamicScheme, color: &DynamicColor) -> f64;
}
static SPEC_2021: ColorCalculationDelegate2021 = ColorCalculationDelegate2021;
static SPEC_2025: ColorCalculationDelegate2025 = ColorCalculationDelegate2025;
pub fn get_spec(spec_version: SpecVersion) -> &'static dyn ColorCalculationDelegate {
match spec_version {
SpecVersion::Spec2021 => &SPEC_2021,
SpecVersion::Spec2025 => &SPEC_2025,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{ContrastCurve, DynamicSchemeOptions, Variant};
fn create_test_scheme() -> DynamicScheme {
let source_color = Hct::from_int(0xFF0000FF); let options = DynamicSchemeOptions::new(source_color, Variant::TonalSpot, 0.0, false);
DynamicScheme::new(options)
}
fn create_test_color() -> DynamicColor {
DynamicColor::from_palette(
"test",
|scheme: &DynamicScheme| scheme.primary_palette.clone(),
Some(|_scheme: &DynamicScheme| 40.0),
false,
None::<fn(&DynamicScheme) -> f64>,
None::<fn(&DynamicScheme) -> Option<DynamicColor>>,
None::<fn(&DynamicScheme) -> Option<DynamicColor>>,
None::<fn(&DynamicScheme) -> Option<ContrastCurve>>,
None::<fn(&DynamicScheme) -> Option<crate::ToneDeltaPair>>,
)
}
#[test]
fn test_get_spec_returns_correct_delegate() {
let delegate_2021 = get_spec(SpecVersion::Spec2021);
let delegate_2025 = get_spec(SpecVersion::Spec2025);
let scheme = create_test_scheme();
let color = create_test_color();
let tone_2021 = delegate_2021.get_tone(&scheme, &color);
let tone_2025 = delegate_2025.get_tone(&scheme, &color);
assert!(tone_2021 >= 0.0 && tone_2021 <= 100.0);
assert!(tone_2025 >= 0.0 && tone_2025 <= 100.0);
}
#[test]
fn test_delegate_2021_get_tone() {
let delegate = ColorCalculationDelegate2021;
let scheme = create_test_scheme();
let color = create_test_color();
let tone = delegate.get_tone(&scheme, &color);
assert_eq!(tone, 40.0);
}
#[test]
fn test_delegate_2025_get_tone() {
let delegate = ColorCalculationDelegate2025;
let scheme = create_test_scheme();
let color = create_test_color();
let tone = delegate.get_tone(&scheme, &color);
assert_eq!(tone, 40.0);
}
#[test]
fn test_delegate_2021_get_hct() {
let delegate = ColorCalculationDelegate2021;
let scheme = create_test_scheme();
let color = create_test_color();
let hct = delegate.get_hct(&scheme, &color);
assert!(hct.tone() >= 0.0 && hct.tone() <= 100.0);
assert!(hct.hue() >= 0.0 && hct.hue() < 360.0);
assert!(hct.chroma() >= 0.0);
}
#[test]
fn test_delegate_2025_get_hct() {
let delegate = ColorCalculationDelegate2025;
let scheme = create_test_scheme();
let color = create_test_color();
let hct = delegate.get_hct(&scheme, &color);
assert!(hct.tone() >= 0.0 && hct.tone() <= 100.0);
assert!(hct.hue() >= 0.0 && hct.hue() < 360.0);
assert!(hct.chroma() >= 0.0);
}
#[test]
fn test_delegate_2021_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<ColorCalculationDelegate2021>();
}
#[test]
fn test_delegate_2025_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<ColorCalculationDelegate2025>();
}
#[test]
fn test_static_delegates_are_accessible() {
let _: &dyn ColorCalculationDelegate = &SPEC_2021;
let _: &dyn ColorCalculationDelegate = &SPEC_2025;
}
}