use mcu_dislike::DislikeAnalyzer;
use mcu_hct::Hct;
use mcu_palettes::TonalPalette;
use mcu_temperature::TemperatureCache;
use mcu_utils::math::sanitize_degrees_double;
use crate::dynamic_scheme_palettes::{
get_rotated_hue, DynamicSchemePalettesDelegate, HUES, SECONDARY_ROTATIONS_EXPRESSIVE,
TERTIARY_ROTATIONS_EXPRESSIVE, VIBRANT_SECONDARY_ROTATIONS, VIBRANT_TERTIARY_ROTATIONS,
};
use crate::{Platform, Variant};
pub struct DynamicSchemePalettesDelegateImpl2021;
impl DynamicSchemePalettesDelegate for DynamicSchemePalettesDelegateImpl2021 {
fn get_primary_palette(
&self,
variant: Variant,
source: &Hct,
_is_dark: bool,
_platform: Platform,
_contrast: f64,
) -> TonalPalette {
match variant {
Variant::Content | Variant::Fidelity => {
TonalPalette::from_hue_and_chroma(source.hue(), source.chroma())
}
Variant::FruitSalad => TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() - 50.0),
48.0,
),
Variant::Monochrome => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::Neutral => TonalPalette::from_hue_and_chroma(source.hue(), 12.0),
Variant::Rainbow => TonalPalette::from_hue_and_chroma(source.hue(), 48.0),
Variant::TonalSpot => TonalPalette::from_hue_and_chroma(source.hue(), 36.0),
Variant::Expressive => TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() + 240.0),
40.0,
),
Variant::Vibrant => TonalPalette::from_hue_and_chroma(source.hue(), 200.0),
}
}
fn get_secondary_palette(
&self,
variant: Variant,
source: &Hct,
_is_dark: bool,
_platform: Platform,
_contrast: f64,
) -> TonalPalette {
match variant {
Variant::Content => {
let chroma = (source.chroma() - 32.0).max(source.chroma() * 0.5);
TonalPalette::from_hue_and_chroma(source.hue(), chroma)
}
Variant::Fidelity => {
let chroma = (source.chroma() - 32.0).max(source.chroma() * 0.5);
TonalPalette::from_hue_and_chroma(source.hue(), chroma)
}
Variant::FruitSalad => TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() - 50.0),
36.0,
),
Variant::Monochrome => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::Neutral => TonalPalette::from_hue_and_chroma(source.hue(), 8.0),
Variant::Rainbow => TonalPalette::from_hue_and_chroma(source.hue(), 16.0),
Variant::TonalSpot => TonalPalette::from_hue_and_chroma(source.hue(), 16.0),
Variant::Expressive => {
let rotated_hue = get_rotated_hue(source, &HUES, &SECONDARY_ROTATIONS_EXPRESSIVE);
TonalPalette::from_hue_and_chroma(rotated_hue, 24.0)
}
Variant::Vibrant => {
let rotated_hue = get_rotated_hue(source, &HUES, &VIBRANT_SECONDARY_ROTATIONS);
TonalPalette::from_hue_and_chroma(rotated_hue, 24.0)
}
}
}
fn get_tertiary_palette(
&self,
variant: Variant,
source: &Hct,
_is_dark: bool,
_platform: Platform,
_contrast: f64,
) -> TonalPalette {
match variant {
Variant::Content => {
let mut cache = TemperatureCache::new(*source);
let analogous = cache.analogous(3, 6);
if analogous.len() > 2 {
let tertiary_hct = analogous[2];
let fixed = DislikeAnalyzer::fix_if_disliked(&tertiary_hct);
TonalPalette::from_hue_and_chroma(fixed.hue(), fixed.chroma())
} else {
TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() + 60.0),
source.chroma(),
)
}
}
Variant::Fidelity => {
let mut cache = TemperatureCache::new(*source);
let complement = cache.complement();
let fixed = DislikeAnalyzer::fix_if_disliked(&complement);
TonalPalette::from_hue_and_chroma(fixed.hue(), fixed.chroma())
}
Variant::FruitSalad => TonalPalette::from_hue_and_chroma(source.hue(), 36.0),
Variant::Monochrome => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::Neutral => TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() + 60.0),
12.0,
),
Variant::Rainbow | Variant::TonalSpot => TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() + 60.0),
24.0,
),
Variant::Expressive => {
let rotated_hue = get_rotated_hue(source, &HUES, &TERTIARY_ROTATIONS_EXPRESSIVE);
TonalPalette::from_hue_and_chroma(rotated_hue, 32.0)
}
Variant::Vibrant => {
let rotated_hue = get_rotated_hue(source, &HUES, &VIBRANT_TERTIARY_ROTATIONS);
TonalPalette::from_hue_and_chroma(rotated_hue, 32.0)
}
}
}
fn get_neutral_palette(
&self,
variant: Variant,
source: &Hct,
_is_dark: bool,
_platform: Platform,
_contrast: f64,
) -> TonalPalette {
match variant {
Variant::Content | Variant::Fidelity => {
TonalPalette::from_hue_and_chroma(source.hue(), source.chroma() / 8.0)
}
Variant::FruitSalad => TonalPalette::from_hue_and_chroma(source.hue(), 10.0),
Variant::Monochrome => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::Neutral => TonalPalette::from_hue_and_chroma(source.hue(), 2.0),
Variant::Rainbow => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::TonalSpot => TonalPalette::from_hue_and_chroma(source.hue(), 6.0),
Variant::Expressive => {
TonalPalette::from_hue_and_chroma(sanitize_degrees_double(source.hue() + 15.0), 8.0)
}
Variant::Vibrant => TonalPalette::from_hue_and_chroma(source.hue(), 10.0),
}
}
fn get_neutral_variant_palette(
&self,
variant: Variant,
source: &Hct,
_is_dark: bool,
_platform: Platform,
_contrast: f64,
) -> TonalPalette {
match variant {
Variant::Content | Variant::Fidelity => {
TonalPalette::from_hue_and_chroma(source.hue(), (source.chroma() / 8.0) + 4.0)
}
Variant::FruitSalad => TonalPalette::from_hue_and_chroma(source.hue(), 16.0),
Variant::Monochrome => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::Neutral => TonalPalette::from_hue_and_chroma(source.hue(), 2.0),
Variant::Rainbow => TonalPalette::from_hue_and_chroma(source.hue(), 0.0),
Variant::TonalSpot => TonalPalette::from_hue_and_chroma(source.hue(), 8.0),
Variant::Expressive => TonalPalette::from_hue_and_chroma(
sanitize_degrees_double(source.hue() + 15.0),
12.0,
),
Variant::Vibrant => TonalPalette::from_hue_and_chroma(source.hue(), 12.0),
}
}
fn get_error_palette(
&self,
_variant: Variant,
_source: &Hct,
_is_dark: bool,
_platform: Platform,
_contrast: f64,
) -> Option<TonalPalette> {
None
}
}