Skip to content

Commit d4c46a8

Browse files
committed
Improve the hue types a bit
1 parent 4ef9fc3 commit d4c46a8

File tree

2 files changed

+130
-57
lines changed

2 files changed

+130
-57
lines changed

palette/src/hues.rs

+88-17
Original file line numberDiff line numberDiff line change
@@ -10,66 +10,94 @@ macro_rules! make_hues {
1010
($($(#[$doc:meta])+ struct $name:ident;)+) => ($(
1111
$(#[$doc])+
1212
///
13-
///The hue is a circular type, where `0` and `360` is the same, and
14-
///it's normalized to `(-180, 180]` when it's converted to a linear
15-
///number (like `f32`). This makes many calculations easier, but may
16-
///also have some surprising effects if it's expected to act as a
17-
///linear number.
13+
/// The hue is a circular type, where `0` and `360` is the same, and
14+
/// it's normalized to `(-180, 180]` when it's converted to a linear
15+
/// number (like `f32`). This makes many calculations easier, but may
16+
/// also have some surprising effects if it's expected to act as a
17+
/// linear number.
1818
#[derive(Clone, Copy, Debug, Default)]
1919
#[repr(C)]
2020
pub struct $name<T: Float = f32>(T);
2121

2222
impl<T: Float> $name<T> {
23-
///Create a new hue from radians, instead of degrees.
23+
/// Create a new hue from degrees.
24+
#[inline]
25+
pub fn from_degrees(degrees: T) -> $name<T> {
26+
$name(degrees)
27+
}
28+
29+
/// Create a new hue from radians, instead of degrees.
30+
#[inline]
2431
pub fn from_radians(radians: T) -> $name<T> {
2532
$name(radians * cast(180.0) / cast(PI))
2633
}
2734

28-
///Get the hue as degrees, in the range `(-180, 180]`.
35+
/// Get the hue as degrees, in the range `(-180, 180]`.
36+
#[inline]
2937
pub fn to_degrees(self) -> T {
3038
normalize_angle(self.0)
3139
}
3240

33-
///Convert the hue to radians, in the range `(-π, π]`.
41+
/// Convert the hue to radians, in the range `(-π, π]`.
42+
#[inline]
3443
pub fn to_radians(self) -> T {
3544
normalize_angle(self.0) * cast(PI) / cast(180.0)
3645
}
3746

38-
///Convert the hue to positive degrees, in the range `[0, 360)`.
47+
/// Convert the hue to positive degrees, in the range `[0, 360)`.
48+
#[inline]
3949
pub fn to_positive_degrees(self) -> T {
4050
normalize_angle_positive(self.0)
4151
}
4252

43-
///Convert the hue to positive radians, in the range `[0, 2π)`.
53+
/// Convert the hue to positive radians, in the range `[0, 2π)`.
54+
#[inline]
4455
pub fn to_positive_radians(self) -> T {
4556
normalize_angle_positive(self.0) * cast(PI) / cast(180.0)
4657
}
58+
59+
/// Get the internal representation, without normalizing it.
60+
#[inline]
61+
pub fn to_raw_degrees(self) -> T {
62+
self.0
63+
}
64+
65+
/// Get the internal representation as radians, without normalizing it.
66+
#[inline]
67+
pub fn to_raw_radians(self) -> T {
68+
self.0 * cast(PI) / cast(180.0)
69+
}
4770
}
4871

4972
impl<T: Float> From<T> for $name<T> {
73+
#[inline]
5074
fn from(degrees: T) -> $name<T> {
5175
$name(degrees)
5276
}
5377
}
5478

5579
impl Into<f64> for $name<f64> {
80+
#[inline]
5681
fn into(self) -> f64 {
5782
normalize_angle(self.0)
5883
}
5984
}
6085

6186
impl Into<f32> for $name<f32> {
87+
#[inline]
6288
fn into(self) -> f32 {
6389
normalize_angle(self.0)
6490
}
6591
}
6692
impl Into<f32> for $name<f64> {
93+
#[inline]
6794
fn into(self) -> f32 {
6895
normalize_angle(self.0) as f32
6996
}
7097
}
7198

7299
impl<T: Float> PartialEq for $name<T> {
100+
#[inline]
73101
fn eq(&self, other: &$name<T>) -> bool {
74102
let hue_s: T = (*self).to_degrees();
75103
let hue_o: T = (*other).to_degrees();
@@ -78,6 +106,7 @@ macro_rules! make_hues {
78106
}
79107

80108
impl<T: Float> PartialEq<T> for $name<T> {
109+
#[inline]
81110
fn eq(&self, other: &T) -> bool {
82111
let hue: T = (*self).to_degrees();
83112
hue.eq(&normalize_angle(*other))
@@ -87,6 +116,7 @@ macro_rules! make_hues {
87116
impl<T: Float> Add<$name<T>> for $name<T> {
88117
type Output = $name<T>;
89118

119+
#[inline]
90120
fn add(self, other: $name<T>) -> $name<T> {
91121
$name(self.0 + other.0)
92122
}
@@ -95,14 +125,34 @@ macro_rules! make_hues {
95125
impl<T: Float> Add<T> for $name<T> {
96126
type Output = $name<T>;
97127

128+
#[inline]
98129
fn add(self, other: T) -> $name<T> {
99130
$name(self.0 + other)
100131
}
101132
}
102133

134+
impl Add<$name<f32>> for f32 {
135+
type Output = $name<f32>;
136+
137+
#[inline]
138+
fn add(self, other: $name<f32>) -> $name<f32> {
139+
$name(self + other.0)
140+
}
141+
}
142+
143+
impl Add<$name<f64>> for f64 {
144+
type Output = $name<f64>;
145+
146+
#[inline]
147+
fn add(self, other: $name<f64>) -> $name<f64> {
148+
$name(self + other.0)
149+
}
150+
}
151+
103152
impl<T: Float> Sub<$name<T>> for $name<T> {
104153
type Output = $name<T>;
105154

155+
#[inline]
106156
fn sub(self, other: $name<T>) -> $name<T> {
107157
$name(self.0 - other.0)
108158
}
@@ -111,34 +161,55 @@ macro_rules! make_hues {
111161
impl<T: Float> Sub<T> for $name<T> {
112162
type Output = $name<T>;
113163

164+
#[inline]
114165
fn sub(self, other: T) -> $name<T> {
115166
$name(self.0 - other)
116167
}
117168
}
169+
170+
impl Sub<$name<f32>> for f32 {
171+
type Output = $name<f32>;
172+
173+
#[inline]
174+
fn sub(self, other: $name<f32>) -> $name<f32> {
175+
$name(self - other.0)
176+
}
177+
}
178+
179+
impl Sub<$name<f64>> for f64 {
180+
type Output = $name<f64>;
181+
182+
#[inline]
183+
fn sub(self, other: $name<f64>) -> $name<f64> {
184+
$name(self - other.0)
185+
}
186+
}
118187
)+)
119188
}
120189

121190
make_hues! {
122-
///A hue type for the CIE L\*a\*b\* family of color spaces.
191+
/// A hue type for the CIE L\*a\*b\* family of color spaces.
123192
///
124-
///It's measured in degrees and it's based on the four physiological
125-
///elementary colors _red_, _yellow_, _green_ and _blue_. This makes it
126-
///different from the hue of RGB based color spaces.
193+
/// It's measured in degrees and it's based on the four physiological
194+
/// elementary colors _red_, _yellow_, _green_ and _blue_. This makes it
195+
/// different from the hue of RGB based color spaces.
127196
struct LabHue;
128197

129-
///A hue type for the RGB family of color spaces.
198+
/// A hue type for the RGB family of color spaces.
130199
///
131-
///It's measured in degrees and uses the three additive primaries _red_,
132-
///_green_ and _blue_.
200+
/// It's measured in degrees and uses the three additive primaries _red_,
201+
/// _green_ and _blue_.
133202
struct RgbHue;
134203
}
135204

205+
#[inline]
136206
fn normalize_angle<T: Float>(deg: T) -> T {
137207
let c360 = cast(360.0);
138208
let c180 = cast(180.0);
139209
deg - (((deg + c180) / c360) - T::one()).ceil() * c360
140210
}
141211

212+
#[inline]
142213
fn normalize_angle_positive<T: Float>(deg: T) -> T {
143214
let c360 = cast(360.0);
144215
deg - ((deg / c360).floor() * c360)

palette/src/lib.rs

+42-40
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
//!
3030
//! ```rust
3131
//! // An alias for Rgb<Srgb>, which is what most pictures store.
32-
//! use palette::{Srgb, Pixel};
32+
//! use palette::{Pixel, Srgb};
3333
//!
3434
//! let orangeish = Srgb::new(1.0, 0.6, 0.0).into_linear();
3535
//! let blueish = Srgb::new(0.0, 0.2, 1.0).into_linear();
3636
//! let whateve_it_becomes = orangeish + blueish;
3737
//!
3838
//! // Encode the result back into sRGB and create a byte array
39-
//! let pixel: [u8;3] = Srgb::from_linear(whateve_it_becomes)
39+
//! let pixel: [u8; 3] = Srgb::from_linear(whateve_it_becomes)
4040
//! .into_format()
4141
//! .into_raw();
4242
//! ```
@@ -53,7 +53,7 @@
5353
//! This approach comes with the extra benefit of allowing operations to
5454
//! selectively affect the alpha component:
5555
//!
56-
//! ```
56+
//! ```rust
5757
//! use palette::{LinSrgb, LinSrgba};
5858
//!
5959
//! let mut c1 = LinSrgba::new(1.0, 0.5, 0.5, 0.8);
@@ -63,6 +63,7 @@
6363
//! c1.blue += 0.2; //The color components can easily be accessed
6464
//! c1 = c1 * 0.5; //Scale both the color and the alpha
6565
//! ```
66+
//!
6667
6768
#![doc(html_root_url = "https://docs.rs/palette/0.3.0/palette/")]
6869
#![cfg_attr(feature = "strict", deny(missing_docs))]
@@ -583,18 +584,18 @@ pub trait Limited {
583584
fn clamp_self(&mut self);
584585
}
585586

586-
///A trait for linear color interpolation.
587+
/// A trait for linear color interpolation.
587588
///
588-
///```
589-
///use palette::{LinSrgb, Mix};
589+
/// ```
590+
/// use palette::{LinSrgb, Mix};
590591
///
591-
///let a = LinSrgb::new(0.0, 0.5, 1.0);
592-
///let b = LinSrgb::new(1.0, 0.5, 0.0);
592+
/// let a = LinSrgb::new(0.0, 0.5, 1.0);
593+
/// let b = LinSrgb::new(1.0, 0.5, 0.0);
593594
///
594-
///assert_eq!(a.mix(&b, 0.0), a);
595-
///assert_eq!(a.mix(&b, 0.5), LinSrgb::new(0.5, 0.5, 0.5));
596-
///assert_eq!(a.mix(&b, 1.0), b);
597-
///```
595+
/// assert_eq!(a.mix(&b, 0.0), a);
596+
/// assert_eq!(a.mix(&b, 0.5), LinSrgb::new(0.5, 0.5, 0.5));
597+
/// assert_eq!(a.mix(&b, 1.0), b);
598+
/// ```
598599
pub trait Mix {
599600
///The type of the mixing factor.
600601
type Scalar: Float;
@@ -607,16 +608,16 @@ pub trait Mix {
607608
fn mix(&self, other: &Self, factor: Self::Scalar) -> Self;
608609
}
609610

610-
///The `Shade` trait allows a color to be lightened or darkened.
611+
/// The `Shade` trait allows a color to be lightened or darkened.
611612
///
612-
///```
613-
///use palette::{LinSrgb, Shade};
613+
/// ```
614+
/// use palette::{LinSrgb, Shade};
614615
///
615-
///let a = LinSrgb::new(0.4, 0.4, 0.4);
616-
///let b = LinSrgb::new(0.6, 0.6, 0.6);
616+
/// let a = LinSrgb::new(0.4, 0.4, 0.4);
617+
/// let b = LinSrgb::new(0.6, 0.6, 0.6);
617618
///
618-
///assert_eq!(a.lighten(0.1), b.darken(0.1));
619-
///```
619+
/// assert_eq!(a.lighten(0.1), b.darken(0.1));
620+
/// ```
620621
pub trait Shade: Sized {
621622
///The type of the lighten/darken amount.
622623
type Scalar: Float;
@@ -630,21 +631,21 @@ pub trait Shade: Sized {
630631
}
631632
}
632633

633-
///A trait for colors where a hue may be calculated.
634+
/// A trait for colors where a hue may be calculated.
634635
///
635-
///```
636-
///use palette::{LinSrgb, GetHue};
636+
/// ```
637+
/// use palette::{GetHue, LinSrgb};
637638
///
638-
///let red = LinSrgb::new(1.0f32, 0.0, 0.0);
639-
///let green = LinSrgb::new(0.0f32, 1.0, 0.0);
640-
///let blue = LinSrgb::new(0.0f32, 0.0, 1.0);
641-
///let gray = LinSrgb::new(0.5f32, 0.5, 0.5);
639+
/// let red = LinSrgb::new(1.0f32, 0.0, 0.0);
640+
/// let green = LinSrgb::new(0.0f32, 1.0, 0.0);
641+
/// let blue = LinSrgb::new(0.0f32, 0.0, 1.0);
642+
/// let gray = LinSrgb::new(0.5f32, 0.5, 0.5);
642643
///
643-
///assert_eq!(red.get_hue(), Some(0.0.into()));
644-
///assert_eq!(green.get_hue(), Some(120.0.into()));
645-
///assert_eq!(blue.get_hue(), Some(240.0.into()));
646-
///assert_eq!(gray.get_hue(), None);
647-
///```
644+
/// assert_eq!(red.get_hue(), Some(0.0.into()));
645+
/// assert_eq!(green.get_hue(), Some(120.0.into()));
646+
/// assert_eq!(blue.get_hue(), Some(240.0.into()));
647+
/// assert_eq!(gray.get_hue(), None);
648+
/// ```
648649
pub trait GetHue {
649650
///The kind of hue unit this color space uses.
650651
///
@@ -670,17 +671,17 @@ pub trait Hue: GetHue {
670671
fn shift_hue<H: Into<Self::Hue>>(&self, amount: H) -> Self;
671672
}
672673

673-
///A trait for colors where the saturation (or chroma) can be manipulated
674-
///without conversion.
674+
/// A trait for colors where the saturation (or chroma) can be manipulated
675+
/// without conversion.
675676
///
676-
///```
677-
///use palette::{Hsv, Saturate};
677+
/// ```
678+
/// use palette::{Hsv, Saturate};
678679
///
679-
///let a = Hsv::new(0.0, 0.25, 1.0);
680-
///let b = Hsv::new(0.0, 1.0, 1.0);
680+
/// let a = Hsv::new(0.0, 0.25, 1.0);
681+
/// let b = Hsv::new(0.0, 1.0, 1.0);
681682
///
682-
///assert_eq!(a.saturate(1.0), b.desaturate(0.5));
683-
///```
683+
/// assert_eq!(a.saturate(1.0), b.desaturate(0.5));
684+
/// ```
684685
pub trait Saturate: Sized {
685686
///The type of the (de)saturation factor.
686687
type Scalar: Float;
@@ -836,7 +837,8 @@ impl Component for u64 {
836837
}
837838
}
838839

839-
///A convenience function to convert a constant number to Float Type
840+
/// A convenience function to convert a constant number to Float Type
841+
#[inline]
840842
fn cast<T: NumCast, P: ToPrimitive>(prim: P) -> T {
841843
NumCast::from(prim).unwrap()
842844
}

0 commit comments

Comments
 (0)