Skip to content

Commit

Permalink
Merge #300
Browse files Browse the repository at this point in the history
300: Removed manual conversion impls, fixed some docs, reduced trait bounds r=Ogeon a=Ogeon

This is a continuation of #258, with various improvements:

 * The manual conversion implementations could just be removed.  They were not needed and the errors were due to a misunderstanding.
 * Some documentation links were broken and some phrasing was changed.
 * There were still some redundant trait bounds that could be removed or simplified. I did also change places that required `Copy` to use `Clone`.

Co-authored-by: Erik Hedvall <erikwhedvall@gmail.com>
  • Loading branch information
bors[bot] and Ogeon authored Jan 11, 2023
2 parents f11e27c + f9d8db2 commit 2775fa6
Show file tree
Hide file tree
Showing 22 changed files with 476 additions and 618 deletions.
2 changes: 2 additions & 0 deletions palette/src/hsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,8 @@ mod test {
use super::Hsl;
use crate::{FromColor, Hsv, Srgb};

test_convert_into_from_xyz!(Hsl);

#[test]
fn red() {
let a = Hsl::from_color(Srgb::new(1.0, 0.0, 0.0));
Expand Down
2 changes: 2 additions & 0 deletions palette/src/hsluv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@ mod test {
use super::Hsluv;
use crate::{white_point::D65, FromColor, Lchuv, LuvHue, Saturate};

test_convert_into_from_xyz!(Hsluv);

#[test]
fn lchuv_round_trip() {
for hue in (0..=20).map(|x| x as f64 * 18.0) {
Expand Down
2 changes: 2 additions & 0 deletions palette/src/hsv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,8 @@ mod test {
use super::Hsv;
use crate::{FromColor, Hsl, Srgb};

test_convert_into_from_xyz!(Hsv);

#[test]
fn red() {
let a = Hsv::from_color(Srgb::new(1.0, 0.0, 0.0));
Expand Down
71 changes: 34 additions & 37 deletions palette/src/hues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::ops::Mul;

use core::{
cmp::PartialEq,
ops::{Add, AddAssign, Sub, SubAssign},
ops::{Add, AddAssign, Neg, Sub, SubAssign},
};

#[cfg(feature = "approx")]
Expand All @@ -19,14 +19,15 @@ use rand::{
};

#[cfg(feature = "approx")]
use crate::angle::HalfRotation;
use crate::num::Zero;
use crate::{angle::HalfRotation, num::Zero};

#[cfg(feature = "random")]
use crate::angle::FullRotation;

use crate::angle::{AngleEq, FromAngle, RealAngle, SignedAngle, UnsignedAngle};
use crate::num::{Arithmetics, Trigonometry};
use crate::{
angle::{AngleEq, FromAngle, RealAngle, SignedAngle, UnsignedAngle},
num::Trigonometry,
};

macro_rules! make_hues {
($($(#[$doc:meta])+ struct $name:ident;)+) => ($(
Expand Down Expand Up @@ -132,6 +133,32 @@ macro_rules! make_hues {
}
}

impl<T: RealAngle + Trigonometry> $name<T> {
/// Returns a hue from `a` and `b`, normalized to `[0°, 360°)`.
///
/// If `a` and `b` are both `0`, returns `0`,
#[inline(always)]
pub fn from_cartesian(a: T, b: T) -> Self where T: Add<T, Output = T> + Neg<Output = T> {
// atan2 returns values in the interval [-π, π]
// instead of
// let hue_rad = T::atan2(b,a);
// use negative a and be and rotate, to ensure the hue is normalized,
let hue_rad = T::from_f64(core::f64::consts::PI) + T::atan2(-b, -a);
Self::from_radians(hue_rad)
}

/// Returns `a` and `b` values for this hue, normalized to `[-1,
/// 1]`.
///
/// They will have to be multiplied by a radius values, such as
/// saturation, value, chroma, etc., to represent a specific color.
#[inline(always)]
pub fn into_cartesian(self) -> (T, T) {
let (b, a) = self.into_raw_radians().sin_cos();
(a, b) // Note the swapped order compared to above
}
}

impl<T> From<T> for $name<T> {
#[inline]
fn from(degrees: T) -> $name<T> {
Expand Down Expand Up @@ -518,36 +545,6 @@ impl_uniform!(UniformRgbHue, RgbHue);
impl_uniform!(UniformLuvHue, LuvHue);
impl_uniform!(UniformOklabHue, OklabHue);

impl<T> OklabHue<T>
where
T: RealAngle + Zero + Arithmetics + Trigonometry + Clone + PartialEq,
{
/// Returns `a` and `b` values for this hue at the given `croma`
#[inline(always)]
pub fn ab(self, chroma: T) -> (T, T) {
let hue_rad = self.into_raw_radians();
let (sin, cos) = hue_rad.sin_cos();
(chroma.clone() * cos, chroma * sin)
}

/// Returns a hue from `a` and `b`, with a normalized angle, i.e. an angle in the half
/// open interval [0° .. 360°).
/// If `a` and `b` are both `zero`, returns `None`
#[inline(always)]
pub fn from_ab(a: T, b: T) -> Option<Self> {
if a == T::zero() && b == T::zero() {
None
} else {
// atan2 returns values in the interval [-π .. π]
// instead of
// let hue_rad = T::atan2(b,a);
// use negative a and be and rotate, to ensure the hue is normalized,
let hue_rad = T::from_f64(core::f64::consts::PI) + T::atan2(-b, -a);
Some(Self::from_radians(hue_rad))
}
}
}

#[cfg(test)]
mod test {
use crate::{
Expand All @@ -559,8 +556,8 @@ mod test {
fn oklabhue_ab_roundtrip() {
for degree in [0.0_f64, 90.0, 30.0, 330.0, 120.0, 240.0] {
let hue = OklabHue::from_degrees(degree);
let (a, b) = hue.ab(10000.0);
let roundtrip_hue = OklabHue::from_ab(a, b).unwrap();
let (a, b) = hue.into_cartesian();
let roundtrip_hue = OklabHue::from_cartesian(a * 10000.0, b * 10000.0);
assert_abs_diff_eq!(roundtrip_hue, hue);
}
}
Expand Down
2 changes: 2 additions & 0 deletions palette/src/hwb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,8 @@ mod test {
use super::Hwb;
use crate::{Clamp, FromColor, Srgb};

test_convert_into_from_xyz!(Hwb);

#[test]
fn red() {
let a = Hwb::from_color(Srgb::new(1.0, 0.0, 0.0));
Expand Down
8 changes: 5 additions & 3 deletions palette/src/lab.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::{
marker::PhantomData,
ops::{Add, AddAssign, BitAnd, BitOr, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
ops::{Add, AddAssign, BitAnd, BitOr, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};

#[cfg(feature = "approx")]
Expand Down Expand Up @@ -295,12 +295,12 @@ impl_premultiply!(Lab<Wp> {l, a, b} phantom: white_point);

impl<Wp, T> GetHue for Lab<Wp, T>
where
T: RealAngle + Trigonometry + Clone,
T: RealAngle + Trigonometry + Add<T, Output = T> + Neg<Output = T> + Clone,
{
type Hue = LabHue<T>;

fn get_hue(&self) -> LabHue<T> {
LabHue::from_radians(self.b.clone().atan2(self.a.clone()))
LabHue::from_cartesian(self.a.clone(), self.b.clone())
}
}

Expand Down Expand Up @@ -469,6 +469,8 @@ mod test {
use crate::white_point::D65;
use crate::{FromColor, LinSrgb};

test_convert_into_from_xyz!(Lab);

#[test]
fn red() {
let a = Lab::from_color(LinSrgb::new(1.0, 0.0, 0.0));
Expand Down
2 changes: 2 additions & 0 deletions palette/src/lch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@ mod test {
use crate::white_point::D65;
use crate::Lch;

test_convert_into_from_xyz!(Lch);

#[test]
fn ranges() {
assert_ranges! {
Expand Down
2 changes: 2 additions & 0 deletions palette/src/lchuv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@ mod test {
use crate::white_point::D65;
use crate::Lchuv;

test_convert_into_from_xyz!(Lchuv);

#[test]
fn ranges() {
assert_ranges! {
Expand Down
2 changes: 2 additions & 0 deletions palette/src/luma/luma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,8 @@ mod test {
use crate::encoding::Srgb;
use crate::Luma;

test_convert_into_from_xyz!(Luma);

#[test]
fn ranges() {
assert_ranges! {
Expand Down
8 changes: 5 additions & 3 deletions palette/src/luv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::{
marker::PhantomData,
ops::{Add, AddAssign, BitAnd, Div, DivAssign, Mul, MulAssign, Sub, SubAssign},
ops::{Add, AddAssign, BitAnd, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};

#[cfg(feature = "approx")]
Expand Down Expand Up @@ -302,12 +302,12 @@ impl_premultiply!(Luv<Wp> {l, u, v} phantom: white_point);

impl<Wp, T> GetHue for Luv<Wp, T>
where
T: RealAngle + Trigonometry + Clone,
T: RealAngle + Trigonometry + Add<T, Output = T> + Neg<Output = T> + Clone,
{
type Hue = LuvHue<T>;

fn get_hue(&self) -> LuvHue<T> {
LuvHue::from_radians(self.v.clone().atan2(self.u.clone()))
LuvHue::from_cartesian(self.u.clone(), self.v.clone())
}
}

Expand Down Expand Up @@ -451,6 +451,8 @@ mod test {
use crate::white_point::D65;
use crate::{FromColor, LinSrgb};

test_convert_into_from_xyz!(Luv);

#[test]
fn red() {
let u = Luv::from_color(LinSrgb::new(1.0, 0.0, 0.0));
Expand Down
2 changes: 2 additions & 0 deletions palette/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ mod lazy_select;
mod simd;
#[macro_use]
mod clamp;
#[macro_use]
mod convert;

#[cfg(feature = "random")]
#[macro_use]
Expand Down
19 changes: 19 additions & 0 deletions palette/src/macros/convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/// Check that traits for converting to and from XYZ have been implemented.
#[cfg(test)]
macro_rules! test_convert_into_from_xyz {
($ty:ty) => {
#[test]
fn convert_from_xyz() {
use crate::FromColor;

let _: $ty = <$ty>::from_color(crate::Xyz::default());
}

#[test]
fn convert_into_xyz() {
use crate::FromColor;

let _: crate::Xyz = crate::Xyz::from_color(<$ty>::default());
}
};
}
Loading

0 comments on commit 2775fa6

Please sign in to comment.