Skip to main content

flatland_client_ui/
color.rs

1//! Shared RGB colors for map presentation (YAML + render backends).
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub struct RgbColor {
5    pub r: u8,
6    pub g: u8,
7    pub b: u8,
8}
9
10impl RgbColor {
11    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
12        Self { r, g, b }
13    }
14
15    pub const BLACK: Self = Self::rgb(0, 0, 0);
16    pub const RED: Self = Self::rgb(128, 0, 0);
17    pub const GREEN: Self = Self::rgb(0, 128, 0);
18    pub const YELLOW: Self = Self::rgb(128, 128, 0);
19    pub const BLUE: Self = Self::rgb(0, 0, 128);
20    pub const MAGENTA: Self = Self::rgb(128, 0, 128);
21    pub const CYAN: Self = Self::rgb(0, 128, 128);
22    pub const DARK_GRAY: Self = Self::rgb(128, 128, 128);
23    pub const LIGHT_RED: Self = Self::rgb(255, 0, 0);
24    pub const LIGHT_GREEN: Self = Self::rgb(0, 255, 0);
25    pub const LIGHT_YELLOW: Self = Self::rgb(255, 255, 0);
26    pub const LIGHT_BLUE: Self = Self::rgb(0, 0, 255);
27    pub const LIGHT_MAGENTA: Self = Self::rgb(255, 0, 255);
28    pub const LIGHT_CYAN: Self = Self::rgb(0, 255, 255);
29    pub const WHITE: Self = Self::rgb(255, 255, 255);
30}
31
32pub fn parse_color(raw: &str) -> Option<RgbColor> {
33    let s = raw.trim();
34    if let Some(hex) = s.strip_prefix('#') {
35        return parse_hex_color(hex);
36    }
37    match s.to_ascii_lowercase().as_str() {
38        "black" => Some(RgbColor::BLACK),
39        "red" => Some(RgbColor::RED),
40        "green" => Some(RgbColor::GREEN),
41        "yellow" => Some(RgbColor::YELLOW),
42        "blue" => Some(RgbColor::BLUE),
43        "magenta" => Some(RgbColor::MAGENTA),
44        "cyan" => Some(RgbColor::CYAN),
45        "gray" | "grey" | "darkgray" | "darkgrey" => Some(RgbColor::DARK_GRAY),
46        "lightred" => Some(RgbColor::LIGHT_RED),
47        "lightgreen" => Some(RgbColor::LIGHT_GREEN),
48        "lightyellow" => Some(RgbColor::LIGHT_YELLOW),
49        "lightblue" => Some(RgbColor::LIGHT_BLUE),
50        "lightmagenta" => Some(RgbColor::LIGHT_MAGENTA),
51        "lightcyan" => Some(RgbColor::LIGHT_CYAN),
52        "white" => Some(RgbColor::WHITE),
53        _ => None,
54    }
55}
56
57fn parse_hex_color(hex: &str) -> Option<RgbColor> {
58    let expand = |c: u8| -> u8 { (c << 4) | c };
59    match hex.len() {
60        3 => {
61            let r = u8::from_str_radix(&hex[0..1], 16).ok()?;
62            let g = u8::from_str_radix(&hex[1..2], 16).ok()?;
63            let b = u8::from_str_radix(&hex[2..3], 16).ok()?;
64            Some(RgbColor::rgb(expand(r), expand(g), expand(b)))
65        }
66        6 => {
67            let r = u8::from_str_radix(&hex[0..2], 16).ok()?;
68            let g = u8::from_str_radix(&hex[2..4], 16).ok()?;
69            let b = u8::from_str_radix(&hex[4..6], 16).ok()?;
70            Some(RgbColor::rgb(r, g, b))
71        }
72        _ => None,
73    }
74}