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