Skip to main content

chromashift/
channels.rs

1/// Trait for extracting the alpha channel of a color.
2pub trait ToAlpha: Sized {
3	/// Returns a number between 0.0 (fully transparent) to 100.0 (fully opaque).
4	fn to_alpha(&self) -> f32;
5
6	/// Returns true if the alpha of this colour is 100.0
7	fn fully_opaque(&self) -> bool {
8		self.to_alpha() == 100.0
9	}
10
11	/// Returns true if the alpha of this colour is 0.0
12	fn fully_transparent(&self) -> bool {
13		self.to_alpha() == 0.0
14	}
15}
16
17/// A generic single color channel value, which may be None
18///
19/// `none` channels in `color-mix` adopt the analogous channel's value from the other color in the interpolation space
20/// (see [`crate::InterpolationSpace::mix`]).
21pub type Channel = Option<f64>;
22
23use crate::{
24	A98Rgb, DisplayP3, Hsl, Hwb, Lab, Lch, LinearRgb, Oklab, Oklch, ProphotoRgb, Rec2020, Srgb, XyzD50, XyzD65,
25};
26
27macro_rules! impl_channels {
28	(@cast $v:expr, u8) => { $v.round() as u8 };
29	(@cast $v:expr, f64) => { $v };
30	(@cast $v:expr, f32) => { $v as f32 };
31	($ty:ident { $f1:ident: $t1:tt, $f2:ident: $t2:tt, $f3:ident: $t3:tt $(,)? }) => {
32		impl From<$ty> for [Channel; 4] {
33			fn from(c: $ty) -> Self {
34				[
35					Some(c.$f1 as f64),
36					Some(c.$f2 as f64),
37					Some(c.$f3 as f64),
38					Some(c.alpha as f64),
39				]
40			}
41		}
42
43		impl From<[Channel; 4]> for $ty {
44			fn from(c: [Channel; 4]) -> Self {
45				$ty::new(
46					impl_channels!(@cast c[0].unwrap_or(0.0), $t1),
47					impl_channels!(@cast c[1].unwrap_or(0.0), $t2),
48					impl_channels!(@cast c[2].unwrap_or(0.0), $t3),
49					c[3].unwrap_or(0.0) as f32,
50				)
51			}
52		}
53	};
54}
55
56impl_channels!(Srgb { red: f64, green: f64, blue: f64 });
57impl_channels!(LinearRgb { red: f64, green: f64, blue: f64 });
58impl_channels!(A98Rgb { red: f64, green: f64, blue: f64 });
59impl_channels!(DisplayP3 { red: f64, green: f64, blue: f64 });
60impl_channels!(ProphotoRgb { red: f64, green: f64, blue: f64 });
61impl_channels!(Rec2020 { red: f64, green: f64, blue: f64 });
62impl_channels!(Lab { lightness: f64, a: f64, b: f64 });
63impl_channels!(Oklab { lightness: f64, a: f64, b: f64 });
64impl_channels!(XyzD50 { x: f64, y: f64, z: f64 });
65impl_channels!(XyzD65 { x: f64, y: f64, z: f64 });
66impl_channels!(Hsl { hue: f64, saturation: f64, lightness: f64 });
67impl_channels!(Hwb { hue: f64, whiteness: f64, blackness: f64 });
68impl_channels!(Lch { lightness: f64, chroma: f64, hue: f64 });
69impl_channels!(Oklch { lightness: f64, chroma: f64, hue: f64 });