1use glam::{Vec3, Vec4};
4use std::ops::{Add, AddAssign, Mul, MulAssign};
5use thiserror::Error;
6use type_ulid::TypeUlid;
7
8#[derive(Clone, Copy, Debug, TypeUlid)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[ulid = "01GW2T0C0Q97B17MFARADVTZG5"]
12#[repr(C)]
13pub enum Color {
14 Rgba {
16 red: f32,
18 green: f32,
20 blue: f32,
22 alpha: f32,
24 },
25}
26
27impl Color {
28 pub const BLACK: Color = Color::rgb(0.0, 0.0, 0.0);
30 pub const BLUE: Color = Color::rgb(0.0, 0.0, 1.0);
32 pub const CYAN: Color = Color::rgb(0.0, 1.0, 1.0);
34 pub const GRAY: Color = Color::rgb(0.5, 0.5, 0.5);
36 pub const GREEN: Color = Color::rgb(0.0, 1.0, 0.0);
38 pub const NONE: Color = Color::rgba(0.0, 0.0, 0.0, 0.0);
40 pub const ORANGE: Color = Color::rgb(1.0, 0.65, 0.0);
42 pub const RED: Color = Color::rgb(1.0, 0.0, 0.0);
44 pub const WHITE: Color = Color::rgb(1.0, 1.0, 1.0);
46 pub const YELLOW: Color = Color::rgb(1.0, 1.0, 0.0);
48
49 pub const fn rgb(r: f32, g: f32, b: f32) -> Color {
60 Color::Rgba {
61 red: r,
62 green: g,
63 blue: b,
64 alpha: 1.0,
65 }
66 }
67
68 pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
80 Color::Rgba {
81 red: r,
82 green: g,
83 blue: b,
84 alpha: a,
85 }
86 }
87
88 pub fn hex<T: AsRef<str>>(hex: T) -> Result<Color, HexColorError> {
99 let hex = hex.as_ref();
100
101 if hex.len() == 3 {
103 let mut data = [0; 6];
104 for (i, ch) in hex.chars().enumerate() {
105 data[i * 2] = ch as u8;
106 data[i * 2 + 1] = ch as u8;
107 }
108 return decode_rgb(&data);
109 }
110
111 if hex.len() == 4 {
113 let mut data = [0; 8];
114 for (i, ch) in hex.chars().enumerate() {
115 data[i * 2] = ch as u8;
116 data[i * 2 + 1] = ch as u8;
117 }
118 return decode_rgba(&data);
119 }
120
121 if hex.len() == 6 {
123 return decode_rgb(hex.as_bytes());
124 }
125
126 if hex.len() == 8 {
128 return decode_rgba(hex.as_bytes());
129 }
130
131 Err(HexColorError::Length)
132 }
133
134 pub fn rgb_u8(r: u8, g: u8, b: u8) -> Color {
145 Color::rgba_u8(r, g, b, u8::MAX)
146 }
147
148 pub fn rgba_u8(r: u8, g: u8, b: u8, a: u8) -> Color {
162 Color::rgba(
163 r as f32 / u8::MAX as f32,
164 g as f32 / u8::MAX as f32,
165 b as f32 / u8::MAX as f32,
166 a as f32 / u8::MAX as f32,
167 )
168 }
169
170 pub fn r(&self) -> f32 {
172 match self.as_rgba() {
173 Color::Rgba { red, .. } => red,
174 }
175 }
176
177 pub fn g(&self) -> f32 {
179 match self.as_rgba() {
180 Color::Rgba { green, .. } => green,
181 }
182 }
183
184 pub fn b(&self) -> f32 {
186 match self.as_rgba() {
187 Color::Rgba { blue, .. } => blue,
188 }
189 }
190
191 pub fn set_r(&mut self, r: f32) -> &mut Self {
193 *self = self.as_rgba();
194 match self {
195 Color::Rgba { red, .. } => *red = r,
196 }
197 self
198 }
199
200 pub fn set_g(&mut self, g: f32) -> &mut Self {
202 *self = self.as_rgba();
203 match self {
204 Color::Rgba { green, .. } => *green = g,
205 }
206 self
207 }
208
209 pub fn set_b(&mut self, b: f32) -> &mut Self {
211 *self = self.as_rgba();
212 match self {
213 Color::Rgba { blue, .. } => *blue = b,
214 }
215 self
216 }
217
218 #[inline(always)]
220 pub fn a(&self) -> f32 {
221 match self {
222 Color::Rgba { alpha, .. } => *alpha,
223 }
224 }
225
226 pub fn set_a(&mut self, a: f32) -> &mut Self {
228 match self {
229 Color::Rgba { alpha, .. } => {
230 *alpha = a;
231 }
232 }
233 self
234 }
235
236 pub fn as_rgba(self: &Color) -> Color {
238 match self {
239 Color::Rgba { .. } => *self,
240 }
241 }
242
243 pub fn as_rgba_f32(self: Color) -> [f32; 4] {
245 match self {
246 Color::Rgba {
247 red,
248 green,
249 blue,
250 alpha,
251 } => [red, green, blue, alpha],
252 }
253 }
254}
255
256impl Default for Color {
257 fn default() -> Self {
258 Color::WHITE
259 }
260}
261
262impl AddAssign<Color> for Color {
263 fn add_assign(&mut self, rhs: Color) {
264 match self {
265 Color::Rgba {
266 red,
267 green,
268 blue,
269 alpha,
270 } => {
271 let rhs = rhs.as_rgba_f32();
272 *red += rhs[0];
273 *green += rhs[1];
274 *blue += rhs[2];
275 *alpha += rhs[3];
276 }
277 }
278 }
279}
280
281impl Add<Color> for Color {
282 type Output = Color;
283
284 fn add(self, rhs: Color) -> Self::Output {
285 match self {
286 Color::Rgba {
287 red,
288 green,
289 blue,
290 alpha,
291 } => {
292 let rhs = rhs.as_rgba_f32();
293 Color::Rgba {
294 red: red + rhs[0],
295 green: green + rhs[1],
296 blue: blue + rhs[2],
297 alpha: alpha + rhs[3],
298 }
299 }
300 }
301 }
302}
303
304impl From<Color> for [f32; 4] {
305 fn from(color: Color) -> Self {
306 color.as_rgba_f32()
307 }
308}
309
310impl From<[f32; 4]> for Color {
311 fn from([r, g, b, a]: [f32; 4]) -> Self {
312 Color::rgba(r, g, b, a)
313 }
314}
315
316impl From<[f32; 3]> for Color {
317 fn from([r, g, b]: [f32; 3]) -> Self {
318 Color::rgb(r, g, b)
319 }
320}
321
322impl From<Color> for Vec4 {
323 fn from(color: Color) -> Self {
324 let color: [f32; 4] = color.into();
325 Vec4::new(color[0], color[1], color[2], color[3])
326 }
327}
328
329impl From<Vec4> for Color {
330 fn from(vec4: Vec4) -> Self {
331 Color::rgba(vec4.x, vec4.y, vec4.z, vec4.w)
332 }
333}
334
335impl Mul<f32> for Color {
336 type Output = Color;
337
338 fn mul(self, rhs: f32) -> Self::Output {
339 match self {
340 Color::Rgba {
341 red,
342 green,
343 blue,
344 alpha,
345 } => Color::Rgba {
346 red: red * rhs,
347 green: green * rhs,
348 blue: blue * rhs,
349 alpha,
350 },
351 }
352 }
353}
354
355impl MulAssign<f32> for Color {
356 fn mul_assign(&mut self, rhs: f32) {
357 match self {
358 Color::Rgba {
359 red, green, blue, ..
360 } => {
361 *red *= rhs;
362 *green *= rhs;
363 *blue *= rhs;
364 }
365 }
366 }
367}
368
369impl Mul<Vec4> for Color {
370 type Output = Color;
371
372 fn mul(self, rhs: Vec4) -> Self::Output {
373 match self {
374 Color::Rgba {
375 red,
376 green,
377 blue,
378 alpha,
379 } => Color::Rgba {
380 red: red * rhs.x,
381 green: green * rhs.y,
382 blue: blue * rhs.z,
383 alpha: alpha * rhs.w,
384 },
385 }
386 }
387}
388
389impl MulAssign<Vec4> for Color {
390 fn mul_assign(&mut self, rhs: Vec4) {
391 match self {
392 Color::Rgba {
393 red,
394 green,
395 blue,
396 alpha,
397 } => {
398 *red *= rhs.x;
399 *green *= rhs.y;
400 *blue *= rhs.z;
401 *alpha *= rhs.w;
402 }
403 }
404 }
405}
406
407impl Mul<Vec3> for Color {
408 type Output = Color;
409
410 fn mul(self, rhs: Vec3) -> Self::Output {
411 match self {
412 Color::Rgba {
413 red,
414 green,
415 blue,
416 alpha,
417 } => Color::Rgba {
418 red: red * rhs.x,
419 green: green * rhs.y,
420 blue: blue * rhs.z,
421 alpha,
422 },
423 }
424 }
425}
426
427impl MulAssign<Vec3> for Color {
428 fn mul_assign(&mut self, rhs: Vec3) {
429 match self {
430 Color::Rgba {
431 red, green, blue, ..
432 } => {
433 *red *= rhs.x;
434 *green *= rhs.y;
435 *blue *= rhs.z;
436 }
437 }
438 }
439}
440
441impl Mul<[f32; 4]> for Color {
442 type Output = Color;
443
444 fn mul(self, rhs: [f32; 4]) -> Self::Output {
445 match self {
446 Color::Rgba {
447 red,
448 green,
449 blue,
450 alpha,
451 } => Color::Rgba {
452 red: red * rhs[0],
453 green: green * rhs[1],
454 blue: blue * rhs[2],
455 alpha: alpha * rhs[3],
456 },
457 }
458 }
459}
460
461impl MulAssign<[f32; 4]> for Color {
462 fn mul_assign(&mut self, rhs: [f32; 4]) {
463 match self {
464 Color::Rgba {
465 red,
466 green,
467 blue,
468 alpha,
469 } => {
470 *red *= rhs[0];
471 *green *= rhs[1];
472 *blue *= rhs[2];
473 *alpha *= rhs[3];
474 }
475 }
476 }
477}
478
479impl Mul<[f32; 3]> for Color {
480 type Output = Color;
481
482 fn mul(self, rhs: [f32; 3]) -> Self::Output {
483 match self {
484 Color::Rgba {
485 red,
486 green,
487 blue,
488 alpha,
489 } => Color::Rgba {
490 red: red * rhs[0],
491 green: green * rhs[1],
492 blue: blue * rhs[2],
493 alpha,
494 },
495 }
496 }
497}
498
499impl MulAssign<[f32; 3]> for Color {
500 fn mul_assign(&mut self, rhs: [f32; 3]) {
501 match self {
502 Color::Rgba {
503 red, green, blue, ..
504 } => {
505 *red *= rhs[0];
506 *green *= rhs[1];
507 *blue *= rhs[2];
508 }
509 }
510 }
511}
512
513#[derive(Debug, Error)]
515pub enum HexColorError {
516 #[error("Unexpected length of hex string")]
518 Length,
519 #[error("Error parsing hex value")]
521 Hex(#[from] hex::FromHexError),
522}
523
524fn decode_rgb(data: &[u8]) -> Result<Color, HexColorError> {
525 let mut buf = [0; 3];
526 match hex::decode_to_slice(data, &mut buf) {
527 Ok(_) => {
528 let r = buf[0] as f32 / 255.0;
529 let g = buf[1] as f32 / 255.0;
530 let b = buf[2] as f32 / 255.0;
531 Ok(Color::rgb(r, g, b))
532 }
533 Err(err) => Err(HexColorError::Hex(err)),
534 }
535}
536
537fn decode_rgba(data: &[u8]) -> Result<Color, HexColorError> {
538 let mut buf = [0; 4];
539 match hex::decode_to_slice(data, &mut buf) {
540 Ok(_) => {
541 let r = buf[0] as f32 / 255.0;
542 let g = buf[1] as f32 / 255.0;
543 let b = buf[2] as f32 / 255.0;
544 let a = buf[3] as f32 / 255.0;
545 Ok(Color::rgba(r, g, b, a))
546 }
547 Err(err) => Err(HexColorError::Hex(err)),
548 }
549}