pronto_graphics/
color.rs

1use sfml::graphics::Color as SfmlColor;
2
3/// A object representing a color in RGBA32 format.
4/// Red/Green/Blue/Alpha each range from 0 to 255.
5#[derive(Clone, Copy, PartialEq, Eq)]
6pub struct Color {
7    sfml_color: SfmlColor,
8}
9
10impl Color {
11    /// Create a [`Color`] from `red`, `green` and `blue`.
12    /// # Examples
13    /// ```
14    /// let color = Color::rgb(0x1D, 0x37, 0x85);
15    /// ```
16    pub const fn rgb(red: u8, green: u8, blue: u8) -> Self {
17        Color {
18            sfml_color: SfmlColor::rgb(red, green, blue),
19        }
20    }
21
22    /// Create a [`Color`] from `red`, `green`, `blue` and `alpha`.
23    /// # Examples
24    /// ```
25    /// let color = Color::rgba(0x1D, 0x37, 0x85, 127);
26    /// ```
27    pub const fn rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
28        Color {
29            sfml_color: SfmlColor::rgba(red, green, blue, alpha),
30        }
31    }
32
33    /// Create a [`Color`] from an existing color with alpha set to `alpha`.
34    /// # Examples
35    /// ```
36    /// let color = Color::BLUE.with_alpha(127);
37    /// ```
38    pub fn with_alpha(self, alpha: u8) -> Self {
39        Self::rgba(self.red(), self.green(), self.blue(), alpha)
40    }
41
42    /// Create a [`Color`] from [HSB] values.
43    ///
44    /// - `hue` : Between 0 and 360.
45    /// - `saturation` : Between 0 and 1.
46    /// - `brightness`  : Between 0 and 1.
47    ///
48    /// [HSB]: https://en.wikipedia.org/wiki/HSL_and_HSV
49    pub fn from_hsb(hue: f32, saturation: f32, brightness: f32) -> Self {
50        // Based on https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative
51
52        let f = |n: f32| {
53            let k = (n + hue / 60.) % 6.;
54            brightness
55                - brightness * saturation * (0f32).max(k.min(4. - k).min(1.))
56        };
57
58        Color::rgb(
59            (255. * f(5.)) as u8,
60            (255. * f(3.)) as u8,
61            (255. * f(1.)) as u8,
62        )
63    }
64
65    /// The `red` component of the color.
66    pub fn red(&self) -> u8 {
67        self.sfml_color.red()
68    }
69
70    /// The `green` component of the color.
71    pub fn green(&self) -> u8 {
72        self.sfml_color.green()
73    }
74
75    /// The `blue` component of the color.
76    pub fn blue(&self) -> u8 {
77        self.sfml_color.blue()
78    }
79
80    /// The `alpha` component of the color.
81    pub fn alpha(&self) -> u8 {
82        self.sfml_color.alpha()
83    }
84
85    pub const TRANSPARENT: Color = Color::rgba(0x00, 0x00, 0x00, 0);
86    pub const BLACK: Color = Color::rgb(0x00, 0x00, 0x00);
87    pub const WHITE: Color = Color::rgb(0xFF, 0xFF, 0xFF);
88    pub const GRAY: Color = Color::rgb(0x80, 0x80, 0x80);
89    pub const DARK_GRAY: Color = Color::rgb(0x40, 0x40, 0x40);
90    pub const LIGHT_GRAY: Color = Color::rgb(0xC0, 0xC0, 0xC0);
91    pub const RED: Color = Color::rgb(0xFF, 0x00, 0x00);
92    pub const GREEN: Color = Color::rgb(0x00, 0xFF, 0x00);
93    pub const BLUE: Color = Color::rgb(0x00, 0x00, 0xFF);
94}
95
96impl From<Color> for SfmlColor {
97    fn from(color: Color) -> Self {
98        color.sfml_color
99    }
100}
101
102impl From<(u8, u8, u8)> for Color {
103    fn from(rgb: (u8, u8, u8)) -> Self {
104        Self::rgb(rgb.0, rgb.1, rgb.2)
105    }
106}
107
108impl From<(u8, u8, u8, u8)> for Color {
109    fn from(rgb: (u8, u8, u8, u8)) -> Self {
110        Self::rgba(rgb.0, rgb.1, rgb.2, rgb.3)
111    }
112}