est_render/math/
color.rs

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    /// Creates a new color with the given red, green, blue, and alpha values.
19    /// Values should be in the range [0.0, 1.0].
20    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    /// Creates a new color from RGBA values in the range [0, 255].
34    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    /// Converts the color to an array of RGBA values in the range [0, 255].
44    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    /// Converts the color into sRGB color space.
54    pub fn into_srgb(mut self) -> Self {
55        utils::rgb_to_srgb(&mut self);
56        self
57    }
58
59    /// Converts the color from sRGB to linear RGB color space.
60    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}