1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub struct Color {
4 pub r: u8,
5 pub g: u8,
6 pub b: u8,
7 pub a: u8,
8}
9
10impl Color {
11 pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
12 Self { r, g, b, a }
13 }
14
15 pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
16 Self { r, g, b, a: 255 }
17 }
18
19 #[allow(dead_code)]
20 pub(crate) fn to_f32_array(self) -> [f32; 4] {
21 [
22 self.r as f32 / 255.0,
23 self.g as f32 / 255.0,
24 self.b as f32 / 255.0,
25 self.a as f32 / 255.0,
26 ]
27 }
28
29 pub const RED: Self = Self::rgb(255, 0, 0);
30 pub const GREEN: Self = Self::rgb(0, 255, 0);
31 pub const BLUE: Self = Self::rgb(0, 0, 255);
32 pub const WHITE: Self = Self::rgb(255, 255, 255);
33 pub const BLACK: Self = Self::rgb(0, 0, 0);
34 pub const YELLOW: Self = Self::rgb(255, 255, 0);
35 pub const CYAN: Self = Self::rgb(0, 255, 255);
36 pub const MAGENTA: Self = Self::rgb(255, 0, 255);
37 pub const TRANSPARENT: Self = Self::rgba(0, 0, 0, 0);
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn rgb_sets_full_alpha() {
46 let c = Color::rgb(10, 20, 30);
47 assert_eq!(c.a, 255);
48 }
49
50 #[test]
51 fn rgba_preserves_all_channels() {
52 let c = Color::rgba(10, 20, 30, 40);
53 assert_eq!((c.r, c.g, c.b, c.a), (10, 20, 30, 40));
54 }
55
56 #[test]
57 fn to_f32_array_normalizes() {
58 let c = Color::rgba(255, 0, 128, 255);
59 let f = c.to_f32_array();
60 assert!((f[0] - 1.0).abs() < f32::EPSILON);
61 assert!((f[1] - 0.0).abs() < f32::EPSILON);
62 assert!((f[2] - 128.0 / 255.0).abs() < 0.001);
63 assert!((f[3] - 1.0).abs() < f32::EPSILON);
64 }
65
66 #[test]
67 fn constants_are_correct() {
68 assert_eq!(Color::RED, Color::rgb(255, 0, 0));
69 assert_eq!(Color::TRANSPARENT, Color::rgba(0, 0, 0, 0));
70 }
71}