use iced::Font; use image::Rgb; use crate::palette::Palette; use iced::Background; use iced::Color; use iced::widget::container; use iced::widget::text_input; pub const FONT_VG5000: Font = Font::External { name: "VG5000", bytes: include_bytes!("../fonts/vg5000/VG5000.otf"), }; #[derive(Copy, Clone, Debug)] pub struct Theme { pub base_color: Color, pub text_color: Color, subtype: Subtype, } #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Subtype { Base, ActiveLyric, } use Subtype::*; impl Theme { pub fn from_palette(palette: Palette) -> Self { let base_color = img_color_to_iced(palette.dominant_color()); let luma = relative_lum(base_color); let text_color = if luma > 0.2 { Color { a: 0.8, ..Color::BLACK } } else { Color::WHITE }; Theme { subtype: Base, base_color, text_color, } } pub fn reduced_text_color(&self) -> Color { Color { a: 0.5, ..self.text_color } } pub fn active_lyric(&self, active: bool) -> Self { if active { self.set_subtype(ActiveLyric) } else { *self } } fn set_subtype(&self, subtype: Subtype) -> Self { Theme { subtype, ..*self } } } impl Default for Theme { fn default() -> Self { Theme { base_color: Color {r: 236. / 255., g: 63. / 255., b: 53. / 255., a: 1.}, text_color: Color {r: 1., g: 1., b: 1., a: 1.}, subtype: Base, } } } impl container::StyleSheet for Theme { fn style(&self) -> container::Style { container::Style { text_color: Some(self.text_color), background: Some(Background::Color(self.base_color)), ..Default::default() } } } impl text_input::StyleSheet for Theme { fn active(&self) -> text_input::Style { text_input::Style { background: Background::Color(self.base_color), border_radius: 0., border_width: 0., ..Default::default() } } fn focused(&self) -> text_input::Style { self.active() } fn placeholder_color(&self) -> Color { Color { a: 0.3, ..self.text_color } } fn value_color(&self) -> Color { if self.subtype == ActiveLyric { self.text_color } else { self.reduced_text_color() } } fn selection_color(&self) -> Color { self.text_color } } fn img_color_to_iced(color: &Rgb) -> Color { Color { r: color[0] as f32 / 255., g: color[1] as f32 / 255., b: color[2] as f32 / 255., a: 1. } } pub fn relative_lum(color: Color) -> f32 { let mut t = [color.r, color.g, color.b] .into_iter() .map(|val| { if val < 0.03928 { val / 12.92 } else { ((val+0.055)/1.055).powf(2.4) } }); 0.2126 * t.next().unwrap() + 0.7152 * t.next().unwrap() + 0.0722 * t.next().unwrap() }