use std::fmt::Display;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Color {
None,
Red,
Green,
Blue,
Yellow,
Purple,
Rgb {
r: u8,
g: u8,
b: u8,
},
}
impl Color {
#[allow(clippy::many_single_char_names)]
#[must_use]
pub fn hsv_to_rgb(h: f64, s: f64, v: f64) -> Self {
let h_i = (h * 6.0) as i64;
let f = h.mul_add(6.0, -h_i as f64);
let p = v * (1.0 - s);
let q = v * f.mul_add(-s, 1.0);
let t = v * (1.0 - f).mul_add(-s, 1.0);
let (r, g, b) = match h_i {
0 => (v, t, p),
1 => (q, v, p),
2 => (p, v, t),
3 => (p, q, v),
4 => (t, p, v),
5 => (v, p, q),
_ => unreachable!(),
};
let r = (r * 256.0) as u8;
let g = (g * 256.0) as u8;
let b = (b * 256.0) as u8;
Self::Rgb { r, g, b }
}
#[inline]
#[must_use]
pub fn from_random_number(mut random: f64) -> Self {
const GOLDEN_RATIO_CONJUGATE: f64 = 0.618_033_988_749_895;
random += GOLDEN_RATIO_CONJUGATE;
random %= 1.0;
Self::hsv_to_rgb(random, 0.7, 0.95)
}
#[inline]
#[must_use]
pub fn is_none(&self) -> bool {
*self == Self::None
}
}
impl Display for Color {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::None => f.write_str(""),
Self::Red => f.write_str("red"),
Self::Green => f.write_str("green"),
Self::Blue => f.write_str("blue"),
Self::Yellow => f.write_str("yellow"),
Self::Purple => f.write_str("purple"),
Self::Rgb { r, g, b } => write!(f, "#{r:02X}{b:02X}{g:02X}"),
}
}
}