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 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 BrBG,
109 PiYG,
110 PRGn,
111 PuOr,
112 RdBu,
113 RdGy,
114 RdYlBu,
115 RdYlGn,
116 Spectral,
117
118 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}