use crate::theme::MacTheme;
use egui::Color32;
pub fn srgb_channel_to_linear(c: u8) -> f32 {
let s = c as f32 / 255.0;
if s <= 0.04045 {
s / 12.92
} else {
((s + 0.055) / 1.055).powf(2.4)
}
}
pub fn relative_luminance(color: Color32) -> f32 {
let r = srgb_channel_to_linear(color.r());
let g = srgb_channel_to_linear(color.g());
let b = srgb_channel_to_linear(color.b());
0.2126 * r + 0.7152 * g + 0.0722 * b
}
pub fn contrast_ratio(fg: Color32, bg: Color32) -> f32 {
let alpha = fg.a() as f32 / 255.0;
let blended_r = ((fg.r() as f32 * alpha) + (bg.r() as f32 * (1.0 - alpha))).round() as u8;
let blended_g = ((fg.g() as f32 * alpha) + (bg.g() as f32 * (1.0 - alpha))).round() as u8;
let blended_b = ((fg.b() as f32 * alpha) + (bg.b() as f32 * (1.0 - alpha))).round() as u8;
let effective_fg = Color32::from_rgb(blended_r, blended_g, blended_b);
let l1 = relative_luminance(effective_fg);
let l2 = relative_luminance(bg);
let lighter = l1.max(l2);
let darker = l1.min(l2);
(lighter + 0.05) / (darker + 0.05)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum MacBackgroundStyle {
#[default]
Light,
Dark,
}
impl MacBackgroundStyle {
pub fn from_color(bg: Color32) -> Self {
let lum = relative_luminance(bg);
let max_c = bg.r().max(bg.g()).max(bg.b());
let min_c = bg.r().min(bg.g()).min(bg.b());
let is_chromatic = (max_c - min_c) > 30;
let threshold = if is_chromatic { 0.26 } else { 0.179 };
if lum <= threshold {
Self::Dark
} else {
Self::Light
}
}
pub fn primary_text_color(&self, theme: &MacTheme) -> Color32 {
match self {
Self::Dark => Color32::from_rgb(255, 255, 255),
Self::Light => theme.tokens().colors().aqua.label.to_color32(),
}
}
pub fn secondary_text_color(&self, theme: &MacTheme) -> Color32 {
match self {
Self::Dark => Color32::from_white_alpha(217),
Self::Light => theme.tokens().colors().aqua.secondary_label.to_color32(),
}
}
pub fn tertiary_text_color(&self, theme: &MacTheme) -> Color32 {
match self {
Self::Dark => Color32::from_white_alpha(179),
Self::Light => theme.tokens().colors().aqua.placeholder_text.to_color32(),
}
}
pub fn primary_text(&self) -> Color32 {
match self {
Self::Dark => Color32::from_rgb(255, 255, 255),
Self::Light => Color32::from_rgb(0, 0, 0),
}
}
pub fn secondary_text(&self) -> Color32 {
match self {
Self::Dark => Color32::from_white_alpha(217),
Self::Light => Color32::from_black_alpha(166),
}
}
pub fn tertiary_text(&self) -> Color32 {
match self {
Self::Dark => Color32::from_white_alpha(179),
Self::Light => Color32::from_black_alpha(115),
}
}
}