palette/alpha/
alpha.rs

1use core::{
2    fmt,
3    iter::FromIterator,
4    ops::{
5        Add, AddAssign, BitAnd, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Sub, SubAssign,
6    },
7};
8
9#[cfg(feature = "approx")]
10use approx::{AbsDiffEq, RelativeEq, UlpsEq};
11#[cfg(feature = "random")]
12use rand::{
13    distributions::{
14        uniform::{SampleBorrow, SampleUniform, Uniform, UniformSampler},
15        Distribution, Standard,
16    },
17    Rng,
18};
19
20use crate::{
21    blend::{PreAlpha, Premultiply},
22    bool_mask::HasBoolMask,
23    cast::ArrayCast,
24    clamp, clamp_assign,
25    convert::{FromColorUnclamped, IntoColorUnclamped},
26    num::{self, Arithmetics, One, PartialCmp, SaturatingAdd, SaturatingSub, Zero},
27    stimulus::Stimulus,
28    ArrayExt, Clamp, ClampAssign, GetHue, IsWithinBounds, Lighten, LightenAssign, Mix, MixAssign,
29    NextArray, Saturate, SaturateAssign, SetHue, ShiftHue, ShiftHueAssign, WithAlpha, WithHue,
30};
31
32/// An alpha component wrapper for colors, for adding transparency.
33///
34/// Instead of having separate types for "RGB with alpha", "HSV with alpha", and
35/// so on, Palette uses this wrapper type to attach the alpha component. The
36/// memory representation is the same as if `alpha` was the last member/property
37/// of `color`, which is just as space efficient. The perk of having a wrapper
38/// is that the alpha can easily be added to or separated form any color.
39///
40/// # Creating Transparent Values
41///
42/// The color types in Palette have transparent type aliases, such as
43/// [`Srgba`](crate::Srgba) for [`Srgb`][crate::Srgb] or [`Hsla`](crate::Hsla)
44/// for [`Hsl`](crate::Hsl). These aliases implement `new` and other useful
45/// methods. Here's the same example as for [`Rgb`](crate::rgb::Rgb), but with
46/// transparency:
47///
48/// ```
49/// use palette::Srgba;
50///
51/// let rgba_u8 = Srgba::new(171u8, 193, 35, 128);
52/// let rgab_f32 = Srgba::new(0.3f32, 0.8, 0.1, 0.5);
53///
54/// // `new` is also `const`:
55/// const RGBA_U8: Srgba<u8> = Srgba::new(171, 193, 35, 128);
56///
57/// // Conversion methods from the color type are usually available for transparent
58/// // values too. For example `into_format` for changing the number format:
59/// let rgb_u8_from_f32 = Srgba::new(0.3f32, 0.8, 0.1, 0.5).into_format::<u8, u8>();
60///
61/// // Hexadecimal is also supported for RGBA, with or without the #:
62/// let rgb_from_hex1: Srgba<u8> = "#f034e65a".parse().unwrap();
63/// let rgb_from_hex2: Srgba<u8> = "f034e65a".parse().unwrap();
64/// assert_eq!(rgb_from_hex1, rgb_from_hex2);
65///
66/// // This includes the shorthand format:
67/// let rgb_from_short_hex: Srgba<u8> = "f3ea".parse().unwrap();
68/// let rgb_from_long_hex: Srgba<u8> = "ff33eeaa".parse().unwrap();
69/// assert_eq!(rgb_from_short_hex, rgb_from_long_hex);
70///
71/// // It's also possible to convert from (and to) arrays, tuples and `u32` values:
72/// let rgb_from_array = Srgba::from([171u8, 193, 35, 128]);
73/// let rgb_from_tuple = Srgba::from((171u8, 193, 35, 128));
74/// let rgb_from_u32 = Srgba::from(0x607F005A);
75/// ```
76///
77/// Opaque values can be made transparent using the [`WithAlpha`] trait, in
78/// addition to simply wrapping them in `Alpha`. [`WithAlpha`] is also useful in
79/// generic code, since it's implemented for both opaque and transparent types.
80///
81/// ```
82/// use palette::{WithAlpha, Srgb};
83///
84/// let rgb = Srgb::new(171u8, 193, 35);
85/// let rgba = rgb.with_alpha(128u8);
86/// assert_eq!(rgba.alpha, 128);
87/// ```
88///
89/// You may have noticed the `u8` in `rgb.with_alpha(128u8)`. That's because
90/// `Alpha` allows the transparency component to have a different type than the
91/// color components. It would be just as valid to write
92/// `rgb.with_alpha(0.5f32)`, for example.
93///
94/// # Accessing Color Components
95///
96/// To help with the nesting, `Alpha` implements [`Deref`] and [`DerefMut`].
97/// This use of the traits is a bit unconventional, since `Alpha` isn't a smart
98/// pointer. It turned out to be a quite successful experiment that stuck
99/// around.
100///
101/// ```
102/// use palette::Srgba;
103///
104/// let rgba = Srgba::new(171u8, 193, 35, 128);
105/// let red = rgba.red; // Accesses `rgba.color.red`.
106/// let alpha = rgba.alpha; // Accesses `rgba.alpha`.
107/// let rgb = rgba.color; // Accesses `rgba.color`;
108/// ```
109///
110/// The main drawback is in generic code:
111///
112/// ```compile_fail
113/// use palette::Srgba;
114///
115/// fn get_red<T>(rgba: Srgba<T>) -> T {
116///     rgba.red // Error: cannot move out of dereference of `Alpha<Rgb<_, T>, T>`
117/// }
118/// ```
119///
120/// `red` has to be accessed through `color`:
121///
122/// ```
123/// use palette::Srgba;
124///
125/// fn get_red<T>(rgba: Srgba<T>) -> T {
126///     rgba.color.red
127/// }
128/// ```
129#[derive(Clone, Copy, Debug)]
130#[repr(C)]
131pub struct Alpha<C, T> {
132    /// The color.
133    pub color: C,
134
135    /// The transparency component. 0.0 (or 0u8) is fully transparent and 1.0
136    /// (or 255u8) is fully opaque.
137    pub alpha: T,
138}
139
140impl<C, A> Alpha<C, A> {
141    /// Return an iterator over the colors in the wrapped collections.
142    pub fn iter<'a>(&'a self) -> <&'a Self as IntoIterator>::IntoIter
143    where
144        &'a Self: IntoIterator,
145    {
146        self.into_iter()
147    }
148
149    /// Return an iterator that allows modifying the colors in the wrapped collections.
150    pub fn iter_mut<'a>(&'a mut self) -> <&'a mut Self as IntoIterator>::IntoIter
151    where
152        &'a mut Self: IntoIterator,
153    {
154        self.into_iter()
155    }
156}
157
158impl<C: Premultiply> Alpha<C, C::Scalar> {
159    /// Alpha mask the color by its transparency.
160    pub fn premultiply(self) -> PreAlpha<C> {
161        PreAlpha::new(self.color, self.alpha)
162    }
163}
164
165impl<C, T: Stimulus> Alpha<C, T> {
166    /// Return the `alpha` value minimum.
167    pub fn min_alpha() -> T {
168        T::zero()
169    }
170
171    /// Return the `alpha` value maximum.
172    pub fn max_alpha() -> T {
173        T::max_intensity()
174    }
175}
176
177impl<C, T> PartialEq for Alpha<C, T>
178where
179    T: PartialEq,
180    C: PartialEq,
181{
182    fn eq(&self, other: &Self) -> bool {
183        self.color == other.color && self.alpha == other.alpha
184    }
185}
186
187impl<C, T> Eq for Alpha<C, T>
188where
189    T: Eq,
190    C: Eq,
191{
192}
193
194impl<C1: WithAlpha<T>, C2, T> FromColorUnclamped<C1> for Alpha<C2, T>
195where
196    C1::Color: IntoColorUnclamped<C2>,
197{
198    fn from_color_unclamped(other: C1) -> Self {
199        let (color, alpha) = other.split();
200
201        Alpha {
202            color: color.into_color_unclamped(),
203            alpha,
204        }
205    }
206}
207
208impl<C, A> WithAlpha<A> for Alpha<C, A> {
209    type Color = C;
210    type WithAlpha = Self;
211
212    fn with_alpha(mut self, alpha: A) -> Self::WithAlpha {
213        self.alpha = alpha;
214        self
215    }
216
217    fn without_alpha(self) -> Self::Color {
218        self.color
219    }
220
221    fn split(self) -> (Self::Color, A) {
222        (self.color, self.alpha)
223    }
224}
225
226impl<C, T> Deref for Alpha<C, T> {
227    type Target = C;
228
229    fn deref(&self) -> &C {
230        &self.color
231    }
232}
233
234impl<C, T> DerefMut for Alpha<C, T> {
235    fn deref_mut(&mut self) -> &mut C {
236        &mut self.color
237    }
238}
239
240impl<C> Mix for Alpha<C, C::Scalar>
241where
242    C: Mix,
243    C::Scalar: Zero + One + num::Clamp + Arithmetics + Clone,
244{
245    type Scalar = C::Scalar;
246
247    #[inline]
248    fn mix(mut self, other: Self, factor: C::Scalar) -> Self {
249        let factor = clamp(factor, C::Scalar::zero(), C::Scalar::one());
250
251        self.color = self.color.mix(other.color, factor.clone());
252        self.alpha = self.alpha.clone() + factor * (other.alpha - self.alpha);
253
254        self
255    }
256}
257
258impl<C> MixAssign for Alpha<C, C::Scalar>
259where
260    C: MixAssign,
261    C::Scalar: Zero + One + num::Clamp + Arithmetics + AddAssign + Clone,
262{
263    type Scalar = C::Scalar;
264
265    #[inline]
266    fn mix_assign(&mut self, other: Self, factor: C::Scalar) {
267        let factor = clamp(factor, C::Scalar::zero(), C::Scalar::one());
268
269        self.color.mix_assign(other.color, factor.clone());
270        self.alpha += factor * (other.alpha - self.alpha.clone());
271    }
272}
273
274impl<C: Lighten> Lighten for Alpha<C, C::Scalar> {
275    type Scalar = C::Scalar;
276
277    #[inline]
278    fn lighten(self, factor: C::Scalar) -> Self {
279        Alpha {
280            color: self.color.lighten(factor),
281            alpha: self.alpha,
282        }
283    }
284
285    #[inline]
286    fn lighten_fixed(self, amount: C::Scalar) -> Self {
287        Alpha {
288            color: self.color.lighten_fixed(amount),
289            alpha: self.alpha,
290        }
291    }
292}
293
294impl<C: LightenAssign> LightenAssign for Alpha<C, C::Scalar> {
295    type Scalar = C::Scalar;
296
297    #[inline]
298    fn lighten_assign(&mut self, factor: C::Scalar) {
299        self.color.lighten_assign(factor);
300    }
301
302    #[inline]
303    fn lighten_fixed_assign(&mut self, amount: C::Scalar) {
304        self.color.lighten_fixed_assign(amount);
305    }
306}
307
308impl<C: GetHue, T> GetHue for Alpha<C, T> {
309    type Hue = C::Hue;
310
311    #[inline]
312    fn get_hue(&self) -> C::Hue {
313        self.color.get_hue()
314    }
315}
316
317impl<C, T, H> WithHue<H> for Alpha<C, T>
318where
319    C: WithHue<H>,
320{
321    #[inline]
322    fn with_hue(mut self, hue: H) -> Self {
323        self.color = self.color.with_hue(hue);
324        self
325    }
326}
327
328impl<C, T, H> SetHue<H> for Alpha<C, T>
329where
330    C: SetHue<H>,
331{
332    #[inline]
333    fn set_hue(&mut self, hue: H) {
334        self.color.set_hue(hue);
335    }
336}
337
338impl<C, T> ShiftHue for Alpha<C, T>
339where
340    C: ShiftHue,
341{
342    type Scalar = C::Scalar;
343
344    #[inline]
345    fn shift_hue(mut self, amount: Self::Scalar) -> Self {
346        self.color = self.color.shift_hue(amount);
347        self
348    }
349}
350
351impl<C, T> ShiftHueAssign for Alpha<C, T>
352where
353    C: ShiftHueAssign,
354{
355    type Scalar = C::Scalar;
356
357    #[inline]
358    fn shift_hue_assign(&mut self, amount: Self::Scalar) {
359        self.color.shift_hue_assign(amount);
360    }
361}
362
363impl<C: Saturate> Saturate for Alpha<C, C::Scalar> {
364    type Scalar = C::Scalar;
365
366    #[inline]
367    fn saturate(self, factor: C::Scalar) -> Self {
368        Alpha {
369            color: self.color.saturate(factor),
370            alpha: self.alpha,
371        }
372    }
373
374    #[inline]
375    fn saturate_fixed(self, amount: C::Scalar) -> Self {
376        Alpha {
377            color: self.color.saturate_fixed(amount),
378            alpha: self.alpha,
379        }
380    }
381}
382
383impl<C: SaturateAssign> SaturateAssign for Alpha<C, C::Scalar> {
384    type Scalar = C::Scalar;
385
386    #[inline]
387    fn saturate_assign(&mut self, factor: C::Scalar) {
388        self.color.saturate_assign(factor);
389    }
390
391    #[inline]
392    fn saturate_fixed_assign(&mut self, amount: C::Scalar) {
393        self.color.saturate_fixed_assign(amount);
394    }
395}
396
397impl<C, T> IsWithinBounds for Alpha<C, T>
398where
399    C: IsWithinBounds,
400    T: Stimulus + PartialCmp + IsWithinBounds<Mask = C::Mask>,
401    C::Mask: BitAnd<Output = C::Mask>,
402{
403    #[inline]
404    fn is_within_bounds(&self) -> C::Mask {
405        self.color.is_within_bounds()
406            & self.alpha.gt_eq(&Self::min_alpha())
407            & self.alpha.lt_eq(&Self::max_alpha())
408    }
409}
410
411impl<C, T> Clamp for Alpha<C, T>
412where
413    C: Clamp,
414    T: Stimulus + num::Clamp,
415{
416    #[inline]
417    fn clamp(self) -> Self {
418        Alpha {
419            color: self.color.clamp(),
420            alpha: clamp(self.alpha, Self::min_alpha(), Self::max_alpha()),
421        }
422    }
423}
424
425impl<C, T> ClampAssign for Alpha<C, T>
426where
427    C: ClampAssign,
428    T: Stimulus + num::ClampAssign,
429{
430    #[inline]
431    fn clamp_assign(&mut self) {
432        self.color.clamp_assign();
433        clamp_assign(&mut self.alpha, Self::min_alpha(), Self::max_alpha());
434    }
435}
436
437unsafe impl<C> ArrayCast for Alpha<C, <<C as ArrayCast>::Array as ArrayExt>::Item>
438where
439    C: ArrayCast,
440    C::Array: NextArray,
441{
442    type Array = <C::Array as NextArray>::Next;
443}
444
445impl<C, T> HasBoolMask for Alpha<C, T>
446where
447    C: HasBoolMask,
448    T: HasBoolMask<Mask = C::Mask>,
449{
450    type Mask = C::Mask;
451}
452
453impl<C: Default, T: Stimulus> Default for Alpha<C, T> {
454    fn default() -> Alpha<C, T> {
455        Alpha {
456            color: C::default(),
457            alpha: Self::max_alpha(),
458        }
459    }
460}
461
462#[cfg(feature = "approx")]
463impl<C, T> AbsDiffEq for Alpha<C, T>
464where
465    C: AbsDiffEq<Epsilon = T::Epsilon>,
466    T: AbsDiffEq,
467    T::Epsilon: Clone,
468{
469    type Epsilon = T::Epsilon;
470
471    fn default_epsilon() -> Self::Epsilon {
472        T::default_epsilon()
473    }
474
475    fn abs_diff_eq(&self, other: &Self, epsilon: T::Epsilon) -> bool {
476        self.color.abs_diff_eq(&other.color, epsilon.clone())
477            && self.alpha.abs_diff_eq(&other.alpha, epsilon)
478    }
479}
480
481#[cfg(feature = "approx")]
482impl<C, T> RelativeEq for Alpha<C, T>
483where
484    C: RelativeEq<Epsilon = T::Epsilon>,
485    T: RelativeEq,
486    T::Epsilon: Clone,
487{
488    fn default_max_relative() -> Self::Epsilon {
489        T::default_max_relative()
490    }
491
492    fn relative_eq(
493        &self,
494        other: &Alpha<C, T>,
495        epsilon: Self::Epsilon,
496        max_relative: Self::Epsilon,
497    ) -> bool {
498        self.color
499            .relative_eq(&other.color, epsilon.clone(), max_relative.clone())
500            && self.alpha.relative_eq(&other.alpha, epsilon, max_relative)
501    }
502}
503
504#[cfg(feature = "approx")]
505impl<C, T> UlpsEq for Alpha<C, T>
506where
507    C: UlpsEq<Epsilon = T::Epsilon>,
508    T: UlpsEq,
509    T::Epsilon: Clone,
510{
511    fn default_max_ulps() -> u32 {
512        T::default_max_ulps()
513    }
514
515    fn ulps_eq(&self, other: &Alpha<C, T>, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
516        self.color.ulps_eq(&other.color, epsilon.clone(), max_ulps)
517            && self.alpha.ulps_eq(&other.alpha, epsilon, max_ulps)
518    }
519}
520
521impl<C, T> Add for Alpha<C, T>
522where
523    C: Add,
524    T: Add,
525{
526    type Output = Alpha<C::Output, <T as Add>::Output>;
527
528    fn add(self, other: Alpha<C, T>) -> Self::Output {
529        Alpha {
530            color: self.color + other.color,
531            alpha: self.alpha + other.alpha,
532        }
533    }
534}
535
536impl<T, C> Add<T> for Alpha<C, T>
537where
538    T: Add + Clone,
539    C: Add<T>,
540{
541    type Output = Alpha<C::Output, <T as Add>::Output>;
542
543    fn add(self, c: T) -> Self::Output {
544        Alpha {
545            color: self.color + c.clone(),
546            alpha: self.alpha + c,
547        }
548    }
549}
550
551impl<C, T> AddAssign for Alpha<C, T>
552where
553    C: AddAssign,
554    T: AddAssign,
555{
556    fn add_assign(&mut self, other: Alpha<C, T>) {
557        self.color += other.color;
558        self.alpha += other.alpha;
559    }
560}
561
562impl<T, C> AddAssign<T> for Alpha<C, T>
563where
564    T: AddAssign + Clone,
565    C: AddAssign<T>,
566{
567    fn add_assign(&mut self, c: T) {
568        self.color += c.clone();
569        self.alpha += c;
570    }
571}
572
573impl<C, T> SaturatingAdd for Alpha<C, T>
574where
575    C: SaturatingAdd,
576    T: SaturatingAdd,
577{
578    type Output = Alpha<C::Output, <T as SaturatingAdd>::Output>;
579
580    fn saturating_add(self, other: Alpha<C, T>) -> Self::Output {
581        Alpha {
582            color: self.color.saturating_add(other.color),
583            alpha: self.alpha.saturating_add(other.alpha),
584        }
585    }
586}
587
588impl<T, C> SaturatingAdd<T> for Alpha<C, T>
589where
590    T: SaturatingAdd + Clone,
591    C: SaturatingAdd<T>,
592{
593    type Output = Alpha<C::Output, <T as SaturatingAdd>::Output>;
594
595    fn saturating_add(self, c: T) -> Self::Output {
596        Alpha {
597            color: self.color.saturating_add(c.clone()),
598            alpha: self.alpha.saturating_add(c),
599        }
600    }
601}
602
603impl<C, T> Sub for Alpha<C, T>
604where
605    C: Sub,
606    T: Sub,
607{
608    type Output = Alpha<C::Output, <T as Sub>::Output>;
609
610    fn sub(self, other: Alpha<C, T>) -> Self::Output {
611        Alpha {
612            color: self.color - other.color,
613            alpha: self.alpha - other.alpha,
614        }
615    }
616}
617
618impl<T, C> Sub<T> for Alpha<C, T>
619where
620    T: Sub + Clone,
621    C: Sub<T>,
622{
623    type Output = Alpha<C::Output, <T as Sub>::Output>;
624
625    fn sub(self, c: T) -> Self::Output {
626        Alpha {
627            color: self.color - c.clone(),
628            alpha: self.alpha - c,
629        }
630    }
631}
632
633impl<C, T> SubAssign for Alpha<C, T>
634where
635    C: SubAssign,
636    T: SubAssign,
637{
638    fn sub_assign(&mut self, other: Alpha<C, T>) {
639        self.color -= other.color;
640        self.alpha -= other.alpha;
641    }
642}
643
644impl<T, C> SubAssign<T> for Alpha<C, T>
645where
646    T: SubAssign + Clone,
647    C: SubAssign<T>,
648{
649    fn sub_assign(&mut self, c: T) {
650        self.color -= c.clone();
651        self.alpha -= c;
652    }
653}
654
655impl<C, T> SaturatingSub for Alpha<C, T>
656where
657    C: SaturatingSub,
658    T: SaturatingSub,
659{
660    type Output = Alpha<C::Output, <T as SaturatingSub>::Output>;
661
662    fn saturating_sub(self, other: Alpha<C, T>) -> Self::Output {
663        Alpha {
664            color: self.color.saturating_sub(other.color),
665            alpha: self.alpha.saturating_sub(other.alpha),
666        }
667    }
668}
669
670impl<T, C> SaturatingSub<T> for Alpha<C, T>
671where
672    T: SaturatingSub + Clone,
673    C: SaturatingSub<T>,
674{
675    type Output = Alpha<C::Output, <T as SaturatingSub>::Output>;
676
677    fn saturating_sub(self, c: T) -> Self::Output {
678        Alpha {
679            color: self.color.saturating_sub(c.clone()),
680            alpha: self.alpha.saturating_sub(c),
681        }
682    }
683}
684
685impl<C, T> Mul for Alpha<C, T>
686where
687    C: Mul,
688    T: Mul,
689{
690    type Output = Alpha<C::Output, <T as Mul>::Output>;
691
692    fn mul(self, other: Alpha<C, T>) -> Self::Output {
693        Alpha {
694            color: self.color * other.color,
695            alpha: self.alpha * other.alpha,
696        }
697    }
698}
699
700impl<T, C> Mul<T> for Alpha<C, T>
701where
702    T: Mul + Clone,
703    C: Mul<T>,
704{
705    type Output = Alpha<C::Output, <T as Mul>::Output>;
706
707    fn mul(self, c: T) -> Self::Output {
708        Alpha {
709            color: self.color * c.clone(),
710            alpha: self.alpha * c,
711        }
712    }
713}
714
715impl<C, T> MulAssign for Alpha<C, T>
716where
717    C: MulAssign,
718    T: MulAssign,
719{
720    fn mul_assign(&mut self, other: Alpha<C, T>) {
721        self.color *= other.color;
722        self.alpha *= other.alpha;
723    }
724}
725
726impl<T, C> MulAssign<T> for Alpha<C, T>
727where
728    T: MulAssign + Clone,
729    C: MulAssign<T>,
730{
731    fn mul_assign(&mut self, c: T) {
732        self.color *= c.clone();
733        self.alpha *= c;
734    }
735}
736
737impl<C, T> Div for Alpha<C, T>
738where
739    C: Div,
740    T: Div,
741{
742    type Output = Alpha<C::Output, <T as Div>::Output>;
743
744    fn div(self, other: Alpha<C, T>) -> Self::Output {
745        Alpha {
746            color: self.color / other.color,
747            alpha: self.alpha / other.alpha,
748        }
749    }
750}
751
752impl<T, C> Div<T> for Alpha<C, T>
753where
754    T: Div + Clone,
755    C: Div<T>,
756{
757    type Output = Alpha<C::Output, <T as Div>::Output>;
758
759    fn div(self, c: T) -> Self::Output {
760        Alpha {
761            color: self.color / c.clone(),
762            alpha: self.alpha / c,
763        }
764    }
765}
766
767impl<C, T> DivAssign for Alpha<C, T>
768where
769    C: DivAssign,
770    T: DivAssign,
771{
772    fn div_assign(&mut self, other: Alpha<C, T>) {
773        self.color /= other.color;
774        self.alpha /= other.alpha;
775    }
776}
777
778impl<T, C> DivAssign<T> for Alpha<C, T>
779where
780    T: DivAssign + Clone,
781    C: DivAssign<T>,
782{
783    fn div_assign(&mut self, c: T) {
784        self.color /= c.clone();
785        self.alpha /= c;
786    }
787}
788
789impl_array_casts!([C, T, const N: usize] Alpha<C, T>, [T; N], where Alpha<C, T>: ArrayCast<Array = [T; N]>);
790
791impl<C, T: Stimulus> From<C> for Alpha<C, T> {
792    fn from(color: C) -> Alpha<C, T> {
793        Alpha {
794            color,
795            alpha: Self::max_alpha(),
796        }
797    }
798}
799
800impl<C, T> fmt::LowerHex for Alpha<C, T>
801where
802    T: fmt::LowerHex,
803    C: fmt::LowerHex,
804{
805    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806        let size = f.width().unwrap_or(::core::mem::size_of::<T>() * 2);
807        write!(
808            f,
809            "{:0width$x}{:0width$x}",
810            self.color,
811            self.alpha,
812            width = size
813        )
814    }
815}
816
817impl<C, T> fmt::UpperHex for Alpha<C, T>
818where
819    T: fmt::UpperHex,
820    C: fmt::UpperHex,
821{
822    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823        let size = f.width().unwrap_or(::core::mem::size_of::<T>() * 2);
824        write!(
825            f,
826            "{:0width$X}{:0width$X}",
827            self.color,
828            self.alpha,
829            width = size
830        )
831    }
832}
833
834impl<Tc, Ta, C, A> Extend<Alpha<Tc, Ta>> for Alpha<C, A>
835where
836    C: Extend<Tc>,
837    A: Extend<Ta>,
838{
839    fn extend<T: IntoIterator<Item = Alpha<Tc, Ta>>>(&mut self, iter: T) {
840        for color in iter {
841            self.color.extend(core::iter::once(color.color));
842            self.alpha.extend(core::iter::once(color.alpha));
843        }
844    }
845}
846
847impl<Tc, Ta, C, A> FromIterator<Alpha<Tc, Ta>> for Alpha<C, A>
848where
849    C: Extend<Tc> + FromIterator<Tc>,
850    A: Extend<Ta> + Default,
851{
852    fn from_iter<T: IntoIterator<Item = Alpha<Tc, Ta>>>(iter: T) -> Self {
853        let mut result = Self {
854            color: C::from_iter(None), // Default is currently a used for black, meaning it's not always what we want here.
855            alpha: A::default(),
856        };
857
858        for color in iter {
859            result.color.extend(core::iter::once(color.color));
860            result.alpha.extend(core::iter::once(color.alpha));
861        }
862
863        result
864    }
865}
866
867/// An iterator for transparent colors.
868pub struct Iter<C, A> {
869    pub(crate) color: C,
870    pub(crate) alpha: A,
871}
872
873impl<C, A> Iterator for Iter<C, A>
874where
875    C: Iterator,
876    A: Iterator,
877{
878    type Item = Alpha<C::Item, A::Item>;
879
880    fn next(&mut self) -> Option<Self::Item> {
881        let color = self.color.next();
882        let alpha = self.alpha.next();
883
884        if let (Some(color), Some(alpha)) = (color, alpha) {
885            Some(Alpha { color, alpha })
886        } else {
887            None
888        }
889    }
890
891    fn size_hint(&self) -> (usize, Option<usize>) {
892        let hint = self.color.size_hint();
893        debug_assert_eq!(
894            self.alpha.size_hint(),
895            hint,
896            "the color and alpha iterators have different size hints"
897        );
898
899        hint
900    }
901
902    fn count(self) -> usize {
903        let count = self.color.count();
904        debug_assert_eq!(
905            self.alpha.count(),
906            count,
907            "the color and alpha iterators have different counts"
908        );
909
910        count
911    }
912}
913
914impl<C, A> DoubleEndedIterator for Iter<C, A>
915where
916    C: DoubleEndedIterator,
917    A: DoubleEndedIterator,
918{
919    fn next_back(&mut self) -> Option<Self::Item> {
920        let color = self.color.next_back();
921        let alpha = self.alpha.next_back();
922
923        if let (Some(color), Some(alpha)) = (color, alpha) {
924            Some(Alpha { color, alpha })
925        } else {
926            None
927        }
928    }
929}
930
931impl<C, A> ExactSizeIterator for Iter<C, A>
932where
933    C: ExactSizeIterator,
934    A: ExactSizeIterator,
935{
936    fn len(&self) -> usize {
937        let len = self.color.len();
938        debug_assert_eq!(
939            self.alpha.len(),
940            len,
941            "the color and alpha iterators have different lengths"
942        );
943
944        len
945    }
946}
947
948#[cfg(feature = "serializing")]
949impl<C, T> serde::Serialize for Alpha<C, T>
950where
951    C: serde::Serialize,
952    T: serde::Serialize,
953{
954    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
955    where
956        S: serde::Serializer,
957    {
958        self.color.serialize(crate::serde::AlphaSerializer {
959            inner: serializer,
960            alpha: &self.alpha,
961        })
962    }
963}
964
965#[cfg(feature = "serializing")]
966impl<'de, C, T> serde::Deserialize<'de> for Alpha<C, T>
967where
968    C: serde::Deserialize<'de>,
969    T: serde::Deserialize<'de>,
970{
971    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
972    where
973        D: serde::Deserializer<'de>,
974    {
975        let mut alpha: Option<T> = None;
976
977        let color = C::deserialize(crate::serde::AlphaDeserializer {
978            inner: deserializer,
979            alpha: &mut alpha,
980        })?;
981
982        if let Some(alpha) = alpha {
983            Ok(Self { color, alpha })
984        } else {
985            Err(serde::de::Error::missing_field("alpha"))
986        }
987    }
988}
989
990#[cfg(feature = "random")]
991impl<C, T> Distribution<Alpha<C, T>> for Standard
992where
993    Standard: Distribution<C> + Distribution<T>,
994{
995    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Alpha<C, T> {
996        Alpha {
997            color: rng.gen(),
998            alpha: rng.gen(),
999        }
1000    }
1001}
1002
1003/// Sample transparent colors uniformly.
1004#[cfg(feature = "random")]
1005pub struct UniformAlpha<C, T>
1006where
1007    T: SampleUniform,
1008    C: SampleUniform,
1009{
1010    color: Uniform<C>,
1011    alpha: Uniform<T>,
1012}
1013
1014#[cfg(feature = "random")]
1015impl<C, T> SampleUniform for Alpha<C, T>
1016where
1017    T: Clone + SampleUniform,
1018    C: Clone + SampleUniform,
1019{
1020    type Sampler = UniformAlpha<C, T>;
1021}
1022
1023#[cfg(feature = "random")]
1024impl<C, T> UniformSampler for UniformAlpha<C, T>
1025where
1026    T: Clone + SampleUniform,
1027    C: Clone + SampleUniform,
1028{
1029    type X = Alpha<C, T>;
1030
1031    fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
1032    where
1033        B1: SampleBorrow<Self::X> + Sized,
1034        B2: SampleBorrow<Self::X> + Sized,
1035    {
1036        let low = low_b.borrow().clone();
1037        let high = high_b.borrow().clone();
1038
1039        UniformAlpha {
1040            color: Uniform::new::<C, _>(low.color, high.color),
1041            alpha: Uniform::new::<_, T>(low.alpha, high.alpha),
1042        }
1043    }
1044
1045    fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
1046    where
1047        B1: SampleBorrow<Self::X> + Sized,
1048        B2: SampleBorrow<Self::X> + Sized,
1049    {
1050        let low = low_b.borrow().clone();
1051        let high = high_b.borrow().clone();
1052
1053        UniformAlpha {
1054            color: Uniform::new_inclusive::<C, _>(low.color, high.color),
1055            alpha: Uniform::new_inclusive::<_, T>(low.alpha, high.alpha),
1056        }
1057    }
1058
1059    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Alpha<C, T> {
1060        Alpha {
1061            color: self.color.sample(rng),
1062            alpha: self.alpha.sample(rng),
1063        }
1064    }
1065}
1066
1067#[cfg(feature = "bytemuck")]
1068unsafe impl<C, T> bytemuck::Zeroable for Alpha<C, T>
1069where
1070    C: bytemuck::Zeroable,
1071    T: bytemuck::Zeroable,
1072{
1073}
1074
1075// Safety:
1076//
1077// It is a requirement of `ArrayCast` that the in-memory representation of `C`
1078// is made of `T`s. Because `T` is `Pod`, `Alpha<C, T>` is `Pod` as well because
1079// no internal padding can be introduced during monomorphization.
1080#[cfg(feature = "bytemuck")]
1081unsafe impl<C, T> bytemuck::Pod for Alpha<C, T>
1082where
1083    T: bytemuck::Pod,
1084    C: bytemuck::Pod + ArrayCast,
1085{
1086}
1087
1088#[cfg(test)]
1089mod test {
1090    use crate::encoding::Srgb;
1091    use crate::rgb::Rgba;
1092
1093    #[test]
1094    fn lower_hex() {
1095        assert_eq!(
1096            format!("{:x}", Rgba::<Srgb, u8>::new(171, 193, 35, 161)),
1097            "abc123a1"
1098        );
1099    }
1100
1101    #[test]
1102    fn lower_hex_small_numbers() {
1103        assert_eq!(
1104            format!("{:x}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1105            "01020304"
1106        );
1107        assert_eq!(
1108            format!("{:x}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1109            "0001000200030004"
1110        );
1111        assert_eq!(
1112            format!("{:x}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1113            "00000001000000020000000300000004"
1114        );
1115        assert_eq!(
1116            format!("{:x}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1117            "0000000000000001000000000000000200000000000000030000000000000004"
1118        );
1119    }
1120
1121    #[test]
1122    fn lower_hex_custom_width() {
1123        assert_eq!(
1124            format!("{:03x}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1125            "001002003004"
1126        );
1127        assert_eq!(
1128            format!("{:03x}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1129            "001002003004"
1130        );
1131        assert_eq!(
1132            format!("{:03x}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1133            "001002003004"
1134        );
1135        assert_eq!(
1136            format!("{:03x}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1137            "001002003004"
1138        );
1139    }
1140
1141    #[test]
1142    fn upper_hex() {
1143        assert_eq!(
1144            format!("{:X}", Rgba::<Srgb, u8>::new(171, 193, 35, 161)),
1145            "ABC123A1"
1146        );
1147    }
1148
1149    #[test]
1150    fn upper_hex_small_numbers() {
1151        assert_eq!(
1152            format!("{:X}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1153            "01020304"
1154        );
1155        assert_eq!(
1156            format!("{:X}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1157            "0001000200030004"
1158        );
1159        assert_eq!(
1160            format!("{:X}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1161            "00000001000000020000000300000004"
1162        );
1163        assert_eq!(
1164            format!("{:X}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1165            "0000000000000001000000000000000200000000000000030000000000000004"
1166        );
1167    }
1168
1169    #[test]
1170    fn upper_hex_custom_width() {
1171        assert_eq!(
1172            format!("{:03X}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1173            "001002003004"
1174        );
1175        assert_eq!(
1176            format!("{:03X}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1177            "001002003004"
1178        );
1179        assert_eq!(
1180            format!("{:03X}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1181            "001002003004"
1182        );
1183        assert_eq!(
1184            format!("{:03X}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1185            "001002003004"
1186        );
1187    }
1188
1189    #[test]
1190    fn check_min_max_components() {
1191        assert_eq!(Rgba::<Srgb>::min_alpha(), 0.0);
1192        assert_eq!(Rgba::<Srgb>::max_alpha(), 1.0);
1193    }
1194
1195    #[cfg(feature = "serializing")]
1196    #[test]
1197    fn serialize() {
1198        let color = Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5);
1199
1200        assert_eq!(
1201            serde_json::to_string(&color).unwrap(),
1202            r#"{"red":0.3,"green":0.8,"blue":0.1,"alpha":0.5}"#
1203        );
1204
1205        assert_eq!(
1206            ron::to_string(&color).unwrap(),
1207            r#"(red:0.3,green:0.8,blue:0.1,alpha:0.5)"#
1208        );
1209    }
1210
1211    #[cfg(feature = "serializing")]
1212    #[test]
1213    fn deserialize() {
1214        let color = Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5);
1215
1216        assert_eq!(
1217            serde_json::from_str::<Rgba<Srgb>>(r#"{"alpha":0.5,"red":0.3,"green":0.8,"blue":0.1}"#)
1218                .unwrap(),
1219            color
1220        );
1221
1222        assert_eq!(
1223            ron::from_str::<Rgba<Srgb>>(r#"(alpha:0.5,red:0.3,green:0.8,blue:0.1)"#).unwrap(),
1224            color
1225        );
1226
1227        assert_eq!(
1228            ron::from_str::<Rgba<Srgb>>(r#"Rgb(alpha:0.5,red:0.3,green:0.8,blue:0.1)"#).unwrap(),
1229            color
1230        );
1231    }
1232
1233    #[cfg(feature = "serializing")]
1234    #[test]
1235    fn serde_round_trips() {
1236        let color = Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5);
1237
1238        assert_eq!(
1239            serde_json::from_str::<Rgba<Srgb>>(&serde_json::to_string(&color).unwrap()).unwrap(),
1240            color
1241        );
1242
1243        assert_eq!(
1244            ron::from_str::<Rgba<Srgb>>(&ron::to_string(&color).unwrap()).unwrap(),
1245            color
1246        );
1247    }
1248
1249    #[cfg(feature = "serializing")]
1250    #[test]
1251    fn serde_various_types() {
1252        macro_rules! test_roundtrip {
1253            ($value:expr $(, $ron_name:expr)?) => {
1254                let value = super::Alpha {
1255                    color: $value,
1256                    alpha: 0.5,
1257                };
1258                assert_eq!(
1259                    serde_json::from_str::<super::Alpha<_, f32>>(
1260                        &serde_json::to_string(&value).expect("json serialization")
1261                    )
1262                    .expect("json deserialization"),
1263                    value
1264                );
1265
1266                let ron_string = ron::to_string(&value).expect("ron serialization");
1267                assert_eq!(
1268                    ron::from_str::<super::Alpha<_, f32>>(&ron_string)
1269                        .expect("ron deserialization"),
1270                    value
1271                );
1272                $(
1273                    assert_eq!(
1274                        ron::from_str::<super::Alpha<_, f32>>(&format!("{}{ron_string}", $ron_name))
1275                            .expect("ron deserialization"),
1276                        value
1277                    );
1278                )?
1279            };
1280        }
1281
1282        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1283        struct Empty;
1284        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1285        struct UnitTuple();
1286        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1287        struct Newtype(f32);
1288        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1289        struct Tuple(f32, f32);
1290        #[derive(Serialize, Deserialize, PartialEq, Debug)]
1291        struct Struct {
1292            value: f32,
1293        }
1294
1295        test_roundtrip!(());
1296        test_roundtrip!(Empty, "Empty");
1297        test_roundtrip!(UnitTuple(), "UnitTuple");
1298        test_roundtrip!(Newtype(0.1), "Newtype");
1299        test_roundtrip!(Tuple(0.1, 0.2), "Tuple");
1300        test_roundtrip!(Struct { value: 0.1 }, "Struct");
1301    }
1302
1303    test_uniform_distribution! {
1304        Rgba<Srgb, f32> {
1305            red: (0.0, 1.0),
1306            green: (0.0, 1.0),
1307            blue: (0.0, 1.0),
1308            alpha: (0.0, 1.0)
1309        },
1310        min: Rgba::new(0.0f32, 0.0, 0.0, 0.0),
1311        max: Rgba::new(1.0, 1.0, 1.0, 1.0)
1312    }
1313}