1use crate::{
2 color_difference::EuclideanDistance, Alpha, Hsla, Hsva, Hue, Hwba, Laba, Lcha, LinearRgba,
3 Luminance, Mix, Oklaba, Oklcha, Saturation, Srgba, StandardColor, Xyza,
4};
5use bevy_math::{MismatchedUnitsError, TryStableInterpolate};
6#[cfg(feature = "bevy_reflect")]
7use bevy_reflect::prelude::*;
8use derive_more::derive::From;
9
10#[doc = include_str!("../docs/conversion.md")]
15#[doc = include_str!("../docs/diagrams/model_graph.svg")]
17#[derive(Debug, Clone, Copy, PartialEq, From)]
46#[cfg_attr(
47 feature = "bevy_reflect",
48 derive(Reflect),
49 reflect(Clone, PartialEq, Default)
50)]
51#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
52#[cfg_attr(
53 all(feature = "serialize", feature = "bevy_reflect"),
54 reflect(Serialize, Deserialize)
55)]
56pub enum Color {
57 Srgba(Srgba),
59 LinearRgba(LinearRgba),
61 Hsla(Hsla),
63 Hsva(Hsva),
65 Hwba(Hwba),
67 Laba(Laba),
69 Lcha(Lcha),
71 Oklaba(Oklaba),
73 Oklcha(Oklcha),
75 Xyza(Xyza),
77}
78
79impl StandardColor for Color {}
80
81impl Color {
82 pub fn to_linear(&self) -> LinearRgba {
84 (*self).into()
85 }
86
87 pub fn to_srgba(&self) -> Srgba {
89 (*self).into()
90 }
91
92 pub const fn srgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
101 Self::Srgba(Srgba {
102 red,
103 green,
104 blue,
105 alpha,
106 })
107 }
108
109 pub const fn srgb(red: f32, green: f32, blue: f32) -> Self {
117 Self::Srgba(Srgba {
118 red,
119 green,
120 blue,
121 alpha: 1.0,
122 })
123 }
124
125 pub const fn srgb_from_array(array: [f32; 3]) -> Self {
130 Self::Srgba(Srgba {
131 red: array[0],
132 green: array[1],
133 blue: array[2],
134 alpha: 1.0,
135 })
136 }
137
138 pub const fn srgba_u8(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
147 Self::Srgba(Srgba {
148 red: red as f32 / 255.0,
149 green: green as f32 / 255.0,
150 blue: blue as f32 / 255.0,
151 alpha: alpha as f32 / 255.0,
152 })
153 }
154
155 pub const fn srgb_u8(red: u8, green: u8, blue: u8) -> Self {
163 Self::Srgba(Srgba {
164 red: red as f32 / 255.0,
165 green: green as f32 / 255.0,
166 blue: blue as f32 / 255.0,
167 alpha: 1.0,
168 })
169 }
170
171 pub fn srgb_u32(color: u32) -> Self {
183 Self::Srgba(Srgba::rgb(
184 ((color >> 16) & 0xff) as f32 / 255.,
185 ((color >> 8) & 0xff) as f32 / 255.,
186 (color & 0xff) as f32 / 255.,
187 ))
188 }
189
190 pub fn srgba_u32(color: u32) -> Self {
202 Self::Srgba(Srgba::new(
203 ((color >> 24) & 0xff) as f32 / 255.,
204 ((color >> 16) & 0xff) as f32 / 255.,
205 ((color >> 8) & 0xff) as f32 / 255.,
206 (color & 0xff) as f32 / 255.,
207 ))
208 }
209
210 pub const fn linear_rgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
219 Self::LinearRgba(LinearRgba {
220 red,
221 green,
222 blue,
223 alpha,
224 })
225 }
226
227 pub const fn linear_rgb(red: f32, green: f32, blue: f32) -> Self {
235 Self::LinearRgba(LinearRgba {
236 red,
237 green,
238 blue,
239 alpha: 1.0,
240 })
241 }
242
243 pub const fn hsla(hue: f32, saturation: f32, lightness: f32, alpha: f32) -> Self {
252 Self::Hsla(Hsla {
253 hue,
254 saturation,
255 lightness,
256 alpha,
257 })
258 }
259
260 pub const fn hsl(hue: f32, saturation: f32, lightness: f32) -> Self {
268 Self::Hsla(Hsla {
269 hue,
270 saturation,
271 lightness,
272 alpha: 1.0,
273 })
274 }
275
276 pub const fn hsva(hue: f32, saturation: f32, value: f32, alpha: f32) -> Self {
285 Self::Hsva(Hsva {
286 hue,
287 saturation,
288 value,
289 alpha,
290 })
291 }
292
293 pub const fn hsv(hue: f32, saturation: f32, value: f32) -> Self {
301 Self::Hsva(Hsva {
302 hue,
303 saturation,
304 value,
305 alpha: 1.0,
306 })
307 }
308
309 pub const fn hwba(hue: f32, whiteness: f32, blackness: f32, alpha: f32) -> Self {
318 Self::Hwba(Hwba {
319 hue,
320 whiteness,
321 blackness,
322 alpha,
323 })
324 }
325
326 pub const fn hwb(hue: f32, whiteness: f32, blackness: f32) -> Self {
334 Self::Hwba(Hwba {
335 hue,
336 whiteness,
337 blackness,
338 alpha: 1.0,
339 })
340 }
341
342 pub const fn laba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
351 Self::Laba(Laba {
352 lightness,
353 a,
354 b,
355 alpha,
356 })
357 }
358
359 pub const fn lab(lightness: f32, a: f32, b: f32) -> Self {
367 Self::Laba(Laba {
368 lightness,
369 a,
370 b,
371 alpha: 1.0,
372 })
373 }
374
375 pub const fn lcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
384 Self::Lcha(Lcha {
385 lightness,
386 chroma,
387 hue,
388 alpha,
389 })
390 }
391
392 pub const fn lch(lightness: f32, chroma: f32, hue: f32) -> Self {
400 Self::Lcha(Lcha {
401 lightness,
402 chroma,
403 hue,
404 alpha: 1.0,
405 })
406 }
407
408 pub const fn oklaba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
417 Self::Oklaba(Oklaba {
418 lightness,
419 a,
420 b,
421 alpha,
422 })
423 }
424
425 pub const fn oklab(lightness: f32, a: f32, b: f32) -> Self {
433 Self::Oklaba(Oklaba {
434 lightness,
435 a,
436 b,
437 alpha: 1.0,
438 })
439 }
440
441 pub const fn oklcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
450 Self::Oklcha(Oklcha {
451 lightness,
452 chroma,
453 hue,
454 alpha,
455 })
456 }
457
458 pub const fn oklch(lightness: f32, chroma: f32, hue: f32) -> Self {
466 Self::Oklcha(Oklcha {
467 lightness,
468 chroma,
469 hue,
470 alpha: 1.0,
471 })
472 }
473
474 pub const fn xyza(x: f32, y: f32, z: f32, alpha: f32) -> Self {
483 Self::Xyza(Xyza { x, y, z, alpha })
484 }
485
486 pub const fn xyz(x: f32, y: f32, z: f32) -> Self {
494 Self::Xyza(Xyza {
495 x,
496 y,
497 z,
498 alpha: 1.0,
499 })
500 }
501
502 pub const WHITE: Self = Self::linear_rgb(1.0, 1.0, 1.0);
504
505 pub const BLACK: Self = Self::linear_rgb(0., 0., 0.);
507
508 pub const NONE: Self = Self::linear_rgba(0., 0., 0., 0.);
510}
511
512impl Default for Color {
513 fn default() -> Self {
515 Color::WHITE
516 }
517}
518
519impl Alpha for Color {
520 fn with_alpha(&self, alpha: f32) -> Self {
521 let mut new = *self;
522
523 match &mut new {
524 Color::Srgba(x) => *x = x.with_alpha(alpha),
525 Color::LinearRgba(x) => *x = x.with_alpha(alpha),
526 Color::Hsla(x) => *x = x.with_alpha(alpha),
527 Color::Hsva(x) => *x = x.with_alpha(alpha),
528 Color::Hwba(x) => *x = x.with_alpha(alpha),
529 Color::Laba(x) => *x = x.with_alpha(alpha),
530 Color::Lcha(x) => *x = x.with_alpha(alpha),
531 Color::Oklaba(x) => *x = x.with_alpha(alpha),
532 Color::Oklcha(x) => *x = x.with_alpha(alpha),
533 Color::Xyza(x) => *x = x.with_alpha(alpha),
534 }
535
536 new
537 }
538
539 fn alpha(&self) -> f32 {
540 match self {
541 Color::Srgba(x) => x.alpha(),
542 Color::LinearRgba(x) => x.alpha(),
543 Color::Hsla(x) => x.alpha(),
544 Color::Hsva(x) => x.alpha(),
545 Color::Hwba(x) => x.alpha(),
546 Color::Laba(x) => x.alpha(),
547 Color::Lcha(x) => x.alpha(),
548 Color::Oklaba(x) => x.alpha(),
549 Color::Oklcha(x) => x.alpha(),
550 Color::Xyza(x) => x.alpha(),
551 }
552 }
553
554 fn set_alpha(&mut self, alpha: f32) {
555 match self {
556 Color::Srgba(x) => x.set_alpha(alpha),
557 Color::LinearRgba(x) => x.set_alpha(alpha),
558 Color::Hsla(x) => x.set_alpha(alpha),
559 Color::Hsva(x) => x.set_alpha(alpha),
560 Color::Hwba(x) => x.set_alpha(alpha),
561 Color::Laba(x) => x.set_alpha(alpha),
562 Color::Lcha(x) => x.set_alpha(alpha),
563 Color::Oklaba(x) => x.set_alpha(alpha),
564 Color::Oklcha(x) => x.set_alpha(alpha),
565 Color::Xyza(x) => x.set_alpha(alpha),
566 }
567 }
568}
569
570impl From<Color> for Srgba {
571 fn from(value: Color) -> Self {
572 match value {
573 Color::Srgba(srgba) => srgba,
574 Color::LinearRgba(linear) => linear.into(),
575 Color::Hsla(hsla) => hsla.into(),
576 Color::Hsva(hsva) => hsva.into(),
577 Color::Hwba(hwba) => hwba.into(),
578 Color::Laba(laba) => laba.into(),
579 Color::Lcha(lcha) => lcha.into(),
580 Color::Oklaba(oklab) => oklab.into(),
581 Color::Oklcha(oklch) => oklch.into(),
582 Color::Xyza(xyza) => xyza.into(),
583 }
584 }
585}
586
587impl From<Color> for LinearRgba {
588 fn from(value: Color) -> Self {
589 match value {
590 Color::Srgba(srgba) => srgba.into(),
591 Color::LinearRgba(linear) => linear,
592 Color::Hsla(hsla) => hsla.into(),
593 Color::Hsva(hsva) => hsva.into(),
594 Color::Hwba(hwba) => hwba.into(),
595 Color::Laba(laba) => laba.into(),
596 Color::Lcha(lcha) => lcha.into(),
597 Color::Oklaba(oklab) => oklab.into(),
598 Color::Oklcha(oklch) => oklch.into(),
599 Color::Xyza(xyza) => xyza.into(),
600 }
601 }
602}
603
604impl From<Color> for Hsla {
605 fn from(value: Color) -> Self {
606 match value {
607 Color::Srgba(srgba) => srgba.into(),
608 Color::LinearRgba(linear) => linear.into(),
609 Color::Hsla(hsla) => hsla,
610 Color::Hsva(hsva) => hsva.into(),
611 Color::Hwba(hwba) => hwba.into(),
612 Color::Laba(laba) => laba.into(),
613 Color::Lcha(lcha) => lcha.into(),
614 Color::Oklaba(oklab) => oklab.into(),
615 Color::Oklcha(oklch) => oklch.into(),
616 Color::Xyza(xyza) => xyza.into(),
617 }
618 }
619}
620
621impl From<Color> for Hsva {
622 fn from(value: Color) -> Self {
623 match value {
624 Color::Srgba(srgba) => srgba.into(),
625 Color::LinearRgba(linear) => linear.into(),
626 Color::Hsla(hsla) => hsla.into(),
627 Color::Hsva(hsva) => hsva,
628 Color::Hwba(hwba) => hwba.into(),
629 Color::Laba(laba) => laba.into(),
630 Color::Lcha(lcha) => lcha.into(),
631 Color::Oklaba(oklab) => oklab.into(),
632 Color::Oklcha(oklch) => oklch.into(),
633 Color::Xyza(xyza) => xyza.into(),
634 }
635 }
636}
637
638impl From<Color> for Hwba {
639 fn from(value: Color) -> Self {
640 match value {
641 Color::Srgba(srgba) => srgba.into(),
642 Color::LinearRgba(linear) => linear.into(),
643 Color::Hsla(hsla) => hsla.into(),
644 Color::Hsva(hsva) => hsva.into(),
645 Color::Hwba(hwba) => hwba,
646 Color::Laba(laba) => laba.into(),
647 Color::Lcha(lcha) => lcha.into(),
648 Color::Oklaba(oklab) => oklab.into(),
649 Color::Oklcha(oklch) => oklch.into(),
650 Color::Xyza(xyza) => xyza.into(),
651 }
652 }
653}
654
655impl From<Color> for Laba {
656 fn from(value: Color) -> Self {
657 match value {
658 Color::Srgba(srgba) => srgba.into(),
659 Color::LinearRgba(linear) => linear.into(),
660 Color::Hsla(hsla) => hsla.into(),
661 Color::Hsva(hsva) => hsva.into(),
662 Color::Hwba(hwba) => hwba.into(),
663 Color::Laba(laba) => laba,
664 Color::Lcha(lcha) => lcha.into(),
665 Color::Oklaba(oklab) => oklab.into(),
666 Color::Oklcha(oklch) => oklch.into(),
667 Color::Xyza(xyza) => xyza.into(),
668 }
669 }
670}
671
672impl From<Color> for Lcha {
673 fn from(value: Color) -> Self {
674 match value {
675 Color::Srgba(srgba) => srgba.into(),
676 Color::LinearRgba(linear) => linear.into(),
677 Color::Hsla(hsla) => hsla.into(),
678 Color::Hsva(hsva) => hsva.into(),
679 Color::Hwba(hwba) => hwba.into(),
680 Color::Laba(laba) => laba.into(),
681 Color::Lcha(lcha) => lcha,
682 Color::Oklaba(oklab) => oklab.into(),
683 Color::Oklcha(oklch) => oklch.into(),
684 Color::Xyza(xyza) => xyza.into(),
685 }
686 }
687}
688
689impl From<Color> for Oklaba {
690 fn from(value: Color) -> Self {
691 match value {
692 Color::Srgba(srgba) => srgba.into(),
693 Color::LinearRgba(linear) => linear.into(),
694 Color::Hsla(hsla) => hsla.into(),
695 Color::Hsva(hsva) => hsva.into(),
696 Color::Hwba(hwba) => hwba.into(),
697 Color::Laba(laba) => laba.into(),
698 Color::Lcha(lcha) => lcha.into(),
699 Color::Oklaba(oklab) => oklab,
700 Color::Oklcha(oklch) => oklch.into(),
701 Color::Xyza(xyza) => xyza.into(),
702 }
703 }
704}
705
706impl From<Color> for Oklcha {
707 fn from(value: Color) -> Self {
708 match value {
709 Color::Srgba(srgba) => srgba.into(),
710 Color::LinearRgba(linear) => linear.into(),
711 Color::Hsla(hsla) => hsla.into(),
712 Color::Hsva(hsva) => hsva.into(),
713 Color::Hwba(hwba) => hwba.into(),
714 Color::Laba(laba) => laba.into(),
715 Color::Lcha(lcha) => lcha.into(),
716 Color::Oklaba(oklab) => oklab.into(),
717 Color::Oklcha(oklch) => oklch,
718 Color::Xyza(xyza) => xyza.into(),
719 }
720 }
721}
722
723impl From<Color> for Xyza {
724 fn from(value: Color) -> Self {
725 match value {
726 Color::Srgba(x) => x.into(),
727 Color::LinearRgba(x) => x.into(),
728 Color::Hsla(x) => x.into(),
729 Color::Hsva(hsva) => hsva.into(),
730 Color::Hwba(hwba) => hwba.into(),
731 Color::Laba(laba) => laba.into(),
732 Color::Lcha(x) => x.into(),
733 Color::Oklaba(x) => x.into(),
734 Color::Oklcha(oklch) => oklch.into(),
735 Color::Xyza(xyza) => xyza,
736 }
737 }
738}
739
740type ChosenColorSpace = Oklcha;
742
743impl Luminance for Color {
744 fn luminance(&self) -> f32 {
745 match self {
746 Color::Srgba(x) => x.luminance(),
747 Color::LinearRgba(x) => x.luminance(),
748 Color::Hsla(x) => x.luminance(),
749 Color::Hsva(x) => ChosenColorSpace::from(*x).luminance(),
750 Color::Hwba(x) => ChosenColorSpace::from(*x).luminance(),
751 Color::Laba(x) => x.luminance(),
752 Color::Lcha(x) => x.luminance(),
753 Color::Oklaba(x) => x.luminance(),
754 Color::Oklcha(x) => x.luminance(),
755 Color::Xyza(x) => x.luminance(),
756 }
757 }
758
759 fn with_luminance(&self, value: f32) -> Self {
760 let mut new = *self;
761
762 match &mut new {
763 Color::Srgba(x) => *x = x.with_luminance(value),
764 Color::LinearRgba(x) => *x = x.with_luminance(value),
765 Color::Hsla(x) => *x = x.with_luminance(value),
766 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
767 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
768 Color::Laba(x) => *x = x.with_luminance(value),
769 Color::Lcha(x) => *x = x.with_luminance(value),
770 Color::Oklaba(x) => *x = x.with_luminance(value),
771 Color::Oklcha(x) => *x = x.with_luminance(value),
772 Color::Xyza(x) => *x = x.with_luminance(value),
773 }
774
775 new
776 }
777
778 fn darker(&self, amount: f32) -> Self {
779 let mut new = *self;
780
781 match &mut new {
782 Color::Srgba(x) => *x = x.darker(amount),
783 Color::LinearRgba(x) => *x = x.darker(amount),
784 Color::Hsla(x) => *x = x.darker(amount),
785 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
786 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
787 Color::Laba(x) => *x = x.darker(amount),
788 Color::Lcha(x) => *x = x.darker(amount),
789 Color::Oklaba(x) => *x = x.darker(amount),
790 Color::Oklcha(x) => *x = x.darker(amount),
791 Color::Xyza(x) => *x = x.darker(amount),
792 }
793
794 new
795 }
796
797 fn lighter(&self, amount: f32) -> Self {
798 let mut new = *self;
799
800 match &mut new {
801 Color::Srgba(x) => *x = x.lighter(amount),
802 Color::LinearRgba(x) => *x = x.lighter(amount),
803 Color::Hsla(x) => *x = x.lighter(amount),
804 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
805 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
806 Color::Laba(x) => *x = x.lighter(amount),
807 Color::Lcha(x) => *x = x.lighter(amount),
808 Color::Oklaba(x) => *x = x.lighter(amount),
809 Color::Oklcha(x) => *x = x.lighter(amount),
810 Color::Xyza(x) => *x = x.lighter(amount),
811 }
812
813 new
814 }
815}
816
817impl Hue for Color {
818 fn with_hue(&self, hue: f32) -> Self {
819 let mut new = *self;
820
821 match &mut new {
822 Color::Srgba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
823 Color::LinearRgba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
824 Color::Hsla(x) => *x = x.with_hue(hue),
825 Color::Hsva(x) => *x = x.with_hue(hue),
826 Color::Hwba(x) => *x = x.with_hue(hue),
827 Color::Laba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
828 Color::Lcha(x) => *x = x.with_hue(hue),
829 Color::Oklaba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
830 Color::Oklcha(x) => *x = x.with_hue(hue),
831 Color::Xyza(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
832 }
833
834 new
835 }
836
837 fn hue(&self) -> f32 {
838 match self {
839 Color::Srgba(x) => ChosenColorSpace::from(*x).hue(),
840 Color::LinearRgba(x) => ChosenColorSpace::from(*x).hue(),
841 Color::Hsla(x) => x.hue(),
842 Color::Hsva(x) => x.hue(),
843 Color::Hwba(x) => x.hue(),
844 Color::Laba(x) => ChosenColorSpace::from(*x).hue(),
845 Color::Lcha(x) => x.hue(),
846 Color::Oklaba(x) => ChosenColorSpace::from(*x).hue(),
847 Color::Oklcha(x) => x.hue(),
848 Color::Xyza(x) => ChosenColorSpace::from(*x).hue(),
849 }
850 }
851
852 fn set_hue(&mut self, hue: f32) {
853 *self = self.with_hue(hue);
854 }
855}
856
857impl Saturation for Color {
858 fn with_saturation(&self, saturation: f32) -> Self {
859 let mut new = *self;
860
861 match &mut new {
862 Color::Srgba(x) => Hsla::from(*x).with_saturation(saturation).into(),
863 Color::LinearRgba(x) => Hsla::from(*x).with_saturation(saturation).into(),
864 Color::Hsla(x) => x.with_saturation(saturation).into(),
865 Color::Hsva(x) => x.with_saturation(saturation).into(),
866 Color::Hwba(x) => Hsla::from(*x).with_saturation(saturation).into(),
867 Color::Laba(x) => Hsla::from(*x).with_saturation(saturation).into(),
868 Color::Lcha(x) => Hsla::from(*x).with_saturation(saturation).into(),
869 Color::Oklaba(x) => Hsla::from(*x).with_saturation(saturation).into(),
870 Color::Oklcha(x) => Hsla::from(*x).with_saturation(saturation).into(),
871 Color::Xyza(x) => Hsla::from(*x).with_saturation(saturation).into(),
872 }
873 }
874
875 fn saturation(&self) -> f32 {
876 match self {
877 Color::Srgba(x) => Hsla::from(*x).saturation(),
878 Color::LinearRgba(x) => Hsla::from(*x).saturation(),
879 Color::Hsla(x) => x.saturation(),
880 Color::Hsva(x) => x.saturation(),
881 Color::Hwba(x) => Hsla::from(*x).saturation(),
882 Color::Laba(x) => Hsla::from(*x).saturation(),
883 Color::Lcha(x) => Hsla::from(*x).saturation(),
884 Color::Oklaba(x) => Hsla::from(*x).saturation(),
885 Color::Oklcha(x) => Hsla::from(*x).saturation(),
886 Color::Xyza(x) => Hsla::from(*x).saturation(),
887 }
888 }
889
890 fn set_saturation(&mut self, saturation: f32) {
891 *self = self.with_saturation(saturation);
892 }
893}
894
895impl Mix for Color {
896 fn mix(&self, other: &Self, factor: f32) -> Self {
897 let mut new = *self;
898
899 match &mut new {
900 Color::Srgba(x) => *x = x.mix(&(*other).into(), factor),
901 Color::LinearRgba(x) => *x = x.mix(&(*other).into(), factor),
902 Color::Hsla(x) => *x = x.mix(&(*other).into(), factor),
903 Color::Hsva(x) => *x = x.mix(&(*other).into(), factor),
904 Color::Hwba(x) => *x = x.mix(&(*other).into(), factor),
905 Color::Laba(x) => *x = x.mix(&(*other).into(), factor),
906 Color::Lcha(x) => *x = x.mix(&(*other).into(), factor),
907 Color::Oklaba(x) => *x = x.mix(&(*other).into(), factor),
908 Color::Oklcha(x) => *x = x.mix(&(*other).into(), factor),
909 Color::Xyza(x) => *x = x.mix(&(*other).into(), factor),
910 }
911
912 new
913 }
914}
915
916impl EuclideanDistance for Color {
917 fn distance_squared(&self, other: &Self) -> f32 {
918 match self {
919 Color::Srgba(x) => x.distance_squared(&(*other).into()),
920 Color::LinearRgba(x) => x.distance_squared(&(*other).into()),
921 Color::Hsla(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
922 Color::Hsva(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
923 Color::Hwba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
924 Color::Laba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
925 Color::Lcha(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
926 Color::Oklaba(x) => x.distance_squared(&(*other).into()),
927 Color::Oklcha(x) => x.distance_squared(&(*other).into()),
928 Color::Xyza(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
929 }
930 }
931}
932
933impl TryStableInterpolate for Color {
934 type Error = MismatchedUnitsError;
935
936 fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
937 match (self, other) {
938 (Color::Srgba(a), Color::Srgba(b)) => Ok(Color::Srgba(a.mix(b, t))),
939 (Color::LinearRgba(a), Color::LinearRgba(b)) => Ok(Color::LinearRgba(a.mix(b, t))),
940 (Color::Hsla(a), Color::Hsla(b)) => Ok(Color::Hsla(a.mix(b, t))),
941 (Color::Hsva(a), Color::Hsva(b)) => Ok(Color::Hsva(a.mix(b, t))),
942 (Color::Hwba(a), Color::Hwba(b)) => Ok(Color::Hwba(a.mix(b, t))),
943 (Color::Laba(a), Color::Laba(b)) => Ok(Color::Laba(a.mix(b, t))),
944 (Color::Lcha(a), Color::Lcha(b)) => Ok(Color::Lcha(a.mix(b, t))),
945 (Color::Oklaba(a), Color::Oklaba(b)) => Ok(Color::Oklaba(a.mix(b, t))),
946 (Color::Oklcha(a), Color::Oklcha(b)) => Ok(Color::Oklcha(a.mix(b, t))),
947 (Color::Xyza(a), Color::Xyza(b)) => Ok(Color::Xyza(a.mix(b, t))),
948 _ => Err(MismatchedUnitsError),
949 }
950 }
951}