1use std::ops::*;
2
3use bytemuck::{Pod, Zeroable};
4use num_traits::ToPrimitive;
5
6use super::utils;
7
8#[repr(C)]
9#[derive(Debug, Clone, Copy, Default, Pod, Zeroable)]
10pub struct Color {
11 pub r: f32,
12 pub g: f32,
13 pub b: f32,
14 pub a: f32,
15}
16
17impl Color {
18 pub fn new<T: ToPrimitive>(r: T, g: T, b: T, a: T) -> Self {
21 Self {
22 r: r.to_f32().unwrap_or(0.0).clamp(0.0, 1.0),
23 g: g.to_f32().unwrap_or(0.0).clamp(0.0, 1.0),
24 b: b.to_f32().unwrap_or(0.0).clamp(0.0, 1.0),
25 a: a.to_f32().unwrap_or(1.0).clamp(0.0, 1.0),
26 }
27 }
28
29 pub const fn new_const(r: f32, g: f32, b: f32, a: f32) -> Self {
30 Self { r, g, b, a }
31 }
32
33 pub fn from_rgb<T: ToPrimitive>(r: T, g: T, b: T, a: T) -> Self {
35 Self {
36 r: (r.to_f32().unwrap_or(0.0) / 255.0).clamp(0.0, 1.0),
37 g: (g.to_f32().unwrap_or(0.0) / 255.0).clamp(0.0, 1.0),
38 b: (b.to_f32().unwrap_or(0.0) / 255.0).clamp(0.0, 1.0),
39 a: (a.to_f32().unwrap_or(1.0) / 255.0).clamp(0.0, 1.0),
40 }
41 }
42
43 pub fn into_rgb(self) -> [u8; 4] {
45 [
46 (self.r * 255.0) as u8,
47 (self.g * 255.0) as u8,
48 (self.b * 255.0) as u8,
49 (self.a * 255.0) as u8,
50 ]
51 }
52
53 pub fn into_srgb(mut self) -> Self {
55 utils::rgb_to_srgb(&mut self);
56 self
57 }
58
59 pub fn into_linear(mut self) -> Self {
61 utils::srgb_to_rgb(&mut self);
62 self
63 }
64
65 pub const ALICEBLUE: Color = Self::new_const(0.941, 0.973, 1.0, 1.0);
66 pub const ANTIQUEWHITE: Color = Self::new_const(0.98, 0.922, 0.843, 1.0);
67 pub const AQUA: Color = Self::new_const(0.0, 1.0, 1.0, 1.0);
68 pub const AQUAMARINE: Color = Self::new_const(0.498, 1.0, 0.831, 1.0);
69 pub const AZURE: Color = Self::new_const(0.941, 1.0, 1.0, 1.0);
70 pub const BEIGE: Color = Self::new_const(0.961, 0.961, 0.863, 1.0);
71 pub const BISQUE: Color = Self::new_const(1.0, 0.894, 0.769, 1.0);
72 pub const BLACK: Color = Self::new_const(0.0, 0.0, 0.0, 1.0);
73 pub const BLANCHEDALMOND: Color = Self::new_const(1.0, 0.922, 0.804, 1.0);
74 pub const BLUE: Color = Self::new_const(0.0, 0.0, 1.0, 1.0);
75 pub const BLUEVIOLET: Color = Self::new_const(0.541, 0.169, 0.886, 1.0);
76 pub const BROWN: Color = Self::new_const(0.647, 0.165, 0.165, 1.0);
77 pub const BURLYWOOD: Color = Self::new_const(0.871, 0.722, 0.529, 1.0);
78 pub const CADETBLUE: Color = Self::new_const(0.373, 0.62, 0.627, 1.0);
79 pub const CHARTREUSE: Color = Self::new_const(0.498, 1.0, 0.0, 1.0);
80 pub const CHOCOLATE: Color = Self::new_const(0.824, 0.412, 0.118, 1.0);
81 pub const CORAL: Color = Self::new_const(1.0, 0.498, 0.314, 1.0);
82 pub const CORNFLOWERBLUE: Color = Self::new_const(0.392, 0.584, 0.929, 1.0);
83 pub const CORNSILK: Color = Self::new_const(1.0, 0.973, 0.863, 1.0);
84 pub const CRIMSON: Color = Self::new_const(0.863, 0.078, 0.235, 1.0);
85 pub const CYAN: Color = Self::new_const(0.0, 1.0, 1.0, 1.0);
86 pub const DARKBLUE: Color = Self::new_const(0.0, 0.0, 0.545, 1.0);
87 pub const DARKCYAN: Color = Self::new_const(0.0, 0.545, 0.545, 1.0);
88 pub const DARKGOLDENROD: Color = Self::new_const(0.722, 0.525, 0.043, 1.0);
89 pub const DARKGRAY: Color = Self::new_const(0.663, 0.663, 0.663, 1.0);
90 pub const DARKGREEN: Color = Self::new_const(0.0, 0.392, 0.0, 1.0);
91 pub const DARKKHAKI: Color = Self::new_const(0.741, 0.718, 0.42, 1.0);
92 pub const DARKMAGENTA: Color = Self::new_const(0.545, 0.0, 0.545, 1.0);
93 pub const DARKOLIVEGREEN: Color = Self::new_const(0.333, 0.42, 0.184, 1.0);
94 pub const DARKORANGE: Color = Self::new_const(1.0, 0.549, 0.0, 1.0);
95 pub const DARKORCHID: Color = Self::new_const(0.6, 0.196, 0.8, 1.0);
96 pub const DARKRED: Color = Self::new_const(0.545, 0.0, 0.0, 1.0);
97 pub const DARKSALMON: Color = Self::new_const(0.914, 0.588, 0.478, 1.0);
98 pub const DARKSEAGREEN: Color = Self::new_const(0.561, 0.737, 0.561, 1.0);
99 pub const DARKSLATEBLUE: Color = Self::new_const(0.282, 0.239, 0.545, 1.0);
100 pub const DARKSLATEGRAY: Color = Self::new_const(0.184, 0.31, 0.31, 1.0);
101 pub const DARKTURQUOISE: Color = Self::new_const(0.0, 0.808, 0.82, 1.0);
102 pub const DARKVIOLET: Color = Self::new_const(0.58, 0.0, 0.827, 1.0);
103 pub const DEEPPINK: Color = Self::new_const(1.0, 0.078, 0.576, 1.0);
104 pub const DEEPSKYBLUE: Color = Self::new_const(0.0, 0.749, 1.0, 1.0);
105 pub const DIMGRAY: Color = Self::new_const(0.412, 0.412, 0.412, 1.0);
106 pub const DODGERBLUE: Color = Self::new_const(0.118, 0.565, 1.0, 1.0);
107 pub const FIREBRICK: Color = Self::new_const(0.698, 0.133, 0.133, 1.0);
108 pub const FLORALWHITE: Color = Self::new_const(1.0, 0.98, 0.941, 1.0);
109 pub const FORESTGREEN: Color = Self::new_const(0.133, 0.545, 0.133, 1.0);
110 pub const FUCHSIA: Color = Self::new_const(1.0, 0.0, 1.0, 1.0);
111 pub const GAINSBORO: Color = Self::new_const(0.863, 0.863, 0.863, 1.0);
112 pub const GHOSTWHITE: Color = Self::new_const(0.973, 0.973, 1.0, 1.0);
113 pub const GOLD: Color = Self::new_const(1.0, 0.843, 0.0, 1.0);
114 pub const GOLDENROD: Color = Self::new_const(0.855, 0.647, 0.125, 1.0);
115 pub const GRAY: Color = Self::new_const(0.502, 0.502, 0.502, 1.0);
116 pub const GREEN: Color = Self::new_const(0.0, 0.502, 0.0, 1.0);
117 pub const GREENYELLOW: Color = Self::new_const(0.678, 1.0, 0.184, 1.0);
118 pub const HONEYDEW: Color = Self::new_const(0.941, 1.0, 0.941, 1.0);
119 pub const HOTPINK: Color = Self::new_const(1.0, 0.412, 0.706, 1.0);
120 pub const INDIANRED: Color = Self::new_const(0.804, 0.361, 0.361, 1.0);
121 pub const INDIGO: Color = Self::new_const(0.294, 0.0, 0.51, 1.0);
122 pub const IVORY: Color = Self::new_const(1.0, 1.0, 0.941, 1.0);
123 pub const KHAKI: Color = Self::new_const(0.941, 0.902, 0.549, 1.0);
124 pub const LAVENDER: Color = Self::new_const(0.902, 0.902, 0.98, 1.0);
125 pub const LAVENDERBLUSH: Color = Self::new_const(1.0, 0.941, 0.961, 1.0);
126 pub const LAWNGREEN: Color = Self::new_const(0.486, 0.988, 0.0, 1.0);
127 pub const LEMONCHIFFON: Color = Self::new_const(1.0, 0.98, 0.804, 1.0);
128 pub const LIGHTBLUE: Color = Self::new_const(0.678, 0.847, 0.902, 1.0);
129 pub const LIGHTCORAL: Color = Self::new_const(0.941, 0.502, 0.502, 1.0);
130 pub const LIGHTCYAN: Color = Self::new_const(0.878, 1.0, 1.0, 1.0);
131 pub const LIGHTGOLDENRODYELLOW: Color = Self::new_const(0.98, 0.98, 0.824, 1.0);
132 pub const LIGHTGRAY: Color = Self::new_const(0.827, 0.827, 0.827, 1.0);
133 pub const LIGHTGREEN: Color = Self::new_const(0.565, 0.933, 0.565, 1.0);
134 pub const LIGHTPINK: Color = Self::new_const(1.0, 0.714, 0.757, 1.0);
135 pub const LIGHTSALMON: Color = Self::new_const(1.0, 0.627, 0.478, 1.0);
136 pub const LIGHTSEAGREEN: Color = Self::new_const(0.125, 0.698, 0.667, 1.0);
137 pub const LIGHTSKYBLUE: Color = Self::new_const(0.529, 0.808, 0.98, 1.0);
138 pub const LIGHTSLATEGRAY: Color = Self::new_const(0.467, 0.533, 0.6, 1.0);
139 pub const LIGHTSTEELBLUE: Color = Self::new_const(0.69, 0.769, 0.871, 1.0);
140 pub const LIGHTYELLOW: Color = Self::new_const(1.0, 1.0, 0.878, 1.0);
141 pub const LIME: Color = Self::new_const(0.0, 1.0, 0.0, 1.0);
142 pub const LIMEGREEN: Color = Self::new_const(0.196, 0.804, 0.196, 1.0);
143 pub const LINEN: Color = Self::new_const(0.98, 0.941, 0.902, 1.0);
144 pub const MAGENTA: Color = Self::new_const(1.0, 0.0, 1.0, 1.0);
145 pub const MAROON: Color = Self::new_const(0.502, 0.0, 0.0, 1.0);
146 pub const MEDIUMAQUAMARINE: Color = Self::new_const(0.4, 0.804, 0.667, 1.0);
147 pub const MEDIUMBLUE: Color = Self::new_const(0.0, 0.0, 0.804, 1.0);
148 pub const MEDIUMORCHID: Color = Self::new_const(0.729, 0.333, 0.827, 1.0);
149 pub const MEDIUMPURPLE: Color = Self::new_const(0.576, 0.439, 0.859, 1.0);
150 pub const MEDIUMSEAGREEN: Color = Self::new_const(0.235, 0.702, 0.443, 1.0);
151 pub const MEDIUMSLATEBLUE: Color = Self::new_const(0.482, 0.408, 0.933, 1.0);
152 pub const MEDIUMSPRINGGREEN: Color = Self::new_const(0.0, 0.98, 0.604, 1.0);
153 pub const MEDIUMTURQUOISE: Color = Self::new_const(0.282, 0.82, 0.8, 1.0);
154 pub const MEDIUMVIOLETRED: Color = Self::new_const(0.78, 0.082, 0.522, 1.0);
155 pub const MIDNIGHTBLUE: Color = Self::new_const(0.098, 0.098, 0.439, 1.0);
156 pub const MINTCREAM: Color = Self::new_const(0.961, 1.0, 0.98, 1.0);
157 pub const MISTYROSE: Color = Self::new_const(1.0, 0.894, 0.882, 1.0);
158 pub const MOCCASIN: Color = Self::new_const(1.0, 0.894, 0.71, 1.0);
159 pub const NAVAJOWHITE: Color = Self::new_const(1.0, 0.871, 0.678, 1.0);
160 pub const NAVY: Color = Self::new_const(0.0, 0.0, 0.502, 1.0);
161 pub const OLDLACE: Color = Self::new_const(0.992, 0.961, 0.902, 1.0);
162 pub const OLIVE: Color = Self::new_const(0.502, 0.502, 0.0, 1.0);
163 pub const OLIVEDRAB: Color = Self::new_const(0.42, 0.557, 0.137, 1.0);
164 pub const ORANGE: Color = Self::new_const(1.0, 0.647, 0.0, 1.0);
165 pub const ORANGERED: Color = Self::new_const(1.0, 0.271, 0.0, 1.0);
166 pub const ORCHID: Color = Self::new_const(0.855, 0.439, 0.839, 1.0);
167 pub const PALEGOLDENROD: Color = Self::new_const(0.933, 0.91, 0.667, 1.0);
168 pub const PALEGREEN: Color = Self::new_const(0.596, 0.984, 0.596, 1.0);
169 pub const PALETURQUOISE: Color = Self::new_const(0.686, 0.933, 0.933, 1.0);
170 pub const PALEVIOLETRED: Color = Self::new_const(0.859, 0.439, 0.576, 1.0);
171 pub const PAPAYAWHIP: Color = Self::new_const(1.0, 0.937, 0.835, 1.0);
172 pub const PEACHPUFF: Color = Self::new_const(1.0, 0.855, 0.725, 1.0);
173 pub const PERU: Color = Self::new_const(0.804, 0.522, 0.247, 1.0);
174 pub const PINK: Color = Self::new_const(1.0, 0.753, 0.796, 1.0);
175 pub const PLUM: Color = Self::new_const(0.867, 0.627, 0.867, 1.0);
176 pub const POWDERBLUE: Color = Self::new_const(0.69, 0.878, 0.902, 1.0);
177 pub const PURPLE: Color = Self::new_const(0.502, 0.0, 0.502, 1.0);
178 pub const RED: Color = Self::new_const(1.0, 0.0, 0.0, 1.0);
179 pub const ROSYBROWN: Color = Self::new_const(0.737, 0.561, 0.561, 1.0);
180 pub const ROYALBLUE: Color = Self::new_const(0.255, 0.412, 0.882, 1.0);
181 pub const SADDLEBROWN: Color = Self::new_const(0.545, 0.271, 0.075, 1.0);
182 pub const SALMON: Color = Self::new_const(0.98, 0.502, 0.447, 1.0);
183 pub const SANDYBROWN: Color = Self::new_const(0.957, 0.643, 0.376, 1.0);
184 pub const SEAGREEN: Color = Self::new_const(0.18, 0.545, 0.341, 1.0);
185 pub const SEASHELL: Color = Self::new_const(1.0, 0.961, 0.933, 1.0);
186 pub const SIENNA: Color = Self::new_const(0.627, 0.322, 0.176, 1.0);
187 pub const SILVER: Color = Self::new_const(0.753, 0.753, 0.753, 1.0);
188 pub const SKYBLUE: Color = Self::new_const(0.529, 0.808, 0.922, 1.0);
189 pub const SLATEBLUE: Color = Self::new_const(0.416, 0.353, 0.804, 1.0);
190 pub const SLATEGRAY: Color = Self::new_const(0.439, 0.502, 0.565, 1.0);
191 pub const SNOW: Color = Self::new_const(1.0, 0.98, 0.98, 1.0);
192 pub const SPRINGGREEN: Color = Self::new_const(0.0, 1.0, 0.498, 1.0);
193 pub const STEELBLUE: Color = Self::new_const(0.275, 0.51, 0.706, 1.0);
194 pub const TAN: Color = Self::new_const(0.824, 0.706, 0.549, 1.0);
195 pub const TEAL: Color = Self::new_const(0.0, 0.502, 0.502, 1.0);
196 pub const THISTLE: Color = Self::new_const(0.847, 0.749, 0.847, 1.0);
197 pub const TOMATO: Color = Self::new_const(1.0, 0.388, 0.278, 1.0);
198 pub const TURQUOISE: Color = Self::new_const(0.251, 0.878, 0.816, 1.0);
199 pub const VIOLET: Color = Self::new_const(0.933, 0.51, 0.933, 1.0);
200 pub const WHEAT: Color = Self::new_const(0.961, 0.871, 0.702, 1.0);
201 pub const WHITE: Color = Self::new_const(1.0, 1.0, 1.0, 1.0);
202 pub const WHITESMOKE: Color = Self::new_const(0.961, 0.961, 0.961, 1.0);
203 pub const YELLOW: Color = Self::new_const(1.0, 1.0, 0.0, 1.0);
204 pub const YELLOWGREEN: Color = Self::new_const(0.604, 0.804, 0.196, 1.0);
205 pub const TRANSPARENT: Color = Self::new_const(0.0, 0.0, 0.0, 0.0);
206}
207
208impl PartialEq for Color {
209 fn eq(&self, other: &Self) -> bool {
210 self.r == other.r && self.g == other.g && self.b == other.b && self.a == other.a
211 }
212}
213
214impl Eq for Color {}
215
216impl Add for Color {
217 type Output = Self;
218
219 fn add(self, other: Self) -> Self {
220 Self {
221 r: self.r + other.r,
222 g: self.g + other.g,
223 b: self.b + other.b,
224 a: self.a + other.a,
225 }
226 }
227}
228
229impl Add<f32> for Color {
230 type Output = Self;
231
232 fn add(self, other: f32) -> Self {
233 Self {
234 r: self.r + other,
235 g: self.g + other,
236 b: self.b + other,
237 a: self.a + other,
238 }
239 }
240}
241
242impl Add<Color> for f32 {
243 type Output = Color;
244
245 fn add(self, other: Color) -> Color {
246 Color {
247 r: self + other.r,
248 g: self + other.g,
249 b: self + other.b,
250 a: self + other.a,
251 }
252 }
253}
254
255impl AddAssign for Color {
256 fn add_assign(&mut self, other: Self) {
257 self.r += other.r;
258 self.g += other.g;
259 self.b += other.b;
260 self.a += other.a;
261 }
262}
263
264impl AddAssign<f32> for Color {
265 fn add_assign(&mut self, other: f32) {
266 self.r += other;
267 self.g += other;
268 self.b += other;
269 self.a += other;
270 }
271}
272
273impl AddAssign<Color> for f32 {
274 fn add_assign(&mut self, other: Color) {
275 *self += other.r;
276 *self += other.g;
277 *self += other.b;
278 *self += other.a;
279 }
280}
281
282impl Sub for Color {
283 type Output = Self;
284
285 fn sub(self, other: Self) -> Self {
286 Self {
287 r: self.r - other.r,
288 g: self.g - other.g,
289 b: self.b - other.b,
290 a: self.a - other.a,
291 }
292 }
293}
294
295impl Sub<f32> for Color {
296 type Output = Self;
297
298 fn sub(self, other: f32) -> Self {
299 Self {
300 r: self.r - other,
301 g: self.g - other,
302 b: self.b - other,
303 a: self.a - other,
304 }
305 }
306}
307
308impl Sub<Color> for f32 {
309 type Output = Color;
310
311 fn sub(self, other: Color) -> Color {
312 Color {
313 r: self - other.r,
314 g: self - other.g,
315 b: self - other.b,
316 a: self - other.a,
317 }
318 }
319}
320
321impl SubAssign for Color {
322 fn sub_assign(&mut self, other: Self) {
323 self.r -= other.r;
324 self.g -= other.g;
325 self.b -= other.b;
326 self.a -= other.a;
327 }
328}
329
330impl SubAssign<f32> for Color {
331 fn sub_assign(&mut self, other: f32) {
332 self.r -= other;
333 self.g -= other;
334 self.b -= other;
335 self.a -= other;
336 }
337}
338
339impl SubAssign<Color> for f32 {
340 fn sub_assign(&mut self, other: Color) {
341 *self -= other.r;
342 *self -= other.g;
343 *self -= other.b;
344 *self -= other.a;
345 }
346}
347
348impl Mul for Color {
349 type Output = Self;
350
351 fn mul(self, other: Self) -> Self {
352 Self {
353 r: self.r * other.r,
354 g: self.g * other.g,
355 b: self.b * other.b,
356 a: self.a * other.a,
357 }
358 }
359}
360
361impl Mul<f32> for Color {
362 type Output = Self;
363
364 fn mul(self, other: f32) -> Self {
365 Self {
366 r: self.r * other,
367 g: self.g * other,
368 b: self.b * other,
369 a: self.a * other,
370 }
371 }
372}
373
374impl Mul<Color> for f32 {
375 type Output = Color;
376
377 fn mul(self, other: Color) -> Color {
378 Color {
379 r: self * other.r,
380 g: self * other.g,
381 b: self * other.b,
382 a: self * other.a,
383 }
384 }
385}
386
387impl MulAssign for Color {
388 fn mul_assign(&mut self, other: Self) {
389 self.r *= other.r;
390 self.g *= other.g;
391 self.b *= other.b;
392 self.a *= other.a;
393 }
394}
395
396impl MulAssign<f32> for Color {
397 fn mul_assign(&mut self, other: f32) {
398 self.r *= other;
399 self.g *= other;
400 self.b *= other;
401 self.a *= other;
402 }
403}
404
405impl MulAssign<Color> for f32 {
406 fn mul_assign(&mut self, other: Color) {
407 *self *= other.r;
408 *self *= other.g;
409 *self *= other.b;
410 *self *= other.a;
411 }
412}
413
414impl Div for Color {
415 type Output = Self;
416
417 fn div(self, other: Self) -> Self {
418 Self {
419 r: self.r / other.r,
420 g: self.g / other.g,
421 b: self.b / other.b,
422 a: self.a / other.a,
423 }
424 }
425}
426
427impl Div<f32> for Color {
428 type Output = Self;
429
430 fn div(self, other: f32) -> Self {
431 Self {
432 r: self.r / other,
433 g: self.g / other,
434 b: self.b / other,
435 a: self.a / other,
436 }
437 }
438}
439
440impl Div<Color> for f32 {
441 type Output = Color;
442
443 fn div(self, other: Color) -> Color {
444 Color {
445 r: self / other.r,
446 g: self / other.g,
447 b: self / other.b,
448 a: self / other.a,
449 }
450 }
451}
452
453impl DivAssign for Color {
454 fn div_assign(&mut self, other: Self) {
455 self.r /= other.r;
456 self.g /= other.g;
457 self.b /= other.b;
458 self.a /= other.a;
459 }
460}
461
462impl DivAssign<f32> for Color {
463 fn div_assign(&mut self, other: f32) {
464 self.r /= other;
465 self.g /= other;
466 self.b /= other;
467 self.a /= other;
468 }
469}
470
471impl DivAssign<Color> for f32 {
472 fn div_assign(&mut self, other: Color) {
473 *self /= other.r;
474 *self /= other.g;
475 *self /= other.b;
476 *self /= other.a;
477 }
478}
479
480impl From<(f32, f32, f32, f32)> for Color {
481 fn from((r, g, b, a): (f32, f32, f32, f32)) -> Self {
482 Self { r, g, b, a }
483 }
484}
485
486impl From<[f32; 4]> for Color {
487 fn from(data: [f32; 4]) -> Self {
488 Self {
489 r: data[0],
490 g: data[1],
491 b: data[2],
492 a: data[3],
493 }
494 }
495}
496
497impl From<[u8; 4]> for Color {
498 fn from(data: [u8; 4]) -> Self {
499 Self {
500 r: data[0] as f32 / 255.0,
501 g: data[1] as f32 / 255.0,
502 b: data[2] as f32 / 255.0,
503 a: data[3] as f32 / 255.0,
504 }
505 }
506}