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 const fn linear_rgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
180 Self::LinearRgba(LinearRgba {
181 red,
182 green,
183 blue,
184 alpha,
185 })
186 }
187
188 pub const fn linear_rgb(red: f32, green: f32, blue: f32) -> Self {
196 Self::LinearRgba(LinearRgba {
197 red,
198 green,
199 blue,
200 alpha: 1.0,
201 })
202 }
203
204 pub const fn hsla(hue: f32, saturation: f32, lightness: f32, alpha: f32) -> Self {
213 Self::Hsla(Hsla {
214 hue,
215 saturation,
216 lightness,
217 alpha,
218 })
219 }
220
221 pub const fn hsl(hue: f32, saturation: f32, lightness: f32) -> Self {
229 Self::Hsla(Hsla {
230 hue,
231 saturation,
232 lightness,
233 alpha: 1.0,
234 })
235 }
236
237 pub const fn hsva(hue: f32, saturation: f32, value: f32, alpha: f32) -> Self {
246 Self::Hsva(Hsva {
247 hue,
248 saturation,
249 value,
250 alpha,
251 })
252 }
253
254 pub const fn hsv(hue: f32, saturation: f32, value: f32) -> Self {
262 Self::Hsva(Hsva {
263 hue,
264 saturation,
265 value,
266 alpha: 1.0,
267 })
268 }
269
270 pub const fn hwba(hue: f32, whiteness: f32, blackness: f32, alpha: f32) -> Self {
279 Self::Hwba(Hwba {
280 hue,
281 whiteness,
282 blackness,
283 alpha,
284 })
285 }
286
287 pub const fn hwb(hue: f32, whiteness: f32, blackness: f32) -> Self {
295 Self::Hwba(Hwba {
296 hue,
297 whiteness,
298 blackness,
299 alpha: 1.0,
300 })
301 }
302
303 pub const fn laba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
312 Self::Laba(Laba {
313 lightness,
314 a,
315 b,
316 alpha,
317 })
318 }
319
320 pub const fn lab(lightness: f32, a: f32, b: f32) -> Self {
328 Self::Laba(Laba {
329 lightness,
330 a,
331 b,
332 alpha: 1.0,
333 })
334 }
335
336 pub const fn lcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
345 Self::Lcha(Lcha {
346 lightness,
347 chroma,
348 hue,
349 alpha,
350 })
351 }
352
353 pub const fn lch(lightness: f32, chroma: f32, hue: f32) -> Self {
361 Self::Lcha(Lcha {
362 lightness,
363 chroma,
364 hue,
365 alpha: 1.0,
366 })
367 }
368
369 pub const fn oklaba(lightness: f32, a: f32, b: f32, alpha: f32) -> Self {
378 Self::Oklaba(Oklaba {
379 lightness,
380 a,
381 b,
382 alpha,
383 })
384 }
385
386 pub const fn oklab(lightness: f32, a: f32, b: f32) -> Self {
394 Self::Oklaba(Oklaba {
395 lightness,
396 a,
397 b,
398 alpha: 1.0,
399 })
400 }
401
402 pub const fn oklcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
411 Self::Oklcha(Oklcha {
412 lightness,
413 chroma,
414 hue,
415 alpha,
416 })
417 }
418
419 pub const fn oklch(lightness: f32, chroma: f32, hue: f32) -> Self {
427 Self::Oklcha(Oklcha {
428 lightness,
429 chroma,
430 hue,
431 alpha: 1.0,
432 })
433 }
434
435 pub const fn xyza(x: f32, y: f32, z: f32, alpha: f32) -> Self {
444 Self::Xyza(Xyza { x, y, z, alpha })
445 }
446
447 pub const fn xyz(x: f32, y: f32, z: f32) -> Self {
455 Self::Xyza(Xyza {
456 x,
457 y,
458 z,
459 alpha: 1.0,
460 })
461 }
462
463 pub const WHITE: Self = Self::linear_rgb(1.0, 1.0, 1.0);
465
466 pub const BLACK: Self = Self::linear_rgb(0., 0., 0.);
468
469 pub const NONE: Self = Self::linear_rgba(0., 0., 0., 0.);
471}
472
473impl Default for Color {
474 fn default() -> Self {
476 Color::WHITE
477 }
478}
479
480impl Alpha for Color {
481 fn with_alpha(&self, alpha: f32) -> Self {
482 let mut new = *self;
483
484 match &mut new {
485 Color::Srgba(x) => *x = x.with_alpha(alpha),
486 Color::LinearRgba(x) => *x = x.with_alpha(alpha),
487 Color::Hsla(x) => *x = x.with_alpha(alpha),
488 Color::Hsva(x) => *x = x.with_alpha(alpha),
489 Color::Hwba(x) => *x = x.with_alpha(alpha),
490 Color::Laba(x) => *x = x.with_alpha(alpha),
491 Color::Lcha(x) => *x = x.with_alpha(alpha),
492 Color::Oklaba(x) => *x = x.with_alpha(alpha),
493 Color::Oklcha(x) => *x = x.with_alpha(alpha),
494 Color::Xyza(x) => *x = x.with_alpha(alpha),
495 }
496
497 new
498 }
499
500 fn alpha(&self) -> f32 {
501 match self {
502 Color::Srgba(x) => x.alpha(),
503 Color::LinearRgba(x) => x.alpha(),
504 Color::Hsla(x) => x.alpha(),
505 Color::Hsva(x) => x.alpha(),
506 Color::Hwba(x) => x.alpha(),
507 Color::Laba(x) => x.alpha(),
508 Color::Lcha(x) => x.alpha(),
509 Color::Oklaba(x) => x.alpha(),
510 Color::Oklcha(x) => x.alpha(),
511 Color::Xyza(x) => x.alpha(),
512 }
513 }
514
515 fn set_alpha(&mut self, alpha: f32) {
516 match self {
517 Color::Srgba(x) => x.set_alpha(alpha),
518 Color::LinearRgba(x) => x.set_alpha(alpha),
519 Color::Hsla(x) => x.set_alpha(alpha),
520 Color::Hsva(x) => x.set_alpha(alpha),
521 Color::Hwba(x) => x.set_alpha(alpha),
522 Color::Laba(x) => x.set_alpha(alpha),
523 Color::Lcha(x) => x.set_alpha(alpha),
524 Color::Oklaba(x) => x.set_alpha(alpha),
525 Color::Oklcha(x) => x.set_alpha(alpha),
526 Color::Xyza(x) => x.set_alpha(alpha),
527 }
528 }
529}
530
531impl From<Color> for Srgba {
532 fn from(value: Color) -> Self {
533 match value {
534 Color::Srgba(srgba) => srgba,
535 Color::LinearRgba(linear) => linear.into(),
536 Color::Hsla(hsla) => hsla.into(),
537 Color::Hsva(hsva) => hsva.into(),
538 Color::Hwba(hwba) => hwba.into(),
539 Color::Laba(laba) => laba.into(),
540 Color::Lcha(lcha) => lcha.into(),
541 Color::Oklaba(oklab) => oklab.into(),
542 Color::Oklcha(oklch) => oklch.into(),
543 Color::Xyza(xyza) => xyza.into(),
544 }
545 }
546}
547
548impl From<Color> for LinearRgba {
549 fn from(value: Color) -> Self {
550 match value {
551 Color::Srgba(srgba) => srgba.into(),
552 Color::LinearRgba(linear) => linear,
553 Color::Hsla(hsla) => hsla.into(),
554 Color::Hsva(hsva) => hsva.into(),
555 Color::Hwba(hwba) => hwba.into(),
556 Color::Laba(laba) => laba.into(),
557 Color::Lcha(lcha) => lcha.into(),
558 Color::Oklaba(oklab) => oklab.into(),
559 Color::Oklcha(oklch) => oklch.into(),
560 Color::Xyza(xyza) => xyza.into(),
561 }
562 }
563}
564
565impl From<Color> for Hsla {
566 fn from(value: Color) -> Self {
567 match value {
568 Color::Srgba(srgba) => srgba.into(),
569 Color::LinearRgba(linear) => linear.into(),
570 Color::Hsla(hsla) => hsla,
571 Color::Hsva(hsva) => hsva.into(),
572 Color::Hwba(hwba) => hwba.into(),
573 Color::Laba(laba) => laba.into(),
574 Color::Lcha(lcha) => lcha.into(),
575 Color::Oklaba(oklab) => oklab.into(),
576 Color::Oklcha(oklch) => oklch.into(),
577 Color::Xyza(xyza) => xyza.into(),
578 }
579 }
580}
581
582impl From<Color> for Hsva {
583 fn from(value: Color) -> Self {
584 match value {
585 Color::Srgba(srgba) => srgba.into(),
586 Color::LinearRgba(linear) => linear.into(),
587 Color::Hsla(hsla) => hsla.into(),
588 Color::Hsva(hsva) => hsva,
589 Color::Hwba(hwba) => hwba.into(),
590 Color::Laba(laba) => laba.into(),
591 Color::Lcha(lcha) => lcha.into(),
592 Color::Oklaba(oklab) => oklab.into(),
593 Color::Oklcha(oklch) => oklch.into(),
594 Color::Xyza(xyza) => xyza.into(),
595 }
596 }
597}
598
599impl From<Color> for Hwba {
600 fn from(value: Color) -> Self {
601 match value {
602 Color::Srgba(srgba) => srgba.into(),
603 Color::LinearRgba(linear) => linear.into(),
604 Color::Hsla(hsla) => hsla.into(),
605 Color::Hsva(hsva) => hsva.into(),
606 Color::Hwba(hwba) => hwba,
607 Color::Laba(laba) => laba.into(),
608 Color::Lcha(lcha) => lcha.into(),
609 Color::Oklaba(oklab) => oklab.into(),
610 Color::Oklcha(oklch) => oklch.into(),
611 Color::Xyza(xyza) => xyza.into(),
612 }
613 }
614}
615
616impl From<Color> for Laba {
617 fn from(value: Color) -> Self {
618 match value {
619 Color::Srgba(srgba) => srgba.into(),
620 Color::LinearRgba(linear) => linear.into(),
621 Color::Hsla(hsla) => hsla.into(),
622 Color::Hsva(hsva) => hsva.into(),
623 Color::Hwba(hwba) => hwba.into(),
624 Color::Laba(laba) => laba,
625 Color::Lcha(lcha) => lcha.into(),
626 Color::Oklaba(oklab) => oklab.into(),
627 Color::Oklcha(oklch) => oklch.into(),
628 Color::Xyza(xyza) => xyza.into(),
629 }
630 }
631}
632
633impl From<Color> for Lcha {
634 fn from(value: Color) -> Self {
635 match value {
636 Color::Srgba(srgba) => srgba.into(),
637 Color::LinearRgba(linear) => linear.into(),
638 Color::Hsla(hsla) => hsla.into(),
639 Color::Hsva(hsva) => hsva.into(),
640 Color::Hwba(hwba) => hwba.into(),
641 Color::Laba(laba) => laba.into(),
642 Color::Lcha(lcha) => lcha,
643 Color::Oklaba(oklab) => oklab.into(),
644 Color::Oklcha(oklch) => oklch.into(),
645 Color::Xyza(xyza) => xyza.into(),
646 }
647 }
648}
649
650impl From<Color> for Oklaba {
651 fn from(value: Color) -> Self {
652 match value {
653 Color::Srgba(srgba) => srgba.into(),
654 Color::LinearRgba(linear) => linear.into(),
655 Color::Hsla(hsla) => hsla.into(),
656 Color::Hsva(hsva) => hsva.into(),
657 Color::Hwba(hwba) => hwba.into(),
658 Color::Laba(laba) => laba.into(),
659 Color::Lcha(lcha) => lcha.into(),
660 Color::Oklaba(oklab) => oklab,
661 Color::Oklcha(oklch) => oklch.into(),
662 Color::Xyza(xyza) => xyza.into(),
663 }
664 }
665}
666
667impl From<Color> for Oklcha {
668 fn from(value: Color) -> Self {
669 match value {
670 Color::Srgba(srgba) => srgba.into(),
671 Color::LinearRgba(linear) => linear.into(),
672 Color::Hsla(hsla) => hsla.into(),
673 Color::Hsva(hsva) => hsva.into(),
674 Color::Hwba(hwba) => hwba.into(),
675 Color::Laba(laba) => laba.into(),
676 Color::Lcha(lcha) => lcha.into(),
677 Color::Oklaba(oklab) => oklab.into(),
678 Color::Oklcha(oklch) => oklch,
679 Color::Xyza(xyza) => xyza.into(),
680 }
681 }
682}
683
684impl From<Color> for Xyza {
685 fn from(value: Color) -> Self {
686 match value {
687 Color::Srgba(x) => x.into(),
688 Color::LinearRgba(x) => x.into(),
689 Color::Hsla(x) => x.into(),
690 Color::Hsva(hsva) => hsva.into(),
691 Color::Hwba(hwba) => hwba.into(),
692 Color::Laba(laba) => laba.into(),
693 Color::Lcha(x) => x.into(),
694 Color::Oklaba(x) => x.into(),
695 Color::Oklcha(oklch) => oklch.into(),
696 Color::Xyza(xyza) => xyza,
697 }
698 }
699}
700
701type ChosenColorSpace = Oklcha;
703
704impl Luminance for Color {
705 fn luminance(&self) -> f32 {
706 match self {
707 Color::Srgba(x) => x.luminance(),
708 Color::LinearRgba(x) => x.luminance(),
709 Color::Hsla(x) => x.luminance(),
710 Color::Hsva(x) => ChosenColorSpace::from(*x).luminance(),
711 Color::Hwba(x) => ChosenColorSpace::from(*x).luminance(),
712 Color::Laba(x) => x.luminance(),
713 Color::Lcha(x) => x.luminance(),
714 Color::Oklaba(x) => x.luminance(),
715 Color::Oklcha(x) => x.luminance(),
716 Color::Xyza(x) => x.luminance(),
717 }
718 }
719
720 fn with_luminance(&self, value: f32) -> Self {
721 let mut new = *self;
722
723 match &mut new {
724 Color::Srgba(x) => *x = x.with_luminance(value),
725 Color::LinearRgba(x) => *x = x.with_luminance(value),
726 Color::Hsla(x) => *x = x.with_luminance(value),
727 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
728 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).with_luminance(value).into(),
729 Color::Laba(x) => *x = x.with_luminance(value),
730 Color::Lcha(x) => *x = x.with_luminance(value),
731 Color::Oklaba(x) => *x = x.with_luminance(value),
732 Color::Oklcha(x) => *x = x.with_luminance(value),
733 Color::Xyza(x) => *x = x.with_luminance(value),
734 }
735
736 new
737 }
738
739 fn darker(&self, amount: f32) -> Self {
740 let mut new = *self;
741
742 match &mut new {
743 Color::Srgba(x) => *x = x.darker(amount),
744 Color::LinearRgba(x) => *x = x.darker(amount),
745 Color::Hsla(x) => *x = x.darker(amount),
746 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
747 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).darker(amount).into(),
748 Color::Laba(x) => *x = x.darker(amount),
749 Color::Lcha(x) => *x = x.darker(amount),
750 Color::Oklaba(x) => *x = x.darker(amount),
751 Color::Oklcha(x) => *x = x.darker(amount),
752 Color::Xyza(x) => *x = x.darker(amount),
753 }
754
755 new
756 }
757
758 fn lighter(&self, amount: f32) -> Self {
759 let mut new = *self;
760
761 match &mut new {
762 Color::Srgba(x) => *x = x.lighter(amount),
763 Color::LinearRgba(x) => *x = x.lighter(amount),
764 Color::Hsla(x) => *x = x.lighter(amount),
765 Color::Hsva(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
766 Color::Hwba(x) => *x = ChosenColorSpace::from(*x).lighter(amount).into(),
767 Color::Laba(x) => *x = x.lighter(amount),
768 Color::Lcha(x) => *x = x.lighter(amount),
769 Color::Oklaba(x) => *x = x.lighter(amount),
770 Color::Oklcha(x) => *x = x.lighter(amount),
771 Color::Xyza(x) => *x = x.lighter(amount),
772 }
773
774 new
775 }
776}
777
778impl Hue for Color {
779 fn with_hue(&self, hue: f32) -> Self {
780 let mut new = *self;
781
782 match &mut new {
783 Color::Srgba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
784 Color::LinearRgba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
785 Color::Hsla(x) => *x = x.with_hue(hue),
786 Color::Hsva(x) => *x = x.with_hue(hue),
787 Color::Hwba(x) => *x = x.with_hue(hue),
788 Color::Laba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
789 Color::Lcha(x) => *x = x.with_hue(hue),
790 Color::Oklaba(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
791 Color::Oklcha(x) => *x = x.with_hue(hue),
792 Color::Xyza(x) => *x = ChosenColorSpace::from(*x).with_hue(hue).into(),
793 }
794
795 new
796 }
797
798 fn hue(&self) -> f32 {
799 match self {
800 Color::Srgba(x) => ChosenColorSpace::from(*x).hue(),
801 Color::LinearRgba(x) => ChosenColorSpace::from(*x).hue(),
802 Color::Hsla(x) => x.hue(),
803 Color::Hsva(x) => x.hue(),
804 Color::Hwba(x) => x.hue(),
805 Color::Laba(x) => ChosenColorSpace::from(*x).hue(),
806 Color::Lcha(x) => x.hue(),
807 Color::Oklaba(x) => ChosenColorSpace::from(*x).hue(),
808 Color::Oklcha(x) => x.hue(),
809 Color::Xyza(x) => ChosenColorSpace::from(*x).hue(),
810 }
811 }
812
813 fn set_hue(&mut self, hue: f32) {
814 *self = self.with_hue(hue);
815 }
816}
817
818impl Saturation for Color {
819 fn with_saturation(&self, saturation: f32) -> Self {
820 let mut new = *self;
821
822 match &mut new {
823 Color::Srgba(x) => Hsla::from(*x).with_saturation(saturation).into(),
824 Color::LinearRgba(x) => Hsla::from(*x).with_saturation(saturation).into(),
825 Color::Hsla(x) => x.with_saturation(saturation).into(),
826 Color::Hsva(x) => x.with_saturation(saturation).into(),
827 Color::Hwba(x) => Hsla::from(*x).with_saturation(saturation).into(),
828 Color::Laba(x) => Hsla::from(*x).with_saturation(saturation).into(),
829 Color::Lcha(x) => Hsla::from(*x).with_saturation(saturation).into(),
830 Color::Oklaba(x) => Hsla::from(*x).with_saturation(saturation).into(),
831 Color::Oklcha(x) => Hsla::from(*x).with_saturation(saturation).into(),
832 Color::Xyza(x) => Hsla::from(*x).with_saturation(saturation).into(),
833 }
834 }
835
836 fn saturation(&self) -> f32 {
837 match self {
838 Color::Srgba(x) => Hsla::from(*x).saturation(),
839 Color::LinearRgba(x) => Hsla::from(*x).saturation(),
840 Color::Hsla(x) => x.saturation(),
841 Color::Hsva(x) => x.saturation(),
842 Color::Hwba(x) => Hsla::from(*x).saturation(),
843 Color::Laba(x) => Hsla::from(*x).saturation(),
844 Color::Lcha(x) => Hsla::from(*x).saturation(),
845 Color::Oklaba(x) => Hsla::from(*x).saturation(),
846 Color::Oklcha(x) => Hsla::from(*x).saturation(),
847 Color::Xyza(x) => Hsla::from(*x).saturation(),
848 }
849 }
850
851 fn set_saturation(&mut self, saturation: f32) {
852 *self = self.with_saturation(saturation);
853 }
854}
855
856impl Mix for Color {
857 fn mix(&self, other: &Self, factor: f32) -> Self {
858 let mut new = *self;
859
860 match &mut new {
861 Color::Srgba(x) => *x = x.mix(&(*other).into(), factor),
862 Color::LinearRgba(x) => *x = x.mix(&(*other).into(), factor),
863 Color::Hsla(x) => *x = x.mix(&(*other).into(), factor),
864 Color::Hsva(x) => *x = x.mix(&(*other).into(), factor),
865 Color::Hwba(x) => *x = x.mix(&(*other).into(), factor),
866 Color::Laba(x) => *x = x.mix(&(*other).into(), factor),
867 Color::Lcha(x) => *x = x.mix(&(*other).into(), factor),
868 Color::Oklaba(x) => *x = x.mix(&(*other).into(), factor),
869 Color::Oklcha(x) => *x = x.mix(&(*other).into(), factor),
870 Color::Xyza(x) => *x = x.mix(&(*other).into(), factor),
871 }
872
873 new
874 }
875}
876
877impl EuclideanDistance for Color {
878 fn distance_squared(&self, other: &Self) -> f32 {
879 match self {
880 Color::Srgba(x) => x.distance_squared(&(*other).into()),
881 Color::LinearRgba(x) => x.distance_squared(&(*other).into()),
882 Color::Hsla(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
883 Color::Hsva(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
884 Color::Hwba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
885 Color::Laba(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
886 Color::Lcha(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
887 Color::Oklaba(x) => x.distance_squared(&(*other).into()),
888 Color::Oklcha(x) => x.distance_squared(&(*other).into()),
889 Color::Xyza(x) => ChosenColorSpace::from(*x).distance_squared(&(*other).into()),
890 }
891 }
892}
893
894impl TryStableInterpolate for Color {
895 type Error = MismatchedUnitsError;
896
897 fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
898 match (self, other) {
899 (Color::Srgba(a), Color::Srgba(b)) => Ok(Color::Srgba(a.mix(b, t))),
900 (Color::LinearRgba(a), Color::LinearRgba(b)) => Ok(Color::LinearRgba(a.mix(b, t))),
901 (Color::Hsla(a), Color::Hsla(b)) => Ok(Color::Hsla(a.mix(b, t))),
902 (Color::Hsva(a), Color::Hsva(b)) => Ok(Color::Hsva(a.mix(b, t))),
903 (Color::Hwba(a), Color::Hwba(b)) => Ok(Color::Hwba(a.mix(b, t))),
904 (Color::Laba(a), Color::Laba(b)) => Ok(Color::Laba(a.mix(b, t))),
905 (Color::Lcha(a), Color::Lcha(b)) => Ok(Color::Lcha(a.mix(b, t))),
906 (Color::Oklaba(a), Color::Oklaba(b)) => Ok(Color::Oklaba(a.mix(b, t))),
907 (Color::Oklcha(a), Color::Oklcha(b)) => Ok(Color::Oklcha(a.mix(b, t))),
908 (Color::Xyza(a), Color::Xyza(b)) => Ok(Color::Xyza(a.mix(b, t))),
909 _ => Err(MismatchedUnitsError),
910 }
911 }
912}