Skip to content

Commit

Permalink
Merge #362
Browse files Browse the repository at this point in the history
362: Add macros for `rand` traits and tuple converison r=Ogeon a=Ogeon

This should cover most of the remaining repetitive parts that aren't too specific for macros. I may also do a separate refactor pass to make the color source files follow the same structure.

The only observable change should be that `Okhsv` doesn't require any additional traits for converting from a tuple, compared to other radial types.

Co-authored-by: Erik Hedvall <erikwhedvall@gmail.com>
  • Loading branch information
bors[bot] and Ogeon authored Oct 29, 2023
2 parents a5afba8 + e377480 commit 508f644
Show file tree
Hide file tree
Showing 29 changed files with 998 additions and 2,120 deletions.
1 change: 0 additions & 1 deletion palette/src/alpha/alpha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,6 @@ mod test {
test_roundtrip!(Struct { value: 0.1 }, "Struct");
}

#[cfg(feature = "random")]
test_uniform_distribution! {
Rgba<Srgb, f32> {
red: (0.0, 1.0),
Expand Down
139 changes: 9 additions & 130 deletions palette/src/hsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@
use core::{any::TypeId, marker::PhantomData, ops::Not};

#[cfg(feature = "random")]
use rand::{
distributions::{
uniform::{SampleBorrow, SampleUniform, Uniform, UniformSampler},
Distribution, Standard,
},
Rng,
};

#[cfg(feature = "random")]
use crate::num::{Cbrt, Powi, Sqrt};

use crate::{
angle::{FromAngle, RealAngle},
bool_mask::{BitOps, BoolMask, HasBoolMask, LazySelect, Select},
Expand Down Expand Up @@ -452,29 +440,7 @@ where
}
}

impl<S, T, H: Into<RgbHue<T>>> From<(H, T, T)> for Hsl<S, T> {
fn from(components: (H, T, T)) -> Self {
Self::from_components(components)
}
}

impl<S, T> From<Hsl<S, T>> for (RgbHue<T>, T, T) {
fn from(color: Hsl<S, T>) -> (RgbHue<T>, T, T) {
color.into_components()
}
}

impl<S, T, H: Into<RgbHue<T>>, A> From<(H, T, T, A)> for Alpha<Hsl<S, T>, A> {
fn from(components: (H, T, T, A)) -> Self {
Self::from_components(components)
}
}

impl<S, T, A> From<Alpha<Hsl<S, T>, A>> for (RgbHue<T>, T, T, A) {
fn from(color: Alpha<Hsl<S, T>, A>) -> (RgbHue<T>, T, T, A) {
color.into_components()
}
}
impl_tuple_conversion_hue!(Hsl<S> as (H, T, T), RgbHue);

impl_is_within_bounds! {
Hsl<S> {
Expand Down Expand Up @@ -547,101 +513,15 @@ where
}
}

#[cfg(feature = "random")]
impl<S, T> Distribution<Hsl<S, T>> for Standard
where
T: Real + One + Cbrt + Sqrt + Arithmetics + PartialCmp + Clone,
T::Mask: LazySelect<T> + Clone,
Standard: Distribution<T> + Distribution<RgbHue<T>>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Hsl<S, T> {
crate::random_sampling::sample_hsl(rng.gen::<RgbHue<T>>(), rng.gen(), rng.gen())
}
}

/// Sample HSL colors uniformly.
#[cfg(feature = "random")]
pub struct UniformHsl<S, T>
where
T: SampleUniform,
{
hue: crate::hues::UniformRgbHue<T>,
u1: Uniform<T>,
u2: Uniform<T>,
space: PhantomData<S>,
}

#[cfg(feature = "random")]
impl<S, T> SampleUniform for Hsl<S, T>
where
T: Real + One + Cbrt + Sqrt + Powi + Arithmetics + PartialCmp + Clone + SampleUniform,
T::Mask: LazySelect<T> + Clone,
RgbHue<T>: SampleBorrow<RgbHue<T>>,
crate::hues::UniformRgbHue<T>: UniformSampler<X = RgbHue<T>>,
{
type Sampler = UniformHsl<S, T>;
}

#[cfg(feature = "random")]
impl<S, T> UniformSampler for UniformHsl<S, T>
where
T: Real + One + Cbrt + Sqrt + Powi + Arithmetics + PartialCmp + Clone + SampleUniform,
T::Mask: LazySelect<T> + Clone,
RgbHue<T>: SampleBorrow<RgbHue<T>>,
crate::hues::UniformRgbHue<T>: UniformSampler<X = RgbHue<T>>,
{
type X = Hsl<S, T>;

fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
use crate::random_sampling::invert_hsl_sample;

let low = low_b.borrow().clone();
let high = high_b.borrow().clone();

let (r1_min, r2_min) = invert_hsl_sample(low.saturation, low.lightness);
let (r1_max, r2_max) = invert_hsl_sample(high.saturation, high.lightness);

UniformHsl {
hue: crate::hues::UniformRgbHue::new(low.hue, high.hue),
u1: Uniform::new::<_, T>(r1_min, r1_max),
u2: Uniform::new::<_, T>(r2_min, r2_max),
space: PhantomData,
}
}

fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
use crate::random_sampling::invert_hsl_sample;

let low = low_b.borrow().clone();
let high = high_b.borrow().clone();

let (r1_min, r2_min) = invert_hsl_sample(low.saturation, low.lightness);
let (r1_max, r2_max) = invert_hsl_sample(high.saturation, high.lightness);

UniformHsl {
hue: crate::hues::UniformRgbHue::new_inclusive(low.hue, high.hue),
u1: Uniform::new_inclusive::<_, T>(r1_min, r1_max),
u2: Uniform::new_inclusive::<_, T>(r2_min, r2_max),
space: PhantomData,
}
}

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Hsl<S, T> {
crate::random_sampling::sample_hsl(
self.hue.sample(rng),
self.u1.sample(rng),
self.u2.sample(rng),
)
impl_rand_traits_hsl_bicone!(
UniformHsl,
Hsl<S> {
hue: UniformRgbHue => RgbHue,
height: lightness,
radius: saturation
}
}
phantom: standard: PhantomData<S>
);

#[cfg(feature = "bytemuck")]
unsafe impl<S, T> bytemuck::Zeroable for Hsl<S, T> where T: bytemuck::Zeroable {}
Expand Down Expand Up @@ -772,7 +652,6 @@ mod test {
assert_eq!(deserialized, Hsl::new(0.3, 0.8, 0.1));
}

#[cfg(feature = "random")]
test_uniform_distribution! {
Hsl<crate::encoding::Srgb, f32> as crate::rgb::Rgb {
red: (0.0, 1.0),
Expand Down
138 changes: 9 additions & 129 deletions palette/src/hsluv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@
use core::marker::PhantomData;

#[cfg(feature = "random")]
use rand::{
distributions::{
uniform::{SampleBorrow, SampleUniform, Uniform, UniformSampler},
Distribution, Standard,
},
Rng,
};

#[cfg(feature = "random")]
use crate::num::{Cbrt, One, Sqrt};

use crate::{
angle::RealAngle,
bool_mask::{HasBoolMask, LazySelect},
Expand Down Expand Up @@ -182,29 +170,7 @@ where
}
}

impl<Wp, T, H: Into<LuvHue<T>>> From<(H, T, T)> for Hsluv<Wp, T> {
fn from(components: (H, T, T)) -> Self {
Self::from_components(components)
}
}

impl<Wp, T> From<Hsluv<Wp, T>> for (LuvHue<T>, T, T) {
fn from(color: Hsluv<Wp, T>) -> (LuvHue<T>, T, T) {
color.into_components()
}
}

impl<Wp, T, H: Into<LuvHue<T>>, A> From<(H, T, T, A)> for Alpha<Hsluv<Wp, T>, A> {
fn from(components: (H, T, T, A)) -> Self {
Self::from_components(components)
}
}

impl<Wp, T, A> From<Alpha<Hsluv<Wp, T>, A>> for (LuvHue<T>, T, T, A) {
fn from(color: Alpha<Hsluv<Wp, T>, A>) -> (LuvHue<T>, T, T, A) {
color.into_components()
}
}
impl_tuple_conversion_hue!(Hsluv<Wp> as (H, T, T), LuvHue);

impl_is_within_bounds! {
Hsluv<Wp> {
Expand Down Expand Up @@ -272,101 +238,15 @@ where
}
}

#[cfg(feature = "random")]
impl<Wp, T> Distribution<Hsluv<Wp, T>> for Standard
where
T: Real + One + Cbrt + Sqrt + Arithmetics + PartialCmp + Clone,
T::Mask: LazySelect<T> + Clone,
Standard: Distribution<T> + Distribution<LuvHue<T>>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Hsluv<Wp, T> {
crate::random_sampling::sample_hsluv(rng.gen::<LuvHue<T>>(), rng.gen(), rng.gen())
}
}

/// Sample HSLuv colors uniformly.
#[cfg(feature = "random")]
pub struct UniformHsluv<Wp, T>
where
T: SampleUniform,
{
hue: crate::hues::UniformLuvHue<T>,
u1: Uniform<T>,
u2: Uniform<T>,
space: PhantomData<Wp>,
}

#[cfg(feature = "random")]
impl<Wp, T> SampleUniform for Hsluv<Wp, T>
where
T: Real + One + Cbrt + Sqrt + Powi + Arithmetics + PartialCmp + Clone + SampleUniform,
T::Mask: LazySelect<T> + Clone,
LuvHue<T>: SampleBorrow<LuvHue<T>>,
crate::hues::UniformLuvHue<T>: UniformSampler<X = LuvHue<T>>,
{
type Sampler = UniformHsluv<Wp, T>;
}

#[cfg(feature = "random")]
impl<Wp, T> UniformSampler for UniformHsluv<Wp, T>
where
T: Real + One + Cbrt + Sqrt + Powi + Arithmetics + PartialCmp + Clone + SampleUniform,
T::Mask: LazySelect<T> + Clone,
LuvHue<T>: SampleBorrow<LuvHue<T>>,
crate::hues::UniformLuvHue<T>: UniformSampler<X = LuvHue<T>>,
{
type X = Hsluv<Wp, T>;

fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
use crate::random_sampling::invert_hsluv_sample;

let low = low_b.borrow().clone();
let high = high_b.borrow().clone();

let (r1_min, r2_min): (T, T) = invert_hsluv_sample(low.saturation, low.l);
let (r1_max, r2_max): (T, T) = invert_hsluv_sample(high.saturation, high.l);

UniformHsluv {
hue: crate::hues::UniformLuvHue::new(low.hue, high.hue),
u1: Uniform::new::<_, T>(r1_min, r1_max),
u2: Uniform::new::<_, T>(r2_min, r2_max),
space: PhantomData,
}
}

fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
use crate::random_sampling::invert_hsluv_sample;

let low = low_b.borrow().clone();
let high = high_b.borrow().clone();

let (r1_min, r2_min): (T, T) = invert_hsluv_sample(low.saturation, low.l);
let (r1_max, r2_max): (T, T) = invert_hsluv_sample(high.saturation, high.l);

UniformHsluv {
hue: crate::hues::UniformLuvHue::new_inclusive(low.hue, high.hue),
u1: Uniform::new_inclusive::<_, T>(r1_min, r1_max),
u2: Uniform::new_inclusive::<_, T>(r2_min, r2_max),
space: PhantomData,
}
}

fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Hsluv<Wp, T> {
crate::random_sampling::sample_hsluv(
self.hue.sample(rng),
self.u1.sample(rng),
self.u2.sample(rng),
)
impl_rand_traits_hsl_bicone!(
UniformHsluv,
Hsluv<Wp> {
hue: UniformLuvHue => LuvHue,
height: l => [|l: T| l * T::from_f64(100.0), |l: T| l / T::from_f64(100.0)],
radius: saturation => [|s: T| s * T::from_f64(100.0), |s: T| s / T::from_f64(100.0)]
}
}
phantom: white_point: PhantomData<Wp>
);

#[cfg(feature = "bytemuck")]
unsafe impl<Wp, T> bytemuck::Zeroable for Hsluv<Wp, T> where T: bytemuck::Zeroable {}
Expand Down
Loading

0 comments on commit 508f644

Please sign in to comment.