Skip to content

Commit

Permalink
Merge 2f96885 into 5262025
Browse files Browse the repository at this point in the history
  • Loading branch information
Ogeon authored Apr 23, 2023
2 parents 5262025 + 2f96885 commit da49fc0
Show file tree
Hide file tree
Showing 36 changed files with 1,850 additions and 31 deletions.
5 changes: 5 additions & 0 deletions palette/src/alpha.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
//! Types related to transparent colors.
#[doc(hidden)]
pub use palette_derive::WithAlpha;

use crate::{num::Zero, stimulus::Stimulus};

pub use self::alpha::*;

#[doc(no_inline)]
pub use crate::blend::PreAlpha; // Cross-link for visibility.

mod alpha;

/// A trait for color types that can have or be given transparency (alpha channel).
Expand Down
186 changes: 186 additions & 0 deletions palette/src/alpha/alpha.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use core::{
fmt,
iter::FromIterator,
ops::{
Add, AddAssign, BitAnd, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Sub, SubAssign,
},
Expand Down Expand Up @@ -40,6 +41,24 @@ pub struct Alpha<C, T> {
pub alpha: T,
}

impl<C, A> Alpha<C, A> {
/// Return an iterator over the colors in the wrapped collections.
pub fn iter<'a>(&'a self) -> <&'a Self as IntoIterator>::IntoIter
where
&'a Self: IntoIterator,
{
self.into_iter()
}

/// Return an iterator that allows modifying the colors in the wrapped collections.
pub fn iter_mut<'a>(&'a mut self) -> <&'a mut Self as IntoIterator>::IntoIter
where
&'a mut Self: IntoIterator,
{
self.into_iter()
}
}

impl<C: Premultiply> Alpha<C, C::Scalar> {
/// Alpha mask the color by its transparency.
pub fn premultiply(self) -> PreAlpha<C> {
Expand Down Expand Up @@ -656,6 +675,172 @@ where
}
}

impl<Tc, Ta, C, A> Extend<Alpha<Tc, Ta>> for Alpha<C, A>
where
C: Extend<Tc>,
A: Extend<Ta>,
{
fn extend<T: IntoIterator<Item = Alpha<Tc, Ta>>>(&mut self, iter: T) {
for color in iter {
self.color.extend(core::iter::once(color.color));
self.alpha.extend(core::iter::once(color.alpha));
}
}
}

impl<Tc, Ta, C, A> FromIterator<Alpha<Tc, Ta>> for Alpha<C, A>
where
C: Extend<Tc> + FromIterator<Tc>,
A: Extend<Ta> + Default,
{
fn from_iter<T: IntoIterator<Item = Alpha<Tc, Ta>>>(iter: T) -> Self {
let mut result = Self {
color: C::from_iter(None), // Default is currently a used for black, meaning it's not always what we want here.
alpha: A::default(),
};

for color in iter {
result.color.extend(core::iter::once(color.color));
result.alpha.extend(core::iter::once(color.alpha));
}

result
}
}

impl<C, A> IntoIterator for Alpha<C, A>
where
C: IntoIterator,
A: IntoIterator,
{
type Item = Alpha<C::Item, A::Item>;

type IntoIter = Iter<C::IntoIter, A::IntoIter>;

fn into_iter(self) -> Self::IntoIter {
Iter {
color: self.color.into_iter(),
alpha: self.alpha.into_iter(),
}
}
}

impl<'a, C, A> IntoIterator for &'a Alpha<C, A>
where
&'a C: IntoIterator,
&'a A: IntoIterator,
{
type Item = Alpha<<&'a C as IntoIterator>::Item, <&'a A as IntoIterator>::Item>;

type IntoIter = Iter<<&'a C as IntoIterator>::IntoIter, <&'a A as IntoIterator>::IntoIter>;

fn into_iter(self) -> Self::IntoIter {
Iter {
color: (&self.color).into_iter(),
alpha: (&self.alpha).into_iter(),
}
}
}

impl<'a, C, A> IntoIterator for &'a mut Alpha<C, A>
where
&'a mut C: IntoIterator,
&'a mut A: IntoIterator,
{
type Item = Alpha<<&'a mut C as IntoIterator>::Item, <&'a mut A as IntoIterator>::Item>;

type IntoIter =
Iter<<&'a mut C as IntoIterator>::IntoIter, <&'a mut A as IntoIterator>::IntoIter>;

fn into_iter(self) -> Self::IntoIter {
Iter {
color: (&mut self.color).into_iter(),
alpha: (&mut self.alpha).into_iter(),
}
}
}

/// An iterator for transparent colors.
pub struct Iter<C, A> {
pub(crate) color: C,
pub(crate) alpha: A,
}

impl<C, A> Iterator for Iter<C, A>
where
C: Iterator,
A: Iterator,
{
type Item = Alpha<C::Item, A::Item>;

fn next(&mut self) -> Option<Self::Item> {
let color = self.color.next();
let alpha = self.alpha.next();

if let (Some(color), Some(alpha)) = (color, alpha) {
Some(Alpha { color, alpha })
} else {
None
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
let hint = self.color.size_hint();
debug_assert_eq!(
self.alpha.size_hint(),
hint,
"the color and alpha iterators have different size hints"
);

hint
}

fn count(self) -> usize {
let count = self.color.count();
debug_assert_eq!(
self.alpha.count(),
count,
"the color and alpha iterators have different counts"
);

count
}
}

impl<C, A> DoubleEndedIterator for Iter<C, A>
where
C: DoubleEndedIterator,
A: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
let color = self.color.next_back();
let alpha = self.alpha.next_back();

if let (Some(color), Some(alpha)) = (color, alpha) {
Some(Alpha { color, alpha })
} else {
None
}
}
}

impl<C, A> ExactSizeIterator for Iter<C, A>
where
C: ExactSizeIterator,
A: ExactSizeIterator,
{
fn len(&self) -> usize {
let len = self.color.len();
debug_assert_eq!(
self.alpha.len(),
len,
"the color and alpha iterators have different lengths"
);

len
}
}

#[cfg(feature = "serializing")]
impl<C, T> serde::Serialize for Alpha<C, T>
where
Expand Down Expand Up @@ -711,6 +896,7 @@ where
}
}

/// Sample transparent colors uniformly.
#[cfg(feature = "random")]
pub struct UniformAlpha<C, T>
where
Expand Down
26 changes: 26 additions & 0 deletions palette/src/hsl.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Types for the HSL color space.
use core::{
any::TypeId,
marker::PhantomData,
Expand All @@ -24,6 +26,7 @@ use crate::{
clamp, clamp_assign, contrast_ratio,
convert::FromColorUnclamped,
encoding::Srgb,
hues::RgbHueIter,
num::{
self, Arithmetics, FromScalarArray, IntoScalarArray, IsValidDivisor, MinMax, One,
PartialCmp, Real, Zero,
Expand Down Expand Up @@ -276,6 +279,9 @@ impl<S, T, A> Alpha<Hsl<S, T>, A> {
}
}

impl_reference_component_methods_hue!(Hsl<S>, [saturation, lightness], standard);
impl_struct_of_arrays_methods_hue!(Hsl<S>, [saturation, lightness], standard);

impl<S1, S2, T> FromColorUnclamped<Hsl<S1, T>> for Hsl<S2, T>
where
S1: RgbStandard + 'static,
Expand Down Expand Up @@ -628,6 +634,7 @@ impl_color_sub!(Hsl<S, T>, [hue, saturation, lightness], standard);

impl_array_casts!(Hsl<S, T>, [T; 3]);
impl_simd_array_conversion_hue!(Hsl<S>, [saturation, lightness], standard);
impl_struct_of_array_traits_hue!(Hsl<S>, RgbHueIter, [saturation, lightness], standard);

impl_eq_hue!(Hsl<S>, RgbHue, [hue, saturation, lightness]);

Expand Down Expand Up @@ -661,6 +668,7 @@ where
}
}

/// Sample HSL colors uniformly.
#[cfg(feature = "random")]
pub struct UniformHsl<S, T>
where
Expand Down Expand Up @@ -835,6 +843,24 @@ mod test {
assert_relative_eq!(Hsl::<Srgb>::max_lightness(), 1.0);
}

struct_of_arrays_tests!(
Hsl<Srgb>,
Hsl::new(0.1f32, 0.2, 0.3),
Hsl::new(0.2, 0.3, 0.4),
Hsl::new(0.3, 0.4, 0.5)
);

mod alpha {
use crate::{encoding::Srgb, hsl::Hsla};

struct_of_arrays_tests!(
Hsla<Srgb>,
Hsla::new(0.1f32, 0.2, 0.3, 0.4),
Hsla::new(0.2, 0.3, 0.4, 0.5),
Hsla::new(0.3, 0.4, 0.5, 0.6)
);
}

#[cfg(feature = "serializing")]
#[test]
fn serialize() {
Expand Down
26 changes: 26 additions & 0 deletions palette/src/hsluv.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Types for the HSLuv color space.
use core::{
marker::PhantomData,
ops::{Add, AddAssign, BitAnd, Sub, SubAssign},
Expand All @@ -23,6 +25,7 @@ use crate::{
bool_mask::{HasBoolMask, LazySelect},
clamp, clamp_assign, contrast_ratio,
convert::FromColorUnclamped,
hues::LuvHueIter,
luv_bounds::LuvBounds,
num::{
self, Arithmetics, FromScalarArray, IntoScalarArray, MinMax, One, PartialCmp, Powi, Real,
Expand Down Expand Up @@ -180,6 +183,9 @@ impl<Wp, T, A> Alpha<Hsluv<Wp, T>, A> {
}
}

impl_reference_component_methods_hue!(Hsluv<Wp>, [saturation, l], white_point);
impl_struct_of_arrays_methods_hue!(Hsluv<Wp>, [saturation, l], white_point);

impl<Wp, T> FromColorUnclamped<Hsluv<Wp, T>> for Hsluv<Wp, T> {
fn from_color_unclamped(hsluv: Hsluv<Wp, T>) -> Self {
hsluv
Expand Down Expand Up @@ -353,6 +359,7 @@ impl_color_sub!(Hsluv<Wp, T>, [hue, saturation, l], white_point);

impl_array_casts!(Hsluv<Wp, T>, [T; 3]);
impl_simd_array_conversion_hue!(Hsluv<Wp>, [saturation, l], white_point);
impl_struct_of_array_traits_hue!(Hsluv<Wp>, LuvHueIter, [saturation, l], white_point);

impl_eq_hue!(Hsluv<Wp>, LuvHue, [hue, saturation, l]);

Expand Down Expand Up @@ -385,6 +392,7 @@ where
}
}

/// Sample HSLuv colors uniformly.
#[cfg(feature = "random")]
pub struct UniformHsluv<Wp, T>
where
Expand Down Expand Up @@ -557,6 +565,24 @@ mod test {
assert_relative_eq!(Hsluv::<D65>::max_l(), 100.0);
}

struct_of_arrays_tests!(
Hsluv<D65>,
Hsluv::new(0.1f32, 0.2, 0.3),
Hsluv::new(0.2, 0.3, 0.4),
Hsluv::new(0.3, 0.4, 0.5)
);

mod alpha {
use crate::{hsluv::Hsluva, white_point::D65};

struct_of_arrays_tests!(
Hsluva<D65>,
Hsluva::new(0.1f32, 0.2, 0.3, 0.4),
Hsluva::new(0.2, 0.3, 0.4, 0.5),
Hsluva::new(0.3, 0.4, 0.5, 0.6)
);
}

#[cfg(feature = "serializing")]
#[test]
fn serialize() {
Expand Down
Loading

0 comments on commit da49fc0

Please sign in to comment.