1use crate::{
2 color_difference::EuclideanDistance, okhsla::Okhsla, okhsva::Okhsva, okhwba::Okhwba, Alpha,
3 Hsla, Hsva, Hue, Hwba, Laba, Lcha, LinearRgba, Luminance, Mix, Oklaba, Oklcha, Saturation,
4 Srgba, StandardColor, Xyza,
5};
6use bevy_math::{MismatchedUnitsError, TryStableInterpolate};
7#[cfg(feature = "bevy_reflect")]
8use bevy_reflect::prelude::*;
9use derive_more::derive::From;
10
11#[doc = include_str!("../docs/conversion.md")]
16#[doc = include_str!("../docs/diagrams/model_graph.svg")]
18#[derive(Debug, Clone, Copy, PartialEq, From)]
47#[cfg_attr(
48 feature = "bevy_reflect",
49 derive(Reflect),
50 reflect(Clone, PartialEq, Default)
51)]
52#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
53#[cfg_attr(
54 all(feature = "serialize", feature = "bevy_reflect"),
55 reflect(Serialize, Deserialize)
56)]
57pub enum Color {
58 Srgba(Srgba),
60 LinearRgba(LinearRgba),
62 Hsla(Hsla),
64 Hsva(Hsva),
66 Hwba(Hwba),
68 Laba(Laba),
70 Lcha(Lcha),
72 Oklaba(Oklaba),
74 Oklcha(Oklcha),
76 Xyza(Xyza),
78 Okhsla(Okhsla),
80 Okhsva(Okhsva),
82 Okhwba(Okhwba),
84}
85
86impl StandardColor for Color {}
87
88impl Color {
89 pub fn to_linear(&self) -> LinearRgba {
91 (*self).into()
92 }
93
94 pub fn to_srgba(&self) -> Srgba {
96 (*self).into()
97 }
98
99 pub const fn srgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
108 Self::Srgba(Srgba {
109 red,
110 green,
111 blue,
112 alpha,
113 })
114 }
115
116 pub const fn srgb(red: f32, green: f32, blue: f32) -> Self {
124 Self::Srgba(Srgba {
125 red,
126 green,
127 blue,
128 alpha: 1.0,
129 })
130 }
131
132 pub const fn srgb_from_array(array: [f32; 3]) -> Self {
137 Self::Srgba(Srgba {
138 red: array[0],
139 green: array[1],
140 blue: array[2],
141 alpha: 1.0,
142 })
143 }
144
145 pub const fn srgba_u8(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
154 Self::Srgba(Srgba {
155 red: red as f32 / 255.0,
156 green: green as f32 / 255.0,
157 blue: blue as f32 / 255.0,
158 alpha: alpha as f32 / 255.0,
159 })
160 }
161
162 pub const fn srgb_u8(red: u8, green: u8, blue: u8) -> Self {
170 Self::Srgba(Srgba {
171 red: red as f32 / 255.0,
172 green: green as f32 / 255.0,
173 blue: blue as f32 / 255.0,
174 alpha: 1.0,
175 })
176 }
177
178 pub const fn srgb_u32(color: u32) -> Self {
190 Self::Srgba(Srgba::rgb(
191 ((color >> 16) & 0xff) as f32 / 255.,
192 ((color >> 8) & 0xff) as f32 / 255.,
193 (color & 0xff) as f32 / 255.,
194 ))
195 }
196
197 pub const fn srgba_u32(color: u32) -> Self {
209 Self::Srgba(Srgba::new(
210 ((color >> 24) & 0xff) as f32 / 255.,
211 ((color >> 16) & 0xff) as f32 / 255.,
212 ((color >> 8) & 0xff) as f32 / 255.,
213 (color & 0xff) as f32 / 255.,
214 ))
215 }
216
217 pub const fn linear_rgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
226 Self::LinearRgba(LinearRgba {
227 red,
228 green,
229 blue,
230 alpha,
231 })
232 }
233
234 pub const fn linear_rgb(red: f32, green: f32, blue: f32) -> Self {
242 Self::LinearRgba(LinearRgba {
243 red,
244 green,
245 blue,
246 alpha: 1.0,
247 })
248 }
249
250 pub const fn hsla(hue: f32, saturation: f32, lightness: f32, alpha: f32) -> Self {
259 Self::Hsla(Hsla {
260 hue,
261 saturation,
262 lightness,
263 alpha,
264 })
265 }
266
267 pub const fn hsl(hue: f32, saturation: f32, lightness: f32) -> Self {
275 Self::Hsla(Hsla {
276 hue,
277 saturation,
278 lightness,
279 alpha: 1.0,
280 })
281 }
282
283 pub const fn hsva(hue: f32, saturation: f32, value: f32, alpha: f32) -> Self {
292 Self::Hsva(Hsva {
293 hue,
294 saturation,
295 value,
296 alpha,
297 })
298 }
299
300 pub const fn hsv(hue: f32, saturation: f32, value: f32) -> Self {
308 Self::Hsva(Hsva {
309 hue,
310 saturation,
311 value,
312 alpha: 1.0,
313 })
314 }
315
316 pub const fn hwba(hue: f32, whiteness: f32, blackness: f32, alpha: f32) -> Self {
325 Self::Hwba(Hwba {
326 hue,
327 whiteness,
328 blackness,
329 alpha,
330 })
331 }
332
333 pub const fn hwb(hue: f32, whiteness: f32, blackness: f32) -> Self {
341 Self::Hwba(Hwba {
342 hue,
343 whiteness,
344 blackness,
345 alpha: 1.0,
346 })
347 }
348
349 pub const fn laba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
358 Self::Laba(Laba {
359 lightness,
360 a,
361 b,
362 alpha,
363 })
364 }
365
366 pub const fn lab(lightness: f32, a: f32, b: f32) -> Self {
374 Self::Laba(Laba {
375 lightness,
376 a,
377 b,
378 alpha: 1.0,
379 })
380 }
381
382 pub const fn lcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
391 Self::Lcha(Lcha {
392 lightness,
393 chroma,
394 hue,
395 alpha,
396 })
397 }
398
399 pub const fn lch(lightness: f32, chroma: f32, hue: f32) -> Self {
407 Self::Lcha(Lcha {
408 lightness,
409 chroma,
410 hue,
411 alpha: 1.0,
412 })
413 }
414
415 pub const fn oklaba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
424 Self::Oklaba(Oklaba {
425 lightness,
426 a,
427 b,
428 alpha,
429 })
430 }
431
432 pub const fn oklab(lightness: f32, a: f32, b: f32) -> Self {
440 Self::Oklaba(Oklaba {
441 lightness,
442 a,
443 b,
444 alpha: 1.0,
445 })
446 }
447
448 pub const fn oklcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
457 Self::Oklcha(Oklcha {
458 lightness,
459 chroma,
460 hue,
461 alpha,
462 })
463 }
464
465 pub const fn oklch(lightness: f32, chroma: f32, hue: f32) -> Self {
473 Self::Oklcha(Oklcha {
474 lightness,
475 chroma,
476 hue,
477 alpha: 1.0,
478 })
479 }
480
481 pub const fn xyza(x: f32, y: f32, z: f32, alpha: f32) -> Self {
490 Self::Xyza(Xyza { x, y, z, alpha })
491 }
492
493 pub const fn xyz(x: f32, y: f32, z: f32) -> Self {
501 Self::Xyza(Xyza {
502 x,
503 y,
504 z,
505 alpha: 1.0,
506 })
507 }
508
509 pub const fn okhsla(hue: f32, saturation: f32, lightness: f32, alpha: f32) -> Self {
518 Self::Okhsla(Okhsla {
519 hue,
520 saturation,
521 lightness,
522 alpha,
523 })
524 }
525
526 pub const fn okhsl(hue: f32, saturation: f32, lightness: f32) -> Self {
534 Self::Okhsla(Okhsla {
535 hue,
536 saturation,
537 lightness,
538 alpha: 1.0,
539 })
540 }
541
542 pub const fn okhsva(hue: f32, saturation: f32, value: f32, alpha: f32) -> Self {
551 Self::Okhsva(Okhsva {
552 hue,
553 saturation,
554 value,
555 alpha,
556 })
557 }
558
559 pub const fn okhsv(hue: f32, saturation: f32, value: f32) -> Self {
567 Self::Okhsva(Okhsva {
568 hue,
569 saturation,
570 value,
571 alpha: 1.0,
572 })
573 }
574
575 pub const fn okhwba(hue: f32, whiteness: f32, blackness: f32, alpha: f32) -> Self {
584 Self::Okhwba(Okhwba {
585 hue,
586 whiteness,
587 blackness,
588 alpha,
589 })
590 }
591
592 pub const fn okhwb(hue: f32, whiteness: f32, blackness: f32) -> Self {
600 Self::Okhwba(Okhwba {
601 hue,
602 whiteness,
603 blackness,
604 alpha: 1.0,
605 })
606 }
607
608 pub const WHITE: Self = Self::linear_rgb(1.0, 1.0, 1.0);
610
611 pub const BLACK: Self = Self::linear_rgb(0., 0., 0.);
613
614 pub const NONE: Self = Self::linear_rgba(0., 0., 0., 0.);
616}
617
618impl Default for Color {
619 fn default() -> Self {
621 Color::WHITE
622 }
623}
624
625impl Alpha for Color {
626 fn with_alpha(&self, alpha: f32) -> Self {
627 let mut new = *self;
628
629 match &mut new {
630 Color::Srgba(x) => *x = x.with_alpha(alpha),
631 Color::LinearRgba(x) => *x = x.with_alpha(alpha),
632 Color::Hsla(x) => *x = x.with_alpha(alpha),
633 Color::Hsva(x) => *x = x.with_alpha(alpha),
634 Color::Hwba(x) => *x = x.with_alpha(alpha),
635 Color::Laba(x) => *x = x.with_alpha(alpha),
636 Color::Lcha(x) => *x = x.with_alpha(alpha),
637 Color::Oklaba(x) => *x = x.with_alpha(alpha),
638 Color::Oklcha(x) => *x = x.with_alpha(alpha),
639 Color::Xyza(x) => *x = x.with_alpha(alpha),
640 Color::Okhsla(x) => *x = x.with_alpha(alpha),
641 Color::Okhsva(x) => *x = x.with_alpha(alpha),
642 Color::Okhwba(x) => *x = x.with_alpha(alpha),
643 }
644
645 new
646 }
647
648 fn alpha(&self) -> f32 {
649 match self {
650 Color::Srgba(x) => x.alpha(),
651 Color::LinearRgba(x) => x.alpha(),
652 Color::Hsla(x) => x.alpha(),
653 Color::Hsva(x) => x.alpha(),
654 Color::Hwba(x) => x.alpha(),
655 Color::Laba(x) => x.alpha(),
656 Color::Lcha(x) => x.alpha(),
657 Color::Oklaba(x) => x.alpha(),
658 Color::Oklcha(x) => x.alpha(),
659 Color::Xyza(x) => x.alpha(),
660 Color::Okhsla(x) => x.alpha(),
661 Color::Okhsva(x) => x.alpha(),
662 Color::Okhwba(x) => x.alpha(),
663 }
664 }
665
666 fn set_alpha(&mut self, alpha: f32) {
667 match self {
668 Color::Srgba(x) => x.set_alpha(alpha),
669 Color::LinearRgba(x) => x.set_alpha(alpha),
670 Color::Hsla(x) => x.set_alpha(alpha),
671 Color::Hsva(x) => x.set_alpha(alpha),
672 Color::Hwba(x) => x.set_alpha(alpha),
673 Color::Laba(x) => x.set_alpha(alpha),
674 Color::Lcha(x) => x.set_alpha(alpha),
675 Color::Oklaba(x) => x.set_alpha(alpha),
676 Color::Oklcha(x) => x.set_alpha(alpha),
677 Color::Xyza(x) => x.set_alpha(alpha),
678 Color::Okhsla(x) => x.set_alpha(alpha),
679 Color::Okhsva(x) => x.set_alpha(alpha),
680 Color::Okhwba(x) => x.set_alpha(alpha),
681 }
682 }
683}
684
685impl From<Color> for Srgba {
686 fn from(value: Color) -> Self {
687 match value {
688 Color::Srgba(srgba) => srgba,
689 Color::LinearRgba(linear) => linear.into(),
690 Color::Hsla(hsla) => hsla.into(),
691 Color::Hsva(hsva) => hsva.into(),
692 Color::Hwba(hwba) => hwba.into(),
693 Color::Laba(laba) => laba.into(),
694 Color::Lcha(lcha) => lcha.into(),
695 Color::Oklaba(oklab) => oklab.into(),
696 Color::Oklcha(oklch) => oklch.into(),
697 Color::Xyza(xyza) => xyza.into(),
698 Color::Okhsla(okhsl) => okhsl.into(),
699 Color::Okhsva(okhsv) => okhsv.into(),
700 Color::Okhwba(okhwb) => okhwb.into(),
701 }
702 }
703}
704
705impl From<Color> for LinearRgba {
706 fn from(value: Color) -> Self {
707 match value {
708 Color::Srgba(srgba) => srgba.into(),
709 Color::LinearRgba(linear) => linear,
710 Color::Hsla(hsla) => hsla.into(),
711 Color::Hsva(hsva) => hsva.into(),
712 Color::Hwba(hwba) => hwba.into(),
713 Color::Laba(laba) => laba.into(),
714 Color::Lcha(lcha) => lcha.into(),
715 Color::Oklaba(oklab) => oklab.into(),
716 Color::Oklcha(oklch) => oklch.into(),
717 Color::Xyza(xyza) => xyza.into(),
718 Color::Okhsla(okhsl) => okhsl.into(),
719 Color::Okhsva(okhsv) => okhsv.into(),
720 Color::Okhwba(okhwb) => okhwb.into(),
721 }
722 }
723}
724
725impl From<Color> for Hsla {
726 fn from(value: Color) -> Self {
727 match value {
728 Color::Srgba(srgba) => srgba.into(),
729 Color::LinearRgba(linear) => linear.into(),
730 Color::Hsla(hsla) => hsla,
731 Color::Hsva(hsva) => hsva.into(),
732 Color::Hwba(hwba) => hwba.into(),
733 Color::Laba(laba) => laba.into(),
734 Color::Lcha(lcha) => lcha.into(),
735 Color::Oklaba(oklab) => oklab.into(),
736 Color::Oklcha(oklch) => oklch.into(),
737 Color::Xyza(xyza) => xyza.into(),
738 Color::Okhsla(okhsl) => okhsl.into(),
739 Color::Okhsva(okhsv) => okhsv.into(),
740 Color::Okhwba(okhwb) => okhwb.into(),
741 }
742 }
743}
744
745impl From<Color> for Hsva {
746 fn from(value: Color) -> Self {
747 match value {
748 Color::Srgba(srgba) => srgba.into(),
749 Color::LinearRgba(linear) => linear.into(),
750 Color::Hsla(hsla) => hsla.into(),
751 Color::Hsva(hsva) => hsva,
752 Color::Hwba(hwba) => hwba.into(),
753 Color::Laba(laba) => laba.into(),
754 Color::Lcha(lcha) => lcha.into(),
755 Color::Oklaba(oklab) => oklab.into(),
756 Color::Oklcha(oklch) => oklch.into(),
757 Color::Xyza(xyza) => xyza.into(),
758 Color::Okhsla(okhsl) => okhsl.into(),
759 Color::Okhsva(okhsv) => okhsv.into(),
760 Color::Okhwba(okhwb) => okhwb.into(),
761 }
762 }
763}
764
765impl From<Color> for Hwba {
766 fn from(value: Color) -> Self {
767 match value {
768 Color::Srgba(srgba) => srgba.into(),
769 Color::LinearRgba(linear) => linear.into(),
770 Color::Hsla(hsla) => hsla.into(),
771 Color::Hsva(hsva) => hsva.into(),
772 Color::Hwba(hwba) => hwba,
773 Color::Laba(laba) => laba.into(),
774 Color::Lcha(lcha) => lcha.into(),
775 Color::Oklaba(oklab) => oklab.into(),
776 Color::Oklcha(oklch) => oklch.into(),
777 Color::Xyza(xyza) => xyza.into(),
778 Color::Okhsla(okhsl) => okhsl.into(),
779 Color::Okhsva(okhsv) => okhsv.into(),
780 Color::Okhwba(okhwb) => okhwb.into(),
781 }
782 }
783}
784
785impl From<Color> for Laba {
786 fn from(value: Color) -> Self {
787 match value {
788 Color::Srgba(srgba) => srgba.into(),
789 Color::LinearRgba(linear) => linear.into(),
790 Color::Hsla(hsla) => hsla.into(),
791 Color::Hsva(hsva) => hsva.into(),
792 Color::Hwba(hwba) => hwba.into(),
793 Color::Laba(laba) => laba,
794 Color::Lcha(lcha) => lcha.into(),
795 Color::Oklaba(oklab) => oklab.into(),
796 Color::Oklcha(oklch) => oklch.into(),
797 Color::Xyza(xyza) => xyza.into(),
798 Color::Okhsla(okhsl) => okhsl.into(),
799 Color::Okhsva(okhsv) => okhsv.into(),
800 Color::Okhwba(okhwb) => okhwb.into(),
801 }
802 }
803}
804
805impl From<Color> for Lcha {
806 fn from(value: Color) -> Self {
807 match value {
808 Color::Srgba(srgba) => srgba.into(),
809 Color::LinearRgba(linear) => linear.into(),
810 Color::Hsla(hsla) => hsla.into(),
811 Color::Hsva(hsva) => hsva.into(),
812 Color::Hwba(hwba) => hwba.into(),
813 Color::Laba(laba) => laba.into(),
814 Color::Lcha(lcha) => lcha,
815 Color::Oklaba(oklab) => oklab.into(),
816 Color::Oklcha(oklch) => oklch.into(),
817 Color::Xyza(xyza) => xyza.into(),
818 Color::Okhsla(okhsl) => okhsl.into(),
819 Color::Okhsva(okhsv) => okhsv.into(),
820 Color::Okhwba(okhwb) => okhwb.into(),
821 }
822 }
823}
824
825impl From<Color> for Oklaba {
826 fn from(value: Color) -> Self {
827 match value {
828 Color::Srgba(srgba) => srgba.into(),
829 Color::LinearRgba(linear) => linear.into(),
830 Color::Hsla(hsla) => hsla.into(),
831 Color::Hsva(hsva) => hsva.into(),
832 Color::Hwba(hwba) => hwba.into(),
833 Color::Laba(laba) => laba.into(),
834 Color::Lcha(lcha) => lcha.into(),
835 Color::Oklaba(oklab) => oklab,
836 Color::Oklcha(oklch) => oklch.into(),
837 Color::Xyza(xyza) => xyza.into(),
838 Color::Okhsla(okhsl) => okhsl.into(),
839 Color::Okhsva(okhsv) => okhsv.into(),
840 Color::Okhwba(okhwb) => okhwb.into(),
841 }
842 }
843}
844
845impl From<Color> for Oklcha {
846 fn from(value: Color) -> Self {
847 match value {
848 Color::Srgba(srgba) => srgba.into(),
849 Color::LinearRgba(linear) => linear.into(),
850 Color::Hsla(hsla) => hsla.into(),
851 Color::Hsva(hsva) => hsva.into(),
852 Color::Hwba(hwba) => hwba.into(),
853 Color::Laba(laba) => laba.into(),
854 Color::Lcha(lcha) => lcha.into(),
855 Color::Oklaba(oklab) => oklab.into(),
856 Color::Oklcha(oklch) => oklch,
857 Color::Xyza(xyza) => xyza.into(),
858 Color::Okhsla(okhsl) => okhsl.into(),
859 Color::Okhsva(okhsv) => okhsv.into(),
860 Color::Okhwba(okhwb) => okhwb.into(),
861 }
862 }
863}
864
865impl From<Color> for Xyza {
866 fn from(value: Color) -> Self {
867 match value {
868 Color::Srgba(x) => x.into(),
869 Color::LinearRgba(x) => x.into(),
870 Color::Hsla(x) => x.into(),
871 Color::Hsva(hsva) => hsva.into(),
872 Color::Hwba(hwba) => hwba.into(),
873 Color::Laba(laba) => laba.into(),
874 Color::Lcha(x) => x.into(),
875 Color::Oklaba(x) => x.into(),
876 Color::Oklcha(oklch) => oklch.into(),
877 Color::Xyza(xyza) => xyza,
878 Color::Okhsla(okhsl) => okhsl.into(),
879 Color::Okhsva(okhsv) => okhsv.into(),
880 Color::Okhwba(okhwb) => okhwb.into(),
881 }
882 }
883}
884
885impl From<Color> for Okhsla {
886 fn from(value: Color) -> Self {
887 match value {
888 Color::Srgba(x) => x.into(),
889 Color::LinearRgba(x) => x.into(),
890 Color::Hsla(x) => x.into(),
891 Color::Hsva(hsva) => hsva.into(),
892 Color::Hwba(hwba) => hwba.into(),
893 Color::Laba(laba) => laba.into(),
894 Color::Lcha(x) => x.into(),
895 Color::Oklaba(x) => x.into(),
896 Color::Oklcha(oklch) => oklch.into(),
897 Color::Xyza(xyza) => xyza.into(),
898 Color::Okhsla(okhsl) => okhsl,
899 Color::Okhsva(okhsv) => okhsv.into(),
900 Color::Okhwba(okhwb) => okhwb.into(),
901 }
902 }
903}
904
905impl From<Color> for Okhsva {
906 fn from(value: Color) -> Self {
907 match value {
908 Color::Srgba(x) => x.into(),
909 Color::LinearRgba(x) => x.into(),
910 Color::Hsla(x) => x.into(),
911 Color::Hsva(hsva) => hsva.into(),
912 Color::Hwba(hwba) => hwba.into(),
913 Color::Laba(laba) => laba.into(),
914 Color::Lcha(x) => x.into(),
915 Color::Oklaba(x) => x.into(),
916 Color::Oklcha(oklch) => oklch.into(),
917 Color::Xyza(xyza) => xyza.into(),
918 Color::Okhsla(okhsl) => okhsl.into(),
919 Color::Okhsva(okhsv) => okhsv,
920 Color::Okhwba(okhwb) => okhwb.into(),
921 }
922 }
923}
924
925impl From<Color> for Okhwba {
926 fn from(value: Color) -> Self {
927 match value {
928 Color::Srgba(x) => x.into(),
929 Color::LinearRgba(x) => x.into(),
930 Color::Hsla(x) => x.into(),
931 Color::Hsva(hsva) => hsva.into(),
932 Color::Hwba(hwba) => hwba.into(),
933 Color::Laba(laba) => laba.into(),
934 Color::Lcha(x) => x.into(),
935 Color::Oklaba(x) => x.into(),
936 Color::Oklcha(oklch) => oklch.into(),
937 Color::Xyza(xyza) => xyza.into(),
938 Color::Okhsla(okhsl) => okhsl.into(),
939 Color::Okhsva(okhsv) => okhsv.into(),
940 Color::Okhwba(okhwb) => okhwb,
941 }
942 }
943}
944
945type ChosenColorSpace = Oklcha;
947
948impl Luminance for Color {
949 fn luminance(&self) -> f32 {
950 match self {
951 Color::Srgba(x) => x.luminance(),
952 Color::LinearRgba(x) => x.luminance(),
953 Color::Hsla(x) => x.luminance(),
954 Color::Hsva(x) => ChosenColorSpace::from(*x).luminance(),
955 Color::Hwba(x) => ChosenColorSpace::from(*x).luminance(),
956 Color::Laba(x) => x.luminance(),
957 Color::Lcha(x) => x.luminance(),
958 Color::Oklaba(x) => x.luminance(),
959 Color::Oklcha(x) => x.luminance(),
960 Color::Xyza(x) => x.luminance(),
961 Color::Okhsla(x) => x.luminance(),
962 Color::Okhsva(x) => ChosenColorSpace::from(*x).luminance(),
963 Color::Okhwba(x) => ChosenColorSpace::from(*x).luminance(),
964 }
965 }
966
967 fn with_luminance(&self, value: f32) -> Self {
968 let mut new = *self;
969
970 match &mut new {
971 Color::Srgba(x) => *x = x.with_luminance(value),
972 Color::LinearRgba(x) => *x = x.with_luminance(value),
973 Color::Hsla(x) => *x = x.with_luminance(value),
974 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
975 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
976 Color::Laba(x) => *x = x.with_luminance(value),
977 Color::Lcha(x) => *x = x.with_luminance(value),
978 Color::Oklaba(x) => *x = x.with_luminance(value),
979 Color::Oklcha(x) => *x = x.with_luminance(value),
980 Color::Xyza(x) => *x = x.with_luminance(value),
981 Color::Okhsla(x) => *x = x.with_luminance(value),
982 Color::Okhsva(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
983 Color::Okhwba(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
984 }
985
986 new
987 }
988
989 fn darker(&self, amount: f32) -> Self {
990 let mut new = *self;
991
992 match &mut new {
993 Color::Srgba(x) => *x = x.darker(amount),
994 Color::LinearRgba(x) => *x = x.darker(amount),
995 Color::Hsla(x) => *x = x.darker(amount),
996 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
997 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
998 Color::Laba(x) => *x = x.darker(amount),
999 Color::Lcha(x) => *x = x.darker(amount),
1000 Color::Oklaba(x) => *x = x.darker(amount),
1001 Color::Oklcha(x) => *x = x.darker(amount),
1002 Color::Xyza(x) => *x = x.darker(amount),
1003 Color::Okhsla(x) => *x = x.darker(amount),
1004 Color::Okhsva(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
1005 Color::Okhwba(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
1006 }
1007
1008 new
1009 }
1010
1011 fn lighter(&self, amount: f32) -> Self {
1012 let mut new = *self;
1013
1014 match &mut new {
1015 Color::Srgba(x) => *x = x.lighter(amount),
1016 Color::LinearRgba(x) => *x = x.lighter(amount),
1017 Color::Hsla(x) => *x = x.lighter(amount),
1018 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
1019 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
1020 Color::Laba(x) => *x = x.lighter(amount),
1021 Color::Lcha(x) => *x = x.lighter(amount),
1022 Color::Oklaba(x) => *x = x.lighter(amount),
1023 Color::Oklcha(x) => *x = x.lighter(amount),
1024 Color::Xyza(x) => *x = x.lighter(amount),
1025 Color::Okhsla(x) => *x = x.lighter(amount),
1026 Color::Okhsva(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
1027 Color::Okhwba(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
1028 }
1029
1030 new
1031 }
1032}
1033
1034impl Hue for Color {
1035 fn with_hue(&self, hue: f32) -> Self {
1036 let mut new = *self;
1037
1038 match &mut new {
1039 Color::Srgba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
1040 Color::LinearRgba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
1041 Color::Hsla(x) => *x = x.with_hue(hue),
1042 Color::Hsva(x) => *x = x.with_hue(hue),
1043 Color::Hwba(x) => *x = x.with_hue(hue),
1044 Color::Laba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
1045 Color::Lcha(x) => *x = x.with_hue(hue),
1046 Color::Oklaba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
1047 Color::Oklcha(x) => *x = x.with_hue(hue),
1048 Color::Xyza(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
1049 Color::Okhsla(x) => *x = x.with_hue(hue),
1050 Color::Okhsva(x) => *x = x.with_hue(hue),
1051 Color::Okhwba(x) => *x = x.with_hue(hue),
1052 }
1053
1054 new
1055 }
1056
1057 fn hue(&self) -> f32 {
1058 match self {
1059 Color::Srgba(x) => ChosenColorSpace::from(*x).hue(),
1060 Color::LinearRgba(x) => ChosenColorSpace::from(*x).hue(),
1061 Color::Hsla(x) => x.hue(),
1062 Color::Hsva(x) => x.hue(),
1063 Color::Hwba(x) => x.hue(),
1064 Color::Laba(x) => ChosenColorSpace::from(*x).hue(),
1065 Color::Lcha(x) => x.hue(),
1066 Color::Oklaba(x) => ChosenColorSpace::from(*x).hue(),
1067 Color::Oklcha(x) => x.hue(),
1068 Color::Xyza(x) => ChosenColorSpace::from(*x).hue(),
1069 Color::Okhsla(x) => x.hue(),
1070 Color::Okhsva(x) => x.hue(),
1071 Color::Okhwba(x) => x.hue(),
1072 }
1073 }
1074
1075 fn set_hue(&mut self, hue: f32) {
1076 *self = self.with_hue(hue);
1077 }
1078}
1079
1080impl Saturation for Color {
1081 fn with_saturation(&self, saturation: f32) -> Self {
1082 let mut new = *self;
1083
1084 match &mut new {
1085 Color::Srgba(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1086 Color::LinearRgba(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1087 Color::Hsla(x) => *x = x.with_saturation(saturation),
1088 Color::Hsva(x) => *x = x.with_saturation(saturation),
1089 Color::Hwba(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1090 Color::Laba(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1091 Color::Lcha(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1092 Color::Oklaba(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1093 Color::Oklcha(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1094 Color::Xyza(x) => *x = Hsla::from(*x).with_saturation(saturation).into(),
1095 Color::Okhsla(x) => *x = x.with_saturation(saturation),
1096 Color::Okhsva(x) => *x = x.with_saturation(saturation),
1097 Color::Okhwba(x) => *x = Okhsva::from(*x).with_saturation(saturation).into(),
1098 }
1099
1100 new
1101 }
1102
1103 fn saturation(&self) -> f32 {
1104 match self {
1105 Color::Srgba(x) => Hsla::from(*x).saturation(),
1106 Color::LinearRgba(x) => Hsla::from(*x).saturation(),
1107 Color::Hsla(x) => x.saturation(),
1108 Color::Hsva(x) => x.saturation(),
1109 Color::Hwba(x) => Hsla::from(*x).saturation(),
1110 Color::Laba(x) => Hsla::from(*x).saturation(),
1111 Color::Lcha(x) => Hsla::from(*x).saturation(),
1112 Color::Oklaba(x) => Hsla::from(*x).saturation(),
1113 Color::Oklcha(x) => Hsla::from(*x).saturation(),
1114 Color::Xyza(x) => Hsla::from(*x).saturation(),
1115 Color::Okhsla(x) => x.saturation(),
1116 Color::Okhsva(x) => x.saturation(),
1117 Color::Okhwba(x) => Okhsva::from(*x).saturation(),
1118 }
1119 }
1120
1121 fn set_saturation(&mut self, saturation: f32) {
1122 *self = self.with_saturation(saturation);
1123 }
1124}
1125
1126impl Mix for Color {
1127 fn mix(&self, other: &Self, factor: f32) -> Self {
1128 let mut new = *self;
1129
1130 match &mut new {
1131 Color::Srgba(x) => *x = x.mix(&(*other).into(), factor),
1132 Color::LinearRgba(x) => *x = x.mix(&(*other).into(), factor),
1133 Color::Hsla(x) => *x = x.mix(&(*other).into(), factor),
1134 Color::Hsva(x) => *x = x.mix(&(*other).into(), factor),
1135 Color::Hwba(x) => *x = x.mix(&(*other).into(), factor),
1136 Color::Laba(x) => *x = x.mix(&(*other).into(), factor),
1137 Color::Lcha(x) => *x = x.mix(&(*other).into(), factor),
1138 Color::Oklaba(x) => *x = x.mix(&(*other).into(), factor),
1139 Color::Oklcha(x) => *x = x.mix(&(*other).into(), factor),
1140 Color::Xyza(x) => *x = x.mix(&(*other).into(), factor),
1141 Color::Okhsla(x) => *x = x.mix(&(*other).into(), factor),
1142 Color::Okhsva(x) => *x = x.mix(&(*other).into(), factor),
1143 Color::Okhwba(x) => *x = x.mix(&(*other).into(), factor),
1144 }
1145
1146 new
1147 }
1148}
1149
1150impl EuclideanDistance for Color {
1151 fn distance_squared(&self, other: &Self) -> f32 {
1152 match self {
1153 Color::Srgba(x) => x.distance_squared(&(*other).into()),
1154 Color::LinearRgba(x) => x.distance_squared(&(*other).into()),
1155 Color::Hsla(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1156 Color::Hsva(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1157 Color::Hwba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1158 Color::Laba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1159 Color::Lcha(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1160 Color::Oklaba(x) => x.distance_squared(&(*other).into()),
1161 Color::Oklcha(x) => x.distance_squared(&(*other).into()),
1162 Color::Xyza(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1163 Color::Okhsla(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1164 Color::Okhsva(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1165 Color::Okhwba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
1166 }
1167 }
1168}
1169
1170impl TryStableInterpolate for Color {
1171 type Error = MismatchedUnitsError;
1172
1173 fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
1174 match (self, other) {
1175 (Color::Srgba(a), Color::Srgba(b)) => Ok(Color::Srgba(a.mix(b, t))),
1176 (Color::LinearRgba(a), Color::LinearRgba(b)) => Ok(Color::LinearRgba(a.mix(b, t))),
1177 (Color::Hsla(a), Color::Hsla(b)) => Ok(Color::Hsla(a.mix(b, t))),
1178 (Color::Hsva(a), Color::Hsva(b)) => Ok(Color::Hsva(a.mix(b, t))),
1179 (Color::Hwba(a), Color::Hwba(b)) => Ok(Color::Hwba(a.mix(b, t))),
1180 (Color::Laba(a), Color::Laba(b)) => Ok(Color::Laba(a.mix(b, t))),
1181 (Color::Lcha(a), Color::Lcha(b)) => Ok(Color::Lcha(a.mix(b, t))),
1182 (Color::Oklaba(a), Color::Oklaba(b)) => Ok(Color::Oklaba(a.mix(b, t))),
1183 (Color::Oklcha(a), Color::Oklcha(b)) => Ok(Color::Oklcha(a.mix(b, t))),
1184 (Color::Xyza(a), Color::Xyza(b)) => Ok(Color::Xyza(a.mix(b, t))),
1185 (Color::Okhsla(a), Color::Okhsla(b)) => Ok(Color::Okhsla(a.mix(b, t))),
1186 (Color::Okhsva(a), Color::Okhsva(b)) => Ok(Color::Okhsva(a.mix(b, t))),
1187 (Color::Okhwba(a), Color::Okhwba(b)) => Ok(Color::Okhwba(a.mix(b, t))),
1188 _ => Err(MismatchedUnitsError),
1189 }
1190 }
1191}