wolf_graph_dot/details/
color.rs

1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum Color {
5    Rgb(u8, u8, u8, Option<u8>),
6    Hsv(f64, f64, f64),
7    X11(&'static str),
8    Svg(&'static str),
9    Brewer(BrewerScheme, usize, usize),
10}
11
12impl Color {
13    pub fn rgb(r: u8, g: u8, b: u8, a: Option<u8>) -> Color {
14        Color::Rgb(r, g, b, a)
15    }
16
17    pub fn hsv(h: f64, s: f64, v: f64) -> Color {
18        Color::Hsv(h, s, v)
19    }
20
21    pub fn x11(color_name: &'static str) -> Color {
22        Color::X11(color_name)
23    }
24
25    pub fn svg(color_name: &'static str) -> Color {
26        Color::Svg(color_name)
27    }
28
29    pub fn brewer(scheme: BrewerScheme, index: usize, max_index: usize) -> Color {
30        Color::Brewer(scheme, index, max_index)
31    }
32
33    pub const RED: Color = Color::X11("red");
34    pub const GREEN: Color = Color::X11("green");
35    pub const BLUE: Color = Color::X11("blue");
36    pub const CYAN: Color = Color::X11("cyan");
37    pub const MAGENTA: Color = Color::X11("magenta");
38    pub const YELLOW: Color = Color::X11("yellow");
39    pub const BLACK: Color = Color::X11("black");
40    pub const WHITE: Color = Color::X11("white");
41    pub const GRAY: Color = Color::X11("gray");
42
43    pub fn scheme_name(&self) -> Option<String> {
44        match self {
45            Color::Rgb(_, _, _, _) | Color::Hsv(_, _, _) => None,
46            Color::X11(_)  => Some("x11".to_string()),
47            Color::Svg(_) => Some("svg".to_string()),
48            Color::Brewer(scheme, _, max_index) => Some(format!("{}{}", scheme, max_index)),
49        }
50    }
51
52    pub fn color_name(&self) -> String {
53        match self {
54            Color::Rgb(r, g, b, a) => {
55                let components = vec![Some(r), Some(g), Some(b), a.as_ref()].into_iter().flatten().map(Color::hex_byte).collect::<String>();
56                format!("#{}", components)
57            },
58            Color::Hsv(h, s, v) => format!("{} {} {}", h, s, v),
59            Color::X11(color_name) => color_name.to_string(),
60            Color::Svg(color_name) => color_name.to_string(),
61            Color::Brewer(_, index, _) => index.to_string(),
62        }
63    }
64
65    fn hex_byte(n: &u8) -> String {
66        format!("{:02x}", n)
67    }
68
69    pub fn full_color_name(&self) -> String {
70        let mut components = Vec::new();
71        if let Some(scheme_name) = self.scheme_name() {
72            components.push(scheme_name);
73        }
74        components.push(self.color_name());
75        components.join("/")
76    }
77}
78
79impl fmt::Display for Color {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        write!(f, "{}", self.color_name())
82    }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
86pub enum BrewerScheme {
87    // Sequential
88    Blues,
89    BuGn,
90    BuPu,
91    GnBu,
92    Greens,
93    Greys,
94    Oranges,
95    OrRd,
96    PuBu,
97    PuBuGn,
98    PuRd,
99    Purples,
100    RdPu,
101    Reds,
102    YlGn,
103    YlGnBu,
104    YlOrBr,
105    YlOrRd,
106
107    // Divergent
108    BrBG,
109    PiYG,
110    PRGn,
111    PuOr,
112    RdBu,
113    RdGy,
114    RdYlBu,
115    RdYlGn,
116    Spectral,
117
118    // Qualitative
119    Accent,
120    Dark2,
121    Paired,
122    Pastel1,
123    Pastel2,
124    Set1,
125    Set2,
126    Set3,
127}
128
129impl fmt::Display for BrewerScheme {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        write!(f, "{:?}", self)
132    }
133}