Skip to main content

bevy_color/
color.rs

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/// An enumerated type that can represent any of the color types in this crate.
12///
13/// This is useful when you need to store a color in a data structure that can't be generic over
14/// the color type.
15#[doc = include_str!("../docs/conversion.md")]
16/// <div>
17#[doc = include_str!("../docs/diagrams/model_graph.svg")]
18/// </div>
19///
20/// # Operations
21///
22/// [`Color`] supports all the standard color operations, such as [mixing](Mix),
23/// [luminance](Luminance) and [hue](Hue) adjustment,
24/// and [diffing](EuclideanDistance). These operations delegate to the concrete color space contained
25/// by [`Color`], but will convert to [`Oklch`](Oklcha) for operations which aren't supported in the
26/// current space. After performing the operation, if a conversion was required, the result will be
27/// converted back into the original color space.
28///
29/// ```rust
30/// # use bevy_color::{Hue, Color};
31/// let red_hsv = Color::hsv(0., 1., 1.);
32/// let red_srgb = Color::srgb(1., 0., 0.);
33///
34/// // HSV has a definition of hue, so it will be returned.
35/// red_hsv.hue();
36///
37/// // SRGB doesn't have a native definition for hue.
38/// // Converts to Oklch and returns that result.
39/// red_srgb.hue();
40/// ```
41///
42/// [`Oklch`](Oklcha) has been chosen as the intermediary space in cases where conversion is required
43/// due to its perceptual uniformity and broad support for Bevy's color operations.
44/// To avoid the cost of repeated conversion, and ensure consistent results where that is desired,
45/// first convert this [`Color`] into your desired color space.
46#[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    /// A color in the sRGB color space with alpha.
59    Srgba(Srgba),
60    /// A color in the linear sRGB color space with alpha.
61    LinearRgba(LinearRgba),
62    /// A color in the HSL color space with alpha.
63    Hsla(Hsla),
64    /// A color in the HSV color space with alpha.
65    Hsva(Hsva),
66    /// A color in the HWB color space with alpha.
67    Hwba(Hwba),
68    /// A color in the LAB color space with alpha.
69    Laba(Laba),
70    /// A color in the LCH color space with alpha.
71    Lcha(Lcha),
72    /// A color in the Oklab color space with alpha.
73    Oklaba(Oklaba),
74    /// A color in the Oklch color space with alpha.
75    Oklcha(Oklcha),
76    /// A color in the XYZ color space with alpha.
77    Xyza(Xyza),
78    /// A color in the Okhsl color space with alpha.
79    Okhsla(Okhsla),
80    /// A color in the Okhsv color space with alpha.
81    Okhsva(Okhsva),
82    /// A color in the Okhwb color space with alpha.
83    Okhwba(Okhwba),
84}
85
86impl StandardColor for Color {}
87
88impl Color {
89    /// Return the color as a linear RGBA color.
90    pub fn to_linear(&self) -> LinearRgba {
91        (*self).into()
92    }
93
94    /// Return the color as an SRGBA color.
95    pub fn to_srgba(&self) -> Srgba {
96        (*self).into()
97    }
98
99    /// Creates a new [`Color`] object storing a [`Srgba`] color.
100    ///
101    /// # Arguments
102    ///
103    /// * `red` - Red channel. [0.0, 1.0]
104    /// * `green` - Green channel. [0.0, 1.0]
105    /// * `blue` - Blue channel. [0.0, 1.0]
106    /// * `alpha` - Alpha channel. [0.0, 1.0]
107    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    /// Creates a new [`Color`] object storing a [`Srgba`] color with an alpha of 1.0.
117    ///
118    /// # Arguments
119    ///
120    /// * `red` - Red channel. [0.0, 1.0]
121    /// * `green` - Green channel. [0.0, 1.0]
122    /// * `blue` - Blue channel. [0.0, 1.0]
123    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    /// Reads an array of floats to creates a new [`Color`] object storing a [`Srgba`] color with an alpha of 1.0.
133    ///
134    /// # Arguments
135    /// * `array` - Red, Green and Blue channels. Each channel is in the range [0.0, 1.0]
136    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    /// Creates a new [`Color`] object storing a [`Srgba`] color from [`u8`] values.
146    ///
147    /// # Arguments
148    ///
149    /// * `red` - Red channel. [0, 255]
150    /// * `green` - Green channel. [0, 255]
151    /// * `blue` - Blue channel. [0, 255]
152    /// * `alpha` - Alpha channel. [0, 255]
153    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    /// Creates a new [`Color`] object storing a [`Srgba`] color from [`u8`] values with an alpha of 1.0.
163    ///
164    /// # Arguments
165    ///
166    /// * `red` - Red channel. [0, 255]
167    /// * `green` - Green channel. [0, 255]
168    /// * `blue` - Blue channel. [0, 255]
169    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    /// Creates a new [`Color`] object storing a [`Srgba`] color from a [`u32`] value with an alpha of 1.0.
179    ///
180    /// For example, a value of `0x000000` results in black, and a value of `0xff0000` results in red.
181    ///
182    /// # Examples
183    ///
184    /// ```
185    /// # use bevy_color::Color;
186    /// let black = Color::srgb_u32(0x000000);
187    /// let red = Color::srgb_u32(0xff0000);
188    /// ```
189    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    /// Creates a new [`Color`] object storing a [`Srgba`] color from a [`u32`] value with the alpha value extracted from the input.
198    ///
199    /// For example, a value of `0x000000ff` results in black with full opacity, and a value of `0xff000080` results in red with half opacity.
200    ///
201    /// # Examples
202    ///
203    /// ```
204    /// # use bevy_color::Color;
205    /// let black = Color::srgba_u32(0x000000ff);
206    /// let semi_transparent_red = Color::srgba_u32(0xff000080);
207    /// ```
208    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    /// Creates a new [`Color`] object storing a [`LinearRgba`] color.
218    ///
219    /// # Arguments
220    ///
221    /// * `red` - Red channel. [0.0, 1.0]
222    /// * `green` - Green channel. [0.0, 1.0]
223    /// * `blue` - Blue channel. [0.0, 1.0]
224    /// * `alpha` - Alpha channel. [0.0, 1.0]
225    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    /// Creates a new [`Color`] object storing a [`LinearRgba`] color with an alpha of 1.0.
235    ///
236    /// # Arguments
237    ///
238    /// * `red` - Red channel. [0.0, 1.0]
239    /// * `green` - Green channel. [0.0, 1.0]
240    /// * `blue` - Blue channel. [0.0, 1.0]
241    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    /// Creates a new [`Color`] object storing a [`Hsla`] color.
251    ///
252    /// # Arguments
253    ///
254    /// * `hue` - Hue channel. [0.0, 360.0]
255    /// * `saturation` - Saturation channel. [0.0, 1.0]
256    /// * `lightness` - Lightness channel. [0.0, 1.0]
257    /// * `alpha` - Alpha channel. [0.0, 1.0]
258    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    /// Creates a new [`Color`] object storing a [`Hsla`] color with an alpha of 1.0.
268    ///
269    /// # Arguments
270    ///
271    /// * `hue` - Hue channel. [0.0, 360.0]
272    /// * `saturation` - Saturation channel. [0.0, 1.0]
273    /// * `lightness` - Lightness channel. [0.0, 1.0]
274    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    /// Creates a new [`Color`] object storing a [`Hsva`] color.
284    ///
285    /// # Arguments
286    ///
287    /// * `hue` - Hue channel. [0.0, 360.0]
288    /// * `saturation` - Saturation channel. [0.0, 1.0]
289    /// * `value` - Value channel. [0.0, 1.0]
290    /// * `alpha` - Alpha channel. [0.0, 1.0]
291    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    /// Creates a new [`Color`] object storing a [`Hsva`] color with an alpha of 1.0.
301    ///
302    /// # Arguments
303    ///
304    /// * `hue` - Hue channel. [0.0, 360.0]
305    /// * `saturation` - Saturation channel. [0.0, 1.0]
306    /// * `value` - Value channel. [0.0, 1.0]
307    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    /// Creates a new [`Color`] object storing a [`Hwba`] color.
317    ///
318    /// # Arguments
319    ///
320    /// * `hue` - Hue channel. [0.0, 360.0]
321    /// * `whiteness` - Whiteness channel. [0.0, 1.0]
322    /// * `blackness` - Blackness channel. [0.0, 1.0]
323    /// * `alpha` - Alpha channel. [0.0, 1.0]
324    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    /// Creates a new [`Color`] object storing a [`Hwba`] color with an alpha of 1.0.
334    ///
335    /// # Arguments
336    ///
337    /// * `hue` - Hue channel. [0.0, 360.0]
338    /// * `whiteness` - Whiteness channel. [0.0, 1.0]
339    /// * `blackness` - Blackness channel. [0.0, 1.0]
340    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    /// Creates a new [`Color`] object storing a [`Laba`] color.
350    ///
351    /// # Arguments
352    ///
353    /// * `lightness` - Lightness channel. [0.0, 1.5]
354    /// * `a` - a axis. [-1.5, 1.5]
355    /// * `b` - b axis. [-1.5, 1.5]
356    /// * `alpha` - Alpha channel. [0.0, 1.0]
357    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    /// Creates a new [`Color`] object storing a [`Laba`] color with an alpha of 1.0.
367    ///
368    /// # Arguments
369    ///
370    /// * `lightness` - Lightness channel. [0.0, 1.5]
371    /// * `a` - a axis. [-1.5, 1.5]
372    /// * `b` - b axis. [-1.5, 1.5]
373    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    /// Creates a new [`Color`] object storing a [`Lcha`] color.
383    ///
384    /// # Arguments
385    ///
386    /// * `lightness` - Lightness channel. [0.0, 1.5]
387    /// * `chroma` - Chroma channel. [0.0, 1.5]
388    /// * `hue` - Hue channel. [0.0, 360.0]
389    /// * `alpha` - Alpha channel. [0.0, 1.0]
390    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    /// Creates a new [`Color`] object storing a [`Lcha`] color with an alpha of 1.0.
400    ///
401    /// # Arguments
402    ///
403    /// * `lightness` - Lightness channel. [0.0, 1.5]
404    /// * `chroma` - Chroma channel. [0.0, 1.5]
405    /// * `hue` - Hue channel. [0.0, 360.0]
406    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    /// Creates a new [`Color`] object storing a [`Oklaba`] color.
416    ///
417    /// # Arguments
418    ///
419    /// * `lightness` - Lightness channel. [0.0, 1.0]
420    /// * `a` - Green-red channel. [-1.0, 1.0]
421    /// * `b` - Blue-yellow channel. [-1.0, 1.0]
422    /// * `alpha` - Alpha channel. [0.0, 1.0]
423    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    /// Creates a new [`Color`] object storing a [`Oklaba`] color with an alpha of 1.0.
433    ///
434    /// # Arguments
435    ///
436    /// * `lightness` - Lightness channel. [0.0, 1.0]
437    /// * `a` - Green-red channel. [-1.0, 1.0]
438    /// * `b` - Blue-yellow channel. [-1.0, 1.0]
439    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    /// Creates a new [`Color`] object storing a [`Oklcha`] color.
449    ///
450    /// # Arguments
451    ///
452    /// * `lightness` - Lightness channel. [0.0, 1.0]
453    /// * `chroma` - Chroma channel. [0.0, 1.0]
454    /// * `hue` - Hue channel. [0.0, 360.0]
455    /// * `alpha` - Alpha channel. [0.0, 1.0]
456    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    /// Creates a new [`Color`] object storing a [`Oklcha`] color with an alpha of 1.0.
466    ///
467    /// # Arguments
468    ///
469    /// * `lightness` - Lightness channel. [0.0, 1.0]
470    /// * `chroma` - Chroma channel. [0.0, 1.0]
471    /// * `hue` - Hue channel. [0.0, 360.0]
472    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    /// Creates a new [`Color`] object storing a [`Xyza`] color.
482    ///
483    /// # Arguments
484    ///
485    /// * `x` - x-axis. [0.0, 1.0]
486    /// * `y` - y-axis. [0.0, 1.0]
487    /// * `z` - z-axis. [0.0, 1.0]
488    /// * `alpha` - Alpha channel. [0.0, 1.0]
489    pub const fn xyza(x: f32, y: f32, z: f32, alpha: f32) -> Self {
490        Self::Xyza(Xyza { x, y, z, alpha })
491    }
492
493    /// Creates a new [`Color`] object storing a [`Xyza`] color with an alpha of 1.0.
494    ///
495    /// # Arguments
496    ///
497    /// * `x` - x-axis. [0.0, 1.0]
498    /// * `y` - y-axis. [0.0, 1.0]
499    /// * `z` - z-axis. [0.0, 1.0]
500    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    /// Creates a new [`Color`] object storing a [`Okhsla`] color.
510    ///
511    /// # Arguments
512    ///
513    /// * `hue` - Hue channel. [0.0, 360.0]
514    /// * `saturation` - Saturation channel. [0.0, 1.0]
515    /// * `lightness` - Lightness channel. [0.0, 1.0]
516    /// * `alpha` - Alpha channel. [0.0, 1.0]
517    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    /// Creates a new [`Color`] object storing a [`Okhsla`] color with an alpha of 1.0.
527    ///
528    /// # Arguments
529    ///
530    /// * `hue` - Hue channel. [0.0, 360.0]
531    /// * `saturation` - Saturation channel. [0.0, 1.0]
532    /// * `lightness` - Lightness channel. [0.0, 1.0]
533    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    /// Creates a new [`Color`] object storing a [`Okhsva`] color.
543    ///
544    /// # Arguments
545    ///
546    /// * `hue` - Hue channel. [0.0, 360.0]
547    /// * `saturation` - Saturation channel. [0.0, 1.0]
548    /// * `value` - Value channel. [0.0, 1.0]
549    /// * `alpha` - Alpha channel. [0.0, 1.0]
550    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    /// Creates a new [`Color`] object storing a [`Okhsva`] color with an alpha of 1.0.
560    ///
561    /// # Arguments
562    ///
563    /// * `hue` - Hue channel. [0.0, 360.0]
564    /// * `saturation` - Saturation channel. [0.0, 1.0]
565    /// * `value` - Value channel. [0.0, 1.0]
566    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    /// Creates a new [`Color`] object storing a [`Okhwba`] color.
576    ///
577    /// # Arguments
578    ///
579    /// * `hue` - Hue channel. [0.0, 360.0]
580    /// * `whiteness` - Whiteness channel. [0.0, 1.0]
581    /// * `blackness` - Blackness channel. [0.0, 1.0]
582    /// * `alpha` - Alpha channel. [0.0, 1.0]
583    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    /// Creates a new [`Color`] object storing a [`Okhwba`] color with an alpha of 1.0.
593    ///
594    /// # Arguments
595    ///
596    /// * `hue` - Hue channel. [0.0, 360.0]
597    /// * `whiteness` - Whiteness channel. [0.0, 1.0]
598    /// * `blackness` - Blackness channel. [0.0, 1.0]
599    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    /// A fully white [`Color::LinearRgba`] color with an alpha of 1.0.
609    pub const WHITE: Self = Self::linear_rgb(1.0, 1.0, 1.0);
610
611    /// A fully black [`Color::LinearRgba`] color with an alpha of 1.0.
612    pub const BLACK: Self = Self::linear_rgb(0., 0., 0.);
613
614    /// A fully transparent [`Color::LinearRgba`] color with 0 red, green and blue.
615    pub const NONE: Self = Self::linear_rgba(0., 0., 0., 0.);
616}
617
618impl Default for Color {
619    /// A fully white [`Color::LinearRgba`] color with an alpha of 1.0.
620    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
945/// Color space chosen for operations on `Color`.
946type 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}