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}