1use super::{Style, StyleUpdater};
2use palette::{FromColor, IntoColor, Packed, Srgb, Srgba};
3
4pub use palette::{self, named};
5
6pub fn display_rgb(rgb: &Srgb) -> String {
7 let (red, green, blue) = rgb.into_components();
8 format!(
9 "rgb({:.2}%, {:.2}%, {:.2}%)",
10 (red * 100.0),
11 green * 100.0,
12 blue * 100.0
13 )
14}
15
16pub fn display_rgba(rgb: &Srgba) -> String {
17 let (red, green, blue, alpha) = rgb.into_components();
18 format!(
19 "rgba({:.2}%, {:.2}%, {:.2}%, {})",
20 red * 100.0,
21 green * 100.0,
22 blue * 100.0,
23 alpha
24 )
25}
26
27pub fn display_rgb_u8(rgb: &Srgb<u8>) -> String {
28 let (red, green, blue) = rgb.into_components();
29 format!("rgb({}, {}, {})", red, green, blue)
30}
31
32pub fn display_rgba_u8(rgb: &Srgba<u8>) -> String {
33 let (red, green, blue, alpha) = rgb.into_components();
34 format!("rgba({}, {}, {}, {})", red, green, blue, alpha)
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Display, From)]
38pub enum Color {
39 #[from]
40 #[display(fmt = "{}", "display_rgb(_0)")]
41 Rgb(Srgb),
42 #[from]
43 #[display(fmt = "{}", "display_rgba(_0)")]
44 Rgba(Srgba),
45 #[from]
46 #[display(fmt = "{}", "display_rgba_u8(_0)")]
47 RgbaU8(Srgba<u8>),
48 #[from]
49 #[display(fmt = "{}", "display_rgb_u8(_0)")]
50 RgbU8(Srgb<u8>),
51 #[display(fmt = "transparent")]
53 Transparent,
54 #[display(fmt = "currentColor")]
55 CurrentColor,
56}
57
58impl From<Packed> for Color {
59 fn from(source: Packed) -> Self {
60 Color::RgbaU8(source.into())
61 }
62}
63
64impl From<u32> for Color {
65 fn from(source: u32) -> Self {
66 Color::from(Packed::from(source))
67 }
68}
69
70impl From<(u8, u8, u8)> for Color {
71 fn from(source: (u8, u8, u8)) -> Self {
72 Color::RgbU8(source.into())
73 }
74}
75
76impl From<(u8, u8, u8, u8)> for Color {
77 fn from(source: (u8, u8, u8, u8)) -> Self {
78 Color::RgbaU8(source.into())
79 }
80}
81
82impl From<(f32, f32, f32)> for Color {
83 fn from(source: (f32, f32, f32)) -> Self {
84 Color::Rgb(source.into())
85 }
86}
87
88impl From<(f32, f32, f32, f32)> for Color {
89 fn from(source: (f32, f32, f32, f32)) -> Self {
90 Color::Rgba(source.into())
91 }
92}
93
94impl<T> FromColor<T> for Color
95where
96 T: IntoColor<Srgba>,
97{
98 fn from_color(t: T) -> Self {
99 let rgba = t.into_color();
100 Color::Rgba(rgba)
101 }
102}
103
104impl StyleUpdater for Color {
105 fn update_style(self, style: Style) -> Style {
106 style.insert("color", self)
107 }
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, From)]
111pub struct Opacity(f32);
112
113impl StyleUpdater for Opacity {
114 fn update_style(self, style: Style) -> Style {
115 style.insert("opacity", self.0)
116 }
117}
118
119impl TryFrom<Color> for Srgba {
120 type Error = &'static str;
121
122 fn try_from(value: Color) -> Result<Self, Self::Error> {
123 match value {
124 Color::Rgb(rgb) => Ok(rgb.into()),
125 Color::Rgba(rgba) => Ok(rgba),
126 Color::RgbaU8(rgb) => Ok(rgb.into_format()),
127 Color::RgbU8(rgb) => Ok(rgb.into_format().into()),
128 Color::Transparent => Ok(Srgba::new(0.0, 0.0, 0.0, 0.0)),
129 Color::CurrentColor => Err("Cannot convert CurrentColor into a color"),
130 }
131 }
132}
133
134impl TryFrom<Color> for Srgb {
135 type Error = &'static str;
136
137 fn try_from(value: Color) -> Result<Self, Self::Error> {
138 let rgba: Srgba = value.try_into()?;
139 Ok(rgba.color)
140 }
141}