use crate::{NumConst, Rgb};
#[doc = crate::_tags!(color)]
#[doc = crate::_doc_location!("media/visual/color")]
#[must_use]
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Lum<T, const LINEAR: bool = true, const LIGHTNESS: bool = false> {
pub c: [T; 1],
}
#[doc = crate::_tags!(color)]
#[doc = crate::_doc_location!("media/visual/color")]
pub type Luminance<T> = Lum<T, true, false>;
#[doc = crate::_tags!(color)]
#[doc = crate::_doc_location!("media/visual/color")]
pub type Lightness<T> = Lum<T, false, true>;
#[doc = crate::_tags!(color)]
#[doc = crate::_doc_location!("media/visual/color")]
pub type Luma<T> = Lum<T, false, false>;
#[doc = crate::_tags!(color)]
#[doc = crate::_doc_location!("media/visual/color")]
pub type LinearLightness<T> = Lum<T, true, true>;
macro_rules! impl_lum {
() => {
impl_lum![common u8|f32, u16|f32];
impl_lum![common f32|f32];
impl_lum![common f64|f64];
impl_lum![lumina u8|f32:8+true, u16|f32:16+true];
impl_lum![lumina f32|f32:32+false];
impl_lum![lumina f64|f64:64+false];
impl_lum![light u8|f32:8+true, u16|f32:16+true];
impl_lum![light f32|f32:32+false];
impl_lum![light f64|f64:64+false];
impl_lum![luma u8|f32:8+true, u16|f32:16+true];
impl_lum![luma f32|f32:32+false];
impl_lum![luma f64|f64:64+false];
impl_lum![lumi_light u8|f32:8+true, u16|f32:16+true];
impl_lum![lumi_light f32|f32:32+false];
impl_lum![lumi_light f64|f64:64+false];
};
( // Methods common to all types.
common $( $T:ty | $f:ty ),+) => { $( impl_lum![@common $T|$f]; )+ };
(@common $T:ty | $f:ty ) => {
impl<const LINEAR: bool, const LIGHTNESS: bool> Lum<$T, LINEAR, LIGHTNESS> {
pub const fn new(c: $T) -> Self { Self { c: [c] } }
pub const fn l(self) -> $T { self.c[0] }
pub const fn l_mut(&mut self) -> &mut $T { &mut self.c[0] }
pub const fn brightness_from_rgb(rgb: Rgb<$T>) -> Self {
Self::new((rgb.r() + rgb.g() + rgb.b()) / <$T as NumConst>::NUM_THREE.unwrap())
}
}
};
( // Methods for Luminance: (linear non-lightness)
lumina $( $T:ty | $f:ty : $BITS:literal + $INT:literal),+) => {
$( impl_lum![@lumina $T|$f : $BITS+$INT]; )+
};
(@lumina $T:ty | $f:ty : $BITS:literal + $INT:literal ) => {
impl Luminance<$T> {
pub const fn luminance(self) -> $T { self.c[0] }
pub const fn luminance_mut(&mut self) -> &mut $T { &mut self.c[0] }
}
};
( light $( $T:ty | $f:ty : $BITS:literal + $INT:literal),+) => {
$( impl_lum![@light $T|$f : $BITS+$INT]; )+
};
(@light $T:ty | $f:ty : $BITS:literal + $INT:literal ) => {
impl Lightness<$T> {
pub const fn lightness(self) -> $T { self.c[0] }
pub const fn lightness_mut(&mut self) -> &mut $T { &mut self.c[0] }
}
};
( luma $( $T:ty | $f:ty : $BITS:literal + $INT:literal),+) => {
$( impl_lum![@luma $T|$f : $BITS+$INT]; )+
};
(@luma $T:ty | $f:ty : $BITS:literal + $INT:literal ) => {
impl Luma<$T> {
pub const fn lightness(self) -> $T { self.c[0] }
pub const fn lightness_mut(&mut self) -> &mut $T { &mut self.c[0] }
}
};
( lumi_light $( $T:ty | $f:ty : $BITS:literal + $INT:literal),+) => {
$( impl_lum![@lumi_light $T|$f : $BITS+$INT]; )+
};
(@lumi_light $T:ty | $f:ty : $BITS:literal + $INT:literal ) => {
impl LinearLightness<$T> {
pub const fn linear_lightness(self) -> $T { self.c[0] }
pub const fn linear_lightness_mut(&mut self) -> &mut $T { &mut self.c[0] }
}
};
}
impl_lum!();