1#[derive(Debug, Clone, Copy, PartialEq)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub struct Color {
5 pub r: f32,
7 pub g: f32,
9 pub b: f32,
11 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 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 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 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 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 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 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 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 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 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 pub const fn rgba(&self) -> [f32; 4] {
100 [self.r, self.g, self.b, self.a]
101 }
102
103 #[inline(always)]
104 pub const fn rgb(&self) -> [f32; 3] {
106 [self.r, self.g, self.b]
107 }
108
109 #[inline(always)]
110 pub fn hex(&self) -> u32 {
112 rgba_to_hex(self.r, self.g, self.b, self.a)
113 }
114
115 #[inline(always)]
116 pub fn hex_string(&self) -> String {
118 hex_to_string(self.hex())
119 }
120
121 #[inline(always)]
122 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 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)]
196pub 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)]
205pub 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)]
216pub fn hex_to_string(hex: u32) -> String {
218 format!("{hex:#X}")
219}