notan_graphics/
color.rs

1/// Represents a visual color
2#[derive(Debug, Clone, Copy, PartialEq)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub struct Color {
5    /// Red value
6    pub r: f32,
7    /// Green value
8    pub g: f32,
9    /// Blue value
10    pub b: f32,
11    /// Alpha value
12    pub a: f32,
13}
14
15impl Color {
16    pub const TRANSPARENT: Color = Color::new(0.0, 0.0, 0.0, 0.0);
17    pub const WHITE: Color = Color::new(1.0, 1.0, 1.0, 1.0);
18    pub const BLACK: Color = Color::new(0.0, 0.0, 0.0, 1.0);
19    pub const RED: Color = Color::new(1.0, 0.0, 0.0, 1.0);
20    pub const GREEN: Color = Color::new(0.0, 1.0, 0.0, 1.0);
21    pub const BLUE: Color = Color::new(0.0, 0.0, 1.0, 1.0);
22    pub const YELLOW: Color = Color::new(1.0, 1.0, 0.0, 1.0);
23    pub const MAGENTA: Color = Color::new(1.0, 0.0, 1.0, 1.0);
24    pub const SILVER: Color = Color::new(0.753, 0.753, 0.753, 1.0);
25    pub const GRAY: Color = Color::new(0.5, 0.5, 0.5, 1.0);
26    pub const OLIVE: Color = Color::new(0.5, 0.5, 0.0, 1.0);
27    pub const PURPLE: Color = Color::new(0.5, 0.0, 0.5, 1.0);
28    pub const MAROON: Color = Color::new(0.5, 0.0, 0.0, 1.0);
29    pub const BROWN: Color = Color::new(0.647, 0.164, 0.164, 1.0);
30    pub const SADDLE_BROWN: Color = Color::new(0.545, 0.27, 0.074, 1.0);
31    pub const AQUA: Color = Color::new(0.0, 1.0, 1.0, 1.0);
32    pub const TEAL: Color = Color::new(0.0, 0.5, 0.5, 1.0);
33    pub const NAVY: Color = Color::new(0.0, 0.0, 0.5, 1.0);
34    pub const ORANGE: Color = Color::new(1.0, 0.647, 0.0, 1.0);
35    pub const PINK: Color = Color::new(1.0, 0.753, 0.796, 1.0);
36
37    #[inline(always)]
38    /// Create a new color from red, green, blue and alpha values
39    pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
40        Self { r, g, b, a }
41    }
42
43    #[inline(always)]
44    /// Create a new color from red, green, blue and alpha values
45    pub const fn from_rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
46        Self::new(r, g, b, a)
47    }
48
49    #[inline(always)]
50    /// Create a new color from red, green and blue values
51    pub const fn from_rgb(r: f32, g: f32, b: f32) -> Self {
52        Self::from_rgba(r, g, b, 1.0)
53    }
54
55    #[inline(always)]
56    /// Create a new color from hexadecimal number like 0x000000ff (0xRRGGBBAA)
57    pub fn from_hex(hex: u32) -> Self {
58        let [r, g, b, a] = hex_to_rgba(hex);
59        Self { r, g, b, a }
60    }
61
62    #[inline(always)]
63    /// Create a new color from rgba bytes
64    pub fn from_bytes(r: u8, g: u8, b: u8, a: u8) -> Self {
65        Self {
66            r: r as f32 / 255.0,
67            g: g as f32 / 255.0,
68            b: b as f32 / 255.0,
69            a: a as f32 / 255.0,
70        }
71    }
72
73    #[inline(always)]
74    /// Returns the same color with the red passed
75    pub const fn with_red(&self, red: f32) -> Color {
76        Self::new(red, self.g, self.b, self.a)
77    }
78
79    #[inline(always)]
80    /// Returns the same color with the green passed
81    pub const fn with_green(&self, green: f32) -> Color {
82        Self::new(self.r, green, self.b, self.a)
83    }
84
85    #[inline(always)]
86    /// Returns the same color with the blue passed
87    pub const fn with_blue(&self, blue: f32) -> Color {
88        Self::new(self.r, self.g, blue, self.a)
89    }
90
91    #[inline(always)]
92    /// Returns the same color with the alpha passed
93    pub const fn with_alpha(&self, alpha: f32) -> Color {
94        Self::new(self.r, self.g, self.b, alpha)
95    }
96
97    #[inline(always)]
98    /// Returns an array with the r, g, b, a values
99    pub const fn rgba(&self) -> [f32; 4] {
100        [self.r, self.g, self.b, self.a]
101    }
102
103    #[inline(always)]
104    /// Returns an array with the r, g, b values
105    pub const fn rgb(&self) -> [f32; 3] {
106        [self.r, self.g, self.b]
107    }
108
109    #[inline(always)]
110    /// Returns the hexadecimal representation of the color like 0xRRGGBBAA
111    pub fn hex(&self) -> u32 {
112        rgba_to_hex(self.r, self.g, self.b, self.a)
113    }
114
115    #[inline(always)]
116    /// Returns the hexadecimal representantion of the colos as string like #RRGGBBAA
117    pub fn hex_string(&self) -> String {
118        hex_to_string(self.hex())
119    }
120
121    #[inline(always)]
122    /// Returns byte representation of the color
123    pub fn rgba_u8(&self) -> [u8; 4] {
124        let r = (self.r * 255.0) as _;
125        let g = (self.g * 255.0) as _;
126        let b = (self.b * 255.0) as _;
127        let a = (self.a * 255.0) as _;
128        [r, g, b, a]
129    }
130
131    #[inline(always)]
132    /// Returns the same color as premultiplied alpha
133    pub fn to_premultiplied_alpha(&self) -> Color {
134        if self.a == 0.0 {
135            Self::TRANSPARENT
136        } else if self.a == 1.0 {
137            *self
138        } else {
139            Self {
140                r: self.r * self.a,
141                g: self.g * self.a,
142                b: self.b * self.a,
143                a: self.a,
144            }
145        }
146    }
147}
148
149impl From<Color> for [u8; 4] {
150    fn from(c: Color) -> Self {
151        c.rgba_u8()
152    }
153}
154
155impl From<Color> for [f32; 4] {
156    fn from(c: Color) -> Self {
157        c.rgba()
158    }
159}
160
161impl From<u32> for Color {
162    fn from(color: u32) -> Self {
163        Color::from_hex(color)
164    }
165}
166
167impl From<[f32; 4]> for Color {
168    fn from(color: [f32; 4]) -> Self {
169        Color::new(color[0], color[1], color[2], color[3])
170    }
171}
172
173impl From<[f32; 3]> for Color {
174    fn from(color: [f32; 3]) -> Self {
175        Color::from_rgb(color[0], color[1], color[2])
176    }
177}
178
179impl From<[u8; 4]> for Color {
180    fn from(color: [u8; 4]) -> Self {
181        Color::from_bytes(color[0], color[1], color[2], color[3])
182    }
183}
184
185impl std::fmt::Display for Color {
186    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187        write!(
188            f,
189            "Color {{ r: {}, g: {}, b: {}, a: {}}}",
190            self.r, self.g, self.b, self.a
191        )
192    }
193}
194
195#[inline(always)]
196/// Converts a rgba color values to a hexadecimal values
197pub fn rgba_to_hex(r: f32, g: f32, b: f32, a: f32) -> u32 {
198    (((r * 255.0) as u32) << 24)
199        + (((g * 255.0) as u32) << 16)
200        + (((b * 255.0) as u32) << 8)
201        + ((a * 255.0) as u32)
202}
203
204#[inline(always)]
205/// Converts an hexadecimal value to a rgba values
206pub fn hex_to_rgba(hex: u32) -> [f32; 4] {
207    [
208        ((hex >> 24) & 0xFF) as f32 / 255.0,
209        ((hex >> 16) & 0xFF) as f32 / 255.0,
210        ((hex >> 8) & 0xFF) as f32 / 255.0,
211        (hex & 0xFF) as f32 / 255.0,
212    ]
213}
214
215#[inline(always)]
216/// Converts a hexadecimal value to string
217pub fn hex_to_string(hex: u32) -> String {
218    format!("{hex:#X}")
219}