#[derive(Debug, Clone, Copy, PartialEq)] pub struct Color { pub r: f64, pub g: f64, pub b: f64, } impl Color { pub fn rgb(r: f64, g: f64, b: f64) -> Self { Self { r, g, b } } pub fn parse(c: &str) -> Option { match c { "red" => Some(Color::RED), "green" => Some(Color::GREEN), "blue" => Some(Color::BLUE), "yellow" => Some(Color::YELLOW), "cyan" => Some(Color::CYAN), "magenta" => Some(Color::MAGENTA), "black" => Some(Color::BLACK), "white" => Some(Color::WHITE), _ => { if c.len() == 6 { Some(Self::from_rgb888( u8::from_str_radix(&c[0..2], 16).ok()?, u8::from_str_radix(&c[2..4], 16).ok()?, u8::from_str_radix(&c[4..6], 16).ok()?, )) } else { None } } } } pub fn as_rgb888(&self) -> (u8, u8, u8) { ( (self.r * 255.0) as u8, (self.g * 255.0) as u8, (self.b * 255.0) as u8, ) } pub fn from_rgb888(r: u8, g: u8, b: u8) -> Self { Color { r: r as f64 / 255.0, g: g as f64 / 255.0, b: b as f64 / 255.0, } } pub const RED: Color = Color { r: 1.0, g: 0.0, b: 0.0, }; pub const GREEN: Color = Color { r: 0.0, g: 1.0, b: 0.0, }; pub const BLUE: Color = Color { r: 0.0, g: 0.0, b: 1.0, }; pub const YELLOW: Color = Color { r: 1.0, g: 1.0, b: 0.0, }; pub const CYAN: Color = Color { r: 0.0, g: 1.0, b: 1.0, }; pub const MAGENTA: Color = Color { r: 1.0, g: 0.0, b: 1.0, }; pub const BLACK: Color = Color { r: 0.0, g: 0.0, b: 0.0, }; pub const WHITE: Color = Color { r: 1.0, g: 1.0, b: 1.0, }; pub fn mix(a: Color, b: Color, x: f64) -> Color { let y = 1.0 - x; Color { r: a.r * y + b.r * x, g: a.g * y + b.g * x, b: a.b * y + b.b * x, } } }