palette/
alpha.rs

1//! Types related to transparent colors.
2
3#[doc(hidden)]
4pub use palette_derive::WithAlpha;
5
6use crate::{num::Zero, stimulus::Stimulus};
7
8pub use self::alpha::*;
9
10#[doc(no_inline)]
11pub use crate::blend::PreAlpha; // Cross-link for visibility.
12
13#[allow(clippy::module_inception)]
14mod alpha;
15
16/// A trait for color types that can have or be given transparency (alpha channel).
17///
18/// `WithAlpha` is an interface for adding, removing and setting the alpha
19/// channel of a color type. The color type itself doesn't need to store the
20/// transparency value as it can be transformed into or wrapped in a type that
21/// has a representation of transparency. This would typically be done by
22/// wrapping it in an [`Alpha`] instance.
23///
24/// # Deriving
25/// The trait is trivial enough to be automatically derived. If the color type
26/// has a field for transparency (an alpha channel), it has to be marked with
27/// `#[palette(alpha)]` to be taken into account.
28///
29/// Derived without an internal alpha channel:
30///
31/// ```
32/// use palette::WithAlpha;
33///
34/// #[derive(WithAlpha)]
35/// struct CustomColor {
36///     redness: f32,
37///     glow: f32,
38///     glitter: f32,
39/// }
40///
41/// let color = CustomColor {
42///     redness: 0.8,
43///     glow: 2.5,
44///     glitter: 1000.0
45/// };
46/// let transparent = color.with_alpha(0.3);
47///
48/// assert_eq!(transparent.alpha, 0.3);
49/// ```
50///
51/// Derived with an internal alpha channel:
52///
53/// ```
54/// use palette::WithAlpha;
55///
56/// #[derive(WithAlpha)]
57/// struct CustomColor {
58///     redness: f32,
59///     glow: f32,
60///     glitter: f32,
61///
62///     #[palette(alpha)]
63///     alpha: u8,
64/// }
65///
66/// let color = CustomColor {
67///     redness: 0.8,
68///     glow: 2.5,
69///     glitter: 1000.0,
70///     alpha: 255
71/// };
72/// let transparent = color.with_alpha(10);
73///
74/// assert_eq!(transparent.alpha, 10);
75/// ```
76pub trait WithAlpha<A>: Sized {
77    /// The opaque color type, without any transparency.
78    ///
79    /// This is typically `Self`.
80    type Color;
81
82    /// The color type with transparency applied.
83    ///
84    /// This is typically `Alpha<Self::Color, A>`.
85    type WithAlpha: WithAlpha<A, Color = Self::Color, WithAlpha = Self::WithAlpha>;
86
87    /// Transforms the color into a transparent color with the provided
88    /// alpha value. If `Self` already has a transparency, it is
89    /// overwritten.
90    ///
91    /// ```
92    /// use palette::{Srgb, WithAlpha};
93    ///
94    /// let color = Srgb::new(255u8, 0, 255);
95    ///
96    /// // This results in an `Alpha<Srgb<u8>, f32>`
97    /// let transparent = color.with_alpha(0.3f32);
98    /// assert_eq!(transparent.alpha, 0.3);
99    ///
100    /// // This changes the transparency to 0.8
101    /// let transparent = transparent.with_alpha(0.8f32);
102    /// assert_eq!(transparent.alpha, 0.8);
103    /// ```
104    #[must_use]
105    fn with_alpha(self, alpha: A) -> Self::WithAlpha;
106
107    /// Removes the transparency from the color. If `Self::Color` has
108    /// an internal transparency field, that field will be set to
109    /// `A::max_intensity()` to make it opaque.
110    ///
111    /// ```
112    /// use palette::{Srgba, Srgb, WithAlpha};
113    ///
114    /// let transparent = Srgba::new(255u8, 0, 255, 10);
115    ///
116    /// // This unwraps the color information from the `Alpha` wrapper
117    /// let color = transparent.without_alpha();
118    /// assert_eq!(transparent.color, color);
119    /// ```
120    #[must_use]
121    fn without_alpha(self) -> Self::Color;
122
123    /// Splits the color into separate color and transparency values.
124    ///
125    /// A color without any transparency field will return
126    /// `A::max_intensity()` instead. If `Self::Color` has an internal
127    /// transparency field, that field will be set to
128    /// `A::max_intensity()` to make it opaque.
129    ///
130    /// ```
131    /// use palette::{Srgba, Srgb, WithAlpha};
132    ///
133    /// let transparent = Srgba::new(255u8, 0, 255, 10);
134    ///
135    /// // This unwraps both the color and alpha from the `Alpha` wrapper
136    /// let (color, alpha) = transparent.split();
137    /// assert_eq!(transparent.color, color);
138    /// assert_eq!(transparent.alpha, alpha);
139    /// ```
140    #[must_use]
141    fn split(self) -> (Self::Color, A);
142
143    /// Transforms the color into a fully opaque color with a transparency
144    /// field. If `Self` already has a transparency, it is overwritten.
145    ///
146    /// ```
147    /// use palette::{Srgb, Srgba, WithAlpha};
148    ///
149    /// let color = Srgb::new(255u8, 0, 255);
150    ///
151    /// let opaque: Srgba<u8> = color.opaque();
152    /// assert_eq!(opaque.alpha, 255);
153    /// ```
154    #[must_use]
155    #[inline]
156    fn opaque(self) -> Self::WithAlpha
157    where
158        A: Stimulus,
159    {
160        self.with_alpha(A::max_intensity())
161    }
162
163    /// Transforms the color into a fully transparent color. If `Self`
164    /// already has a transparency, it is overwritten.
165    ///
166    /// ```
167    /// use palette::{Srgb, Srgba, WithAlpha};
168    ///
169    /// let color = Srgb::new(255u8, 0, 255);
170    ///
171    /// let transparent: Srgba<u8> = color.transparent();
172    /// assert_eq!(transparent.alpha, 0);
173    /// ```
174    #[must_use]
175    #[inline]
176    fn transparent(self) -> Self::WithAlpha
177    where
178        A: Zero,
179    {
180        self.with_alpha(A::zero())
181    }
182}