use std::{
fmt::{Display, Formatter, Result as FmtResult},
marker::PhantomData,
ops::{Add, Div, Mul, Sub},
};
#[cfg(feature = "space-cmy")]
use crate::space::Cmy;
#[cfg(feature = "space-hpluv")]
use crate::space::Hpluv;
#[cfg(feature = "space-hsi")]
use crate::space::Hsi;
#[cfg(feature = "space-hsl")]
use crate::space::Hsl;
#[cfg(feature = "space-hsluv")]
use crate::space::Hsluv;
#[cfg(feature = "space-hsv")]
use crate::space::Hsv;
#[cfg(feature = "space-hwb")]
use crate::space::Hwb;
#[cfg(feature = "space-lab")]
use crate::space::Lab;
#[cfg(feature = "space-lch")]
use crate::space::Lch;
#[cfg(feature = "space-lchuv")]
use crate::space::Lchuv;
#[cfg(feature = "space-luv")]
use crate::space::Luv;
#[cfg(feature = "space-okhsl")]
use crate::space::Okhsl;
#[cfg(feature = "space-okhsv")]
use crate::space::Okhsv;
#[cfg(feature = "space-okhwb")]
use crate::space::Okhwb;
#[cfg(feature = "space-oklab")]
use crate::space::Oklab;
#[cfg(feature = "space-oklch")]
use crate::space::Oklch;
#[cfg(feature = "space-xyy")]
use crate::space::Xyy;
use crate::{
ColorimetricContext,
component::Component,
space::{ColorSpace, Lms, Rgb, RgbSpec, Srgb, Xyz},
};
#[derive(Clone, Copy, Debug)]
pub struct Cmyk<S = Srgb>
where
S: RgbSpec,
{
alpha: Component,
context: ColorimetricContext,
c: Component,
k: Component,
m: Component,
y: Component,
_spec: PhantomData<S>,
}
impl<S> Cmyk<S>
where
S: RgbSpec,
{
pub fn new(
c: impl Into<Component>,
m: impl Into<Component>,
y: impl Into<Component>,
k: impl Into<Component>,
) -> Self {
Self {
alpha: Component::new(1.0),
context: S::CONTEXT,
c: c.into() / 100.0,
k: k.into() / 100.0,
m: m.into() / 100.0,
y: y.into() / 100.0,
_spec: PhantomData,
}
}
pub const fn new_const(c: f64, m: f64, y: f64, k: f64) -> Self {
Self {
alpha: Component::new_const(1.0),
context: S::CONTEXT,
c: Component::new_const(c / 100.0),
k: Component::new_const(k / 100.0),
m: Component::new_const(m / 100.0),
y: Component::new_const(y / 100.0),
_spec: PhantomData,
}
}
pub fn black(&self) -> f64 {
self.k.0
}
pub fn c(&self) -> f64 {
self.c.0
}
pub fn components(&self) -> [f64; 4] {
[self.c.0, self.m.0, self.y.0, self.k.0]
}
pub fn context(&self) -> &ColorimetricContext {
&self.context
}
pub fn cyan(&self) -> f64 {
self.c.0 * 100.0
}
pub fn decrement_c(&mut self, amount: impl Into<Component>) {
self.c -= amount.into();
}
pub fn decrement_cyan(&mut self, amount: impl Into<Component>) {
self.decrement_c(amount.into() / 100.0)
}
pub fn decrement_k(&mut self, amount: impl Into<Component>) {
self.k -= amount.into();
}
pub fn decrement_key(&mut self, amount: impl Into<Component>) {
self.decrement_k(amount.into() / 100.0)
}
pub fn decrement_m(&mut self, amount: impl Into<Component>) {
self.m -= amount.into();
}
pub fn decrement_magenta(&mut self, amount: impl Into<Component>) {
self.decrement_m(amount.into() / 100.0)
}
pub fn decrement_y(&mut self, amount: impl Into<Component>) {
self.y -= amount.into();
}
pub fn decrement_yellow(&mut self, amount: impl Into<Component>) {
self.decrement_y(amount.into() / 100.0)
}
pub fn increment_c(&mut self, amount: impl Into<Component>) {
self.c += amount.into();
}
pub fn increment_cyan(&mut self, amount: impl Into<Component>) {
self.increment_c(amount.into() / 100.0)
}
pub fn increment_k(&mut self, amount: impl Into<Component>) {
self.k += amount.into();
}
pub fn increment_key(&mut self, amount: impl Into<Component>) {
self.increment_k(amount.into() / 100.0)
}
pub fn increment_m(&mut self, amount: impl Into<Component>) {
self.m += amount.into();
}
pub fn increment_magenta(&mut self, amount: impl Into<Component>) {
self.increment_m(amount.into() / 100.0)
}
pub fn increment_y(&mut self, amount: impl Into<Component>) {
self.y += amount.into();
}
pub fn increment_yellow(&mut self, amount: impl Into<Component>) {
self.increment_y(amount.into() / 100.0)
}
pub fn k(&self) -> f64 {
self.k.0
}
pub fn key(&self) -> f64 {
self.k.0 * 100.0
}
pub fn m(&self) -> f64 {
self.m.0
}
pub fn magenta(&self) -> f64 {
self.m.0 * 100.0
}
pub fn scale_c(&mut self, factor: impl Into<Component>) {
self.c *= factor.into();
}
pub fn scale_cyan(&mut self, factor: impl Into<Component>) {
self.scale_c(factor)
}
pub fn scale_k(&mut self, factor: impl Into<Component>) {
self.k *= factor.into();
}
pub fn scale_key(&mut self, factor: impl Into<Component>) {
self.scale_k(factor)
}
pub fn scale_m(&mut self, factor: impl Into<Component>) {
self.m *= factor.into();
}
pub fn scale_magenta(&mut self, factor: impl Into<Component>) {
self.scale_m(factor)
}
pub fn scale_y(&mut self, factor: impl Into<Component>) {
self.y *= factor.into();
}
pub fn scale_yellow(&mut self, factor: impl Into<Component>) {
self.scale_y(factor)
}
pub fn set_components(&mut self, components: [impl Into<Component> + Clone; 4]) {
self.set_c(components[0].clone());
self.set_m(components[1].clone());
self.set_y(components[2].clone());
self.set_k(components[3].clone());
}
pub fn set_c(&mut self, c: impl Into<Component>) {
self.c = c.into();
}
pub fn set_cyan(&mut self, cyan: impl Into<Component>) {
self.c = cyan.into() / 100.0;
}
pub fn set_k(&mut self, k: impl Into<Component>) {
self.k = k.into();
}
pub fn set_key(&mut self, key: impl Into<Component>) {
self.k = key.into() / 100.0;
}
pub fn set_m(&mut self, m: impl Into<Component>) {
self.m = m.into();
}
pub fn set_magenta(&mut self, magenta: impl Into<Component>) {
self.m = magenta.into() / 100.0;
}
pub fn set_y(&mut self, y: impl Into<Component>) {
self.y = y.into();
}
pub fn set_yellow(&mut self, yellow: impl Into<Component>) {
self.y = yellow.into() / 100.0;
}
#[cfg(feature = "space-cmy")]
pub fn to_cmy<OS>(&self) -> Cmy<OS>
where
OS: RgbSpec,
{
let nc = self.c.0;
let nm = self.m.0;
let ny = self.y.0;
let nk = self.k.0;
Cmy::<OS>::new(
((nc * (1.0 - nk)) + nk) * 100.0,
((nm * (1.0 - nk)) + nk) * 100.0,
((ny * (1.0 - nk)) + nk) * 100.0,
)
.with_alpha(self.alpha)
}
pub fn to_rgb<OS>(&self) -> Rgb<OS>
where
OS: RgbSpec,
{
let nc = self.c.0;
let nm = self.m.0;
let ny = self.y.0;
let nk = self.k.0;
Rgb::<S>::from_normalized(
(1.0 - nc) * (1.0 - nk),
(1.0 - nm) * (1.0 - nk),
(1.0 - ny) * (1.0 - nk),
)
.to_rgb::<OS>()
.with_alpha(self.alpha)
}
pub fn with_context(&self, context: ColorimetricContext) -> Self {
Self {
context,
..*self
}
}
pub fn with_c(&self, c: impl Into<Component>) -> Self {
Self {
c: c.into(),
..*self
}
}
pub fn with_c_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_c(amount);
cmyk
}
pub fn with_c_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_c(amount);
cmyk
}
pub fn with_c_scaled_by(&self, factor: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.scale_c(factor);
cmyk
}
pub fn with_cyan(&self, cyan: impl Into<Component>) -> Self {
Self {
c: cyan.into() / 100.0,
..*self
}
}
pub fn with_cyan_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_cyan(amount);
cmyk
}
pub fn with_cyan_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_cyan(amount);
cmyk
}
pub fn with_cyan_scaled_by(&self, factor: impl Into<Component>) -> Self {
self.with_c_scaled_by(factor)
}
pub fn with_k(&self, k: impl Into<Component>) -> Self {
Self {
k: k.into(),
..*self
}
}
pub fn with_k_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_k(amount);
cmyk
}
pub fn with_k_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_k(amount);
cmyk
}
pub fn with_k_scaled_by(&self, factor: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.scale_k(factor);
cmyk
}
pub fn with_key(&self, key: impl Into<Component>) -> Self {
Self {
k: key.into() / 100.0,
..*self
}
}
pub fn with_key_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_key(amount);
cmyk
}
pub fn with_key_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_key(amount);
cmyk
}
pub fn with_key_scaled_by(&self, factor: impl Into<Component>) -> Self {
self.with_k_scaled_by(factor)
}
pub fn with_m(&self, m: impl Into<Component>) -> Self {
Self {
m: m.into(),
..*self
}
}
pub fn with_m_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_m(amount);
cmyk
}
pub fn with_m_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_m(amount);
cmyk
}
pub fn with_m_scaled_by(&self, factor: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.scale_m(factor);
cmyk
}
pub fn with_magenta(&self, magenta: impl Into<Component>) -> Self {
Self {
m: magenta.into() / 100.0,
..*self
}
}
pub fn with_magenta_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_magenta(amount);
cmyk
}
pub fn with_magenta_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_magenta(amount);
cmyk
}
pub fn with_magenta_scaled_by(&self, factor: impl Into<Component>) -> Self {
self.with_m_scaled_by(factor)
}
pub fn with_y(&self, y: impl Into<Component>) -> Self {
Self {
y: y.into(),
..*self
}
}
pub fn with_y_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_y(amount);
cmyk
}
pub fn with_y_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_y(amount);
cmyk
}
pub fn with_y_scaled_by(&self, factor: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.scale_y(factor);
cmyk
}
pub fn with_yellow(&self, yellow: impl Into<Component>) -> Self {
Self {
y: yellow.into() / 100.0,
..*self
}
}
pub fn with_yellow_decremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.decrement_yellow(amount);
cmyk
}
pub fn with_yellow_incremented_by(&self, amount: impl Into<Component>) -> Self {
let mut cmyk = *self;
cmyk.increment_yellow(amount);
cmyk
}
pub fn with_yellow_scaled_by(&self, factor: impl Into<Component>) -> Self {
self.with_y_scaled_by(factor)
}
pub fn y(&self) -> f64 {
self.y.0
}
pub fn yellow(&self) -> f64 {
self.y.0 * 100.0
}
}
impl<S, T> Add<T> for Cmyk<S>
where
S: RgbSpec,
T: Into<Self>,
{
type Output = Self;
fn add(self, rhs: T) -> Self {
Self::from(self.to_rgb::<S>() + rhs.into().to_rgb::<S>())
}
}
impl<S> ColorSpace<4> for Cmyk<S>
where
S: RgbSpec,
{
fn alpha(&self) -> f64 {
self.alpha.0
}
fn components(&self) -> [f64; 4] {
self.components()
}
fn set_alpha(&mut self, alpha: impl Into<Component>) {
self.alpha = alpha.into().clamp(0.0, 1.0);
}
fn set_components(&mut self, components: [impl Into<Component> + Clone; 4]) {
self.set_components(components)
}
fn to_xyz(&self) -> Xyz {
self.to_rgb::<S>().to_xyz()
}
}
#[cfg(feature = "serde")]
impl<'de, S> serde::Deserialize<'de> for Cmyk<S>
where
S: RgbSpec,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(serde::Deserialize)]
struct CmykData {
c: Component,
m: Component,
y: Component,
k: Component,
#[serde(default = "crate::component::default_alpha")]
alpha: Component,
}
let data = CmykData::deserialize(deserializer)?;
Ok(Self {
c: data.c,
m: data.m,
y: data.y,
k: data.k,
alpha: data.alpha,
context: S::CONTEXT,
_spec: PhantomData,
})
}
}
impl<S> Display for Cmyk<S>
where
S: RgbSpec,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let precision = f.precision().unwrap_or(2);
if self.alpha.0 < 1.0 {
write!(
f,
"CMYK({:.precision$}%, {:.precision$}%, {:.precision$}%, {:.precision$}%, {:.0}%)",
self.cyan(),
self.magenta(),
self.yellow(),
self.key(),
self.opacity()
)
} else {
write!(
f,
"CMYK({:.precision$}%, {:.precision$}%, {:.precision$}%, {:.precision$}%)",
self.cyan(),
self.magenta(),
self.yellow(),
self.key()
)
}
}
}
impl<S, T> Div<T> for Cmyk<S>
where
S: RgbSpec,
T: Into<Self>,
{
type Output = Self;
fn div(self, rhs: T) -> Self {
Self::from(self.to_rgb::<S>() / rhs.into().to_rgb::<S>())
}
}
impl<S, T> From<[T; 4]> for Cmyk<S>
where
S: RgbSpec,
T: Into<Component>,
{
fn from([c, m, y, k]: [T; 4]) -> Self {
Self::new(c, m, y, k)
}
}
#[cfg(feature = "space-cmy")]
impl<OS, S> From<Cmy<OS>> for Cmyk<S>
where
OS: RgbSpec,
S: RgbSpec,
{
fn from(cmy: Cmy<OS>) -> Self {
cmy.to_cmyk()
}
}
#[cfg(feature = "space-hpluv")]
impl<S> From<Hpluv> for Cmyk<S>
where
S: RgbSpec,
{
fn from(hpluv: Hpluv) -> Self {
hpluv.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-hsi")]
impl<OS, S> From<Hsi<OS>> for Cmyk<S>
where
OS: RgbSpec,
S: RgbSpec,
{
fn from(hsi: Hsi<OS>) -> Self {
hsi.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-hsl")]
impl<OS, S> From<Hsl<OS>> for Cmyk<S>
where
OS: RgbSpec,
S: RgbSpec,
{
fn from(hsl: Hsl<OS>) -> Self {
hsl.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-hsluv")]
impl<S> From<Hsluv> for Cmyk<S>
where
S: RgbSpec,
{
fn from(hsluv: Hsluv) -> Self {
hsluv.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-hsv")]
impl<OS, S> From<Hsv<OS>> for Cmyk<S>
where
OS: RgbSpec,
S: RgbSpec,
{
fn from(hsv: Hsv<OS>) -> Self {
hsv.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-hwb")]
impl<OS, S> From<Hwb<OS>> for Cmyk<S>
where
OS: RgbSpec,
S: RgbSpec,
{
fn from(hwb: Hwb<OS>) -> Self {
hwb.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-lab")]
impl<S> From<Lab> for Cmyk<S>
where
S: RgbSpec,
{
fn from(lab: Lab) -> Self {
lab.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-lch")]
impl<S> From<Lch> for Cmyk<S>
where
S: RgbSpec,
{
fn from(lch: Lch) -> Self {
lch.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-lchuv")]
impl<S> From<Lchuv> for Cmyk<S>
where
S: RgbSpec,
{
fn from(lchuv: Lchuv) -> Self {
lchuv.to_rgb::<S>().to_cmyk()
}
}
impl<S> From<Lms> for Cmyk<S>
where
S: RgbSpec,
{
fn from(lms: Lms) -> Self {
lms.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-luv")]
impl<S> From<Luv> for Cmyk<S>
where
S: RgbSpec,
{
fn from(luv: Luv) -> Self {
luv.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-okhsl")]
impl<S> From<Okhsl> for Cmyk<S>
where
S: RgbSpec,
{
fn from(okhsl: Okhsl) -> Self {
okhsl.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-okhsv")]
impl<S> From<Okhsv> for Cmyk<S>
where
S: RgbSpec,
{
fn from(okhsv: Okhsv) -> Self {
okhsv.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-okhwb")]
impl<S> From<Okhwb> for Cmyk<S>
where
S: RgbSpec,
{
fn from(okhwb: Okhwb) -> Self {
okhwb.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-oklab")]
impl<S> From<Oklab> for Cmyk<S>
where
S: RgbSpec,
{
fn from(oklab: Oklab) -> Self {
oklab.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-oklch")]
impl<S> From<Oklch> for Cmyk<S>
where
S: RgbSpec,
{
fn from(oklch: Oklch) -> Self {
oklch.to_rgb::<S>().to_cmyk()
}
}
impl<OS, S> From<Rgb<OS>> for Cmyk<S>
where
OS: RgbSpec,
S: RgbSpec,
{
fn from(rgb: Rgb<OS>) -> Self {
rgb.to_rgb::<S>().to_cmyk()
}
}
#[cfg(feature = "space-xyy")]
impl<S> From<Xyy> for Cmyk<S>
where
S: RgbSpec,
{
fn from(xyy: Xyy) -> Self {
xyy.to_rgb::<S>().to_cmyk()
}
}
impl<S> From<Xyz> for Cmyk<S>
where
S: RgbSpec,
{
fn from(xyz: Xyz) -> Self {
xyz.to_rgb::<S>().to_cmyk()
}
}
impl<S, T> Mul<T> for Cmyk<S>
where
S: RgbSpec,
T: Into<Self>,
{
type Output = Self;
fn mul(self, rhs: T) -> Self {
Self::from(self.to_rgb::<S>() * rhs.into().to_rgb::<S>())
}
}
impl<S, T> PartialEq<T> for Cmyk<S>
where
S: RgbSpec,
T: Into<Cmyk<S>> + Copy,
{
fn eq(&self, other: &T) -> bool {
let other = (*other).into();
self.alpha == other.alpha && self.c == other.c && self.m == other.m && self.y == other.y && self.k == other.k
}
}
#[cfg(feature = "serde")]
impl<S> serde::Serialize for Cmyk<S>
where
S: RgbSpec,
{
fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
use serde::ser::SerializeStruct;
let field_count = if self.alpha.0 < 1.0 { 5 } else { 4 };
let mut state = serializer.serialize_struct("Cmyk", field_count)?;
state.serialize_field("c", &self.c)?;
state.serialize_field("m", &self.m)?;
state.serialize_field("y", &self.y)?;
state.serialize_field("k", &self.k)?;
if self.alpha.0 < 1.0 {
state.serialize_field("alpha", &self.alpha)?;
}
state.end()
}
}
impl<S, T> Sub<T> for Cmyk<S>
where
S: RgbSpec,
T: Into<Self>,
{
type Output = Self;
fn sub(self, rhs: T) -> Self {
Self::from(self.to_rgb::<S>() - rhs.into().to_rgb::<S>())
}
}
#[cfg(test)]
mod test {
use super::*;
mod add {
use super::*;
#[test]
fn it_adds_two_cmyk_values_via_rgb() {
let a = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let b = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let result = a + b;
assert!(result.c().is_finite());
assert!(result.m().is_finite());
assert!(result.y().is_finite());
assert!(result.k().is_finite());
}
}
mod decrement_c {
use super::*;
#[test]
fn it_subtracts_from_c() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
cmyk.decrement_c(0.2);
assert!((cmyk.c() - 0.3).abs() < 1e-10);
}
}
mod decrement_cyan {
use super::*;
#[test]
fn it_subtracts_percentage_from_cyan() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
cmyk.decrement_cyan(20.0);
assert!((cmyk.cyan() - 30.0).abs() < 1e-10);
}
}
mod decrement_k {
use super::*;
#[test]
fn it_subtracts_from_k() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 50.0);
cmyk.decrement_k(0.2);
assert!((cmyk.k() - 0.3).abs() < 1e-10);
}
}
mod decrement_key {
use super::*;
#[test]
fn it_subtracts_percentage_from_key() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 50.0);
cmyk.decrement_key(20.0);
assert!((cmyk.key() - 30.0).abs() < 1e-10);
}
}
mod decrement_m {
use super::*;
#[test]
fn it_subtracts_from_m() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
cmyk.decrement_m(0.2);
assert!((cmyk.m() - 0.3).abs() < 1e-10);
}
}
mod decrement_magenta {
use super::*;
#[test]
fn it_subtracts_percentage_from_magenta() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
cmyk.decrement_magenta(20.0);
assert!((cmyk.magenta() - 30.0).abs() < 1e-10);
}
}
mod decrement_y {
use super::*;
#[test]
fn it_subtracts_from_y() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
cmyk.decrement_y(0.2);
assert!((cmyk.y() - 0.3).abs() < 1e-10);
}
}
mod decrement_yellow {
use super::*;
#[test]
fn it_subtracts_percentage_from_yellow() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
cmyk.decrement_yellow(20.0);
assert!((cmyk.yellow() - 30.0).abs() < 1e-10);
}
}
mod display {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_formats_with_default_precision() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
assert_eq!(format!("{}", cmyk), "CMYK(25.00%, 50.00%, 75.00%, 10.00%)");
}
#[test]
fn it_formats_with_custom_precision() {
let cmyk = Cmyk::<Srgb>::new(25.6789, 50.1234, 75.4321, 10.5678);
assert_eq!(format!("{:.4}", cmyk), "CMYK(25.6789%, 50.1234%, 75.4321%, 10.5678%)");
}
#[test]
fn it_includes_opacity_when_alpha_below_one() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0).with_alpha(0.5);
assert_eq!(format!("{}", cmyk), "CMYK(25.00%, 50.00%, 75.00%, 10.00%, 50%)");
}
#[test]
fn it_omits_opacity_when_fully_opaque() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
assert_eq!(format!("{}", cmyk), "CMYK(25.00%, 50.00%, 75.00%, 10.00%)");
}
}
mod div {
use super::*;
#[test]
fn it_divides_two_cmyk_values_via_rgb() {
let a = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let b = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let result = a / b;
assert!(result.c().is_finite());
assert!(result.m().is_finite());
assert!(result.y().is_finite());
assert!(result.k().is_finite());
}
}
#[cfg(feature = "space-cmy")]
mod from_cmy {
use super::*;
#[test]
fn it_converts_via_rgb() {
let cmy = Cmy::<Srgb>::new(100.0, 0.0, 100.0);
let cmyk: Cmyk<Srgb> = cmy.into();
assert!(cmyk.c().is_finite());
assert!(cmyk.m().is_finite());
assert!(cmyk.y().is_finite());
assert!(cmyk.k().is_finite());
}
}
#[cfg(feature = "space-hsl")]
mod from_hsl {
use super::*;
#[test]
fn it_converts_via_rgb() {
let hsl = Hsl::<Srgb>::new(120.0, 100.0, 50.0);
let cmyk: Cmyk<Srgb> = hsl.into();
assert!(cmyk.c().is_finite());
assert!(cmyk.m().is_finite());
assert!(cmyk.y().is_finite());
assert!(cmyk.k().is_finite());
}
}
#[cfg(feature = "space-hsv")]
mod from_hsv {
use super::*;
#[test]
fn it_converts_via_rgb() {
let hsv = Hsv::<Srgb>::new(120.0, 100.0, 100.0);
let cmyk: Cmyk<Srgb> = hsv.into();
assert!(cmyk.c().is_finite());
assert!(cmyk.m().is_finite());
assert!(cmyk.y().is_finite());
assert!(cmyk.k().is_finite());
}
}
#[cfg(feature = "space-hwb")]
mod from_hwb {
use super::*;
#[test]
fn it_converts_via_rgb() {
let hwb = Hwb::<Srgb>::new(120.0, 0.0, 0.0);
let cmyk: Cmyk<Srgb> = hwb.into();
assert!(cmyk.c().is_finite());
assert!(cmyk.m().is_finite());
assert!(cmyk.y().is_finite());
assert!(cmyk.k().is_finite());
}
}
mod from_lms {
use super::*;
#[test]
fn it_converts_from_lms_via_rgb() {
let lms = Lms::new(0.5, 0.5, 0.5);
let cmyk: Cmyk<Srgb> = lms.into();
assert!(cmyk.c().is_finite());
assert!(cmyk.m().is_finite());
assert!(cmyk.y().is_finite());
assert!(cmyk.k().is_finite());
}
}
mod from_rgb {
use super::*;
#[test]
fn it_converts_pure_red() {
let rgb = Rgb::<Srgb>::from_normalized(1.0, 0.0, 0.0);
let cmyk: Cmyk<Srgb> = rgb.into();
assert!((cmyk.cyan()).abs() < 1e-10);
assert!((cmyk.magenta() - 100.0).abs() < 1e-10);
assert!((cmyk.yellow() - 100.0).abs() < 1e-10);
assert!((cmyk.key()).abs() < 1e-10);
}
#[test]
fn it_converts_pure_green() {
let rgb = Rgb::<Srgb>::from_normalized(0.0, 1.0, 0.0);
let cmyk: Cmyk<Srgb> = rgb.into();
assert!((cmyk.cyan() - 100.0).abs() < 1e-10);
assert!((cmyk.magenta()).abs() < 1e-10);
assert!((cmyk.yellow() - 100.0).abs() < 1e-10);
assert!((cmyk.key()).abs() < 1e-10);
}
#[test]
fn it_converts_pure_blue() {
let rgb = Rgb::<Srgb>::from_normalized(0.0, 0.0, 1.0);
let cmyk: Cmyk<Srgb> = rgb.into();
assert!((cmyk.cyan() - 100.0).abs() < 1e-10);
assert!((cmyk.magenta() - 100.0).abs() < 1e-10);
assert!((cmyk.yellow()).abs() < 1e-10);
assert!((cmyk.key()).abs() < 1e-10);
}
#[test]
fn it_converts_white() {
let rgb = Rgb::<Srgb>::from_normalized(1.0, 1.0, 1.0);
let cmyk: Cmyk<Srgb> = rgb.into();
assert!((cmyk.cyan()).abs() < 1e-10);
assert!((cmyk.magenta()).abs() < 1e-10);
assert!((cmyk.yellow()).abs() < 1e-10);
assert!((cmyk.key()).abs() < 1e-10);
}
#[test]
fn it_converts_black() {
let rgb = Rgb::<Srgb>::from_normalized(0.0, 0.0, 0.0);
let cmyk: Cmyk<Srgb> = rgb.into();
assert!((cmyk.cyan()).abs() < 1e-10);
assert!((cmyk.magenta()).abs() < 1e-10);
assert!((cmyk.yellow()).abs() < 1e-10);
assert!((cmyk.key() - 100.0).abs() < 1e-10);
}
#[test]
fn it_converts_gray_50_percent() {
let rgb = Rgb::<Srgb>::from_normalized(0.5, 0.5, 0.5);
let cmyk: Cmyk<Srgb> = rgb.into();
assert!((cmyk.cyan()).abs() < 1e-10);
assert!((cmyk.magenta()).abs() < 1e-10);
assert!((cmyk.yellow()).abs() < 1e-10);
assert!((cmyk.key() - 50.0).abs() < 1e-10);
}
}
mod from_xyz {
use super::*;
#[test]
fn it_converts_from_xyz_via_rgb() {
let xyz = Xyz::new(0.5, 0.5, 0.5);
let cmyk: Cmyk<Srgb> = xyz.into();
assert!(cmyk.c().is_finite());
assert!(cmyk.m().is_finite());
assert!(cmyk.y().is_finite());
assert!(cmyk.k().is_finite());
}
}
mod increment_c {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_adds_to_c() {
let mut cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 0.0);
cmyk.increment_c(0.25);
assert_eq!(cmyk.c(), 0.5);
}
}
mod increment_cyan {
use super::*;
#[test]
fn it_adds_percentage_to_cyan() {
let mut cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 0.0);
cmyk.increment_cyan(25.0);
assert!((cmyk.cyan() - 50.0).abs() < 1e-10);
}
}
mod increment_k {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_adds_to_k() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 25.0);
cmyk.increment_k(0.25);
assert_eq!(cmyk.k(), 0.5);
}
}
mod increment_key {
use super::*;
#[test]
fn it_adds_percentage_to_key() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 25.0);
cmyk.increment_key(25.0);
assert!((cmyk.key() - 50.0).abs() < 1e-10);
}
}
mod increment_m {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_adds_to_m() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 0.0);
cmyk.increment_m(0.25);
assert_eq!(cmyk.m(), 0.5);
}
}
mod increment_magenta {
use super::*;
#[test]
fn it_adds_percentage_to_magenta() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 0.0);
cmyk.increment_magenta(25.0);
assert!((cmyk.magenta() - 50.0).abs() < 1e-10);
}
}
mod increment_y {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_adds_to_y() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 0.0);
cmyk.increment_y(0.25);
assert_eq!(cmyk.y(), 0.5);
}
}
mod increment_yellow {
use super::*;
#[test]
fn it_adds_percentage_to_yellow() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 0.0);
cmyk.increment_yellow(25.0);
assert!((cmyk.yellow() - 50.0).abs() < 1e-10);
}
}
mod mul {
use super::*;
#[test]
fn it_multiplies_two_cmyk_values_via_rgb() {
let a = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let b = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let result = a * b;
assert!(result.c().is_finite());
assert!(result.m().is_finite());
assert!(result.y().is_finite());
assert!(result.k().is_finite());
}
}
mod new_const {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_normalizes_cyan_to_0_1() {
const CMYK: Cmyk<Srgb> = Cmyk::new_const(75.0, 50.0, 25.0, 10.0);
assert_eq!(CMYK.c(), 0.75);
}
#[test]
fn it_normalizes_magenta_to_0_1() {
const CMYK: Cmyk<Srgb> = Cmyk::new_const(50.0, 75.0, 25.0, 10.0);
assert_eq!(CMYK.m(), 0.75);
}
#[test]
fn it_normalizes_yellow_to_0_1() {
const CMYK: Cmyk<Srgb> = Cmyk::new_const(50.0, 25.0, 75.0, 10.0);
assert_eq!(CMYK.y(), 0.75);
}
#[test]
fn it_normalizes_key_to_0_1() {
const CMYK: Cmyk<Srgb> = Cmyk::new_const(50.0, 25.0, 10.0, 75.0);
assert_eq!(CMYK.k(), 0.75);
}
}
mod partial_eq {
use pretty_assertions::{assert_eq, assert_ne};
use super::*;
#[test]
fn it_compares_equal_cmyk_values() {
let a = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let b = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
assert_eq!(a, b);
}
#[test]
fn it_compares_unequal_cmyk_values() {
let a = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let b = Cmyk::<Srgb>::new(25.0, 50.0, 80.0, 10.0);
assert_ne!(a, b);
}
#[test]
fn it_compares_unequal_when_alpha_differs() {
let a = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0).with_alpha(0.5);
let b = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
assert_ne!(a, b);
}
}
mod scale_c {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_multiplies_c_by_factor() {
let mut cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 0.0);
cmyk.scale_c(2.0);
assert_eq!(cmyk.c(), 0.5);
}
}
mod scale_k {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_multiplies_k_by_factor() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 25.0);
cmyk.scale_k(2.0);
assert_eq!(cmyk.k(), 0.5);
}
}
mod scale_m {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_multiplies_m_by_factor() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 0.0);
cmyk.scale_m(2.0);
assert_eq!(cmyk.m(), 0.5);
}
}
mod scale_y {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_multiplies_y_by_factor() {
let mut cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 0.0);
cmyk.scale_y(2.0);
assert_eq!(cmyk.y(), 0.5);
}
}
mod sub {
use super::*;
#[test]
fn it_subtracts_two_cmyk_values_via_rgb() {
let a = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 10.0);
let b = Cmyk::<Srgb>::new(25.0, 25.0, 25.0, 5.0);
let result = a - b;
assert!(result.c().is_finite());
assert!(result.m().is_finite());
assert!(result.y().is_finite());
assert!(result.k().is_finite());
}
}
#[cfg(feature = "space-cmy")]
mod to_cmy {
use super::*;
#[test]
fn it_converts_pure_cyan() {
let cmyk = Cmyk::<Srgb>::new(100.0, 0.0, 0.0, 0.0);
let cmy: Cmy<Srgb> = cmyk.to_cmy();
assert!((cmy.cyan() - 100.0).abs() < 1e-10);
assert!((cmy.magenta()).abs() < 1e-10);
assert!((cmy.yellow()).abs() < 1e-10);
}
#[test]
fn it_converts_with_key() {
let cmyk = Cmyk::<Srgb>::new(0.0, 0.0, 0.0, 50.0);
let cmy: Cmy<Srgb> = cmyk.to_cmy();
assert!((cmy.cyan() - 50.0).abs() < 1e-10);
assert!((cmy.magenta() - 50.0).abs() < 1e-10);
assert!((cmy.yellow() - 50.0).abs() < 1e-10);
}
#[test]
fn it_converts_full_black() {
let cmyk = Cmyk::<Srgb>::new(0.0, 0.0, 0.0, 100.0);
let cmy: Cmy<Srgb> = cmyk.to_cmy();
assert!((cmy.cyan() - 100.0).abs() < 1e-10);
assert!((cmy.magenta() - 100.0).abs() < 1e-10);
assert!((cmy.yellow() - 100.0).abs() < 1e-10);
}
#[test]
fn it_roundtrips_preserving_color() {
let original = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let cmy: Cmy<Srgb> = original.to_cmy();
let back: Cmyk<Srgb> = cmy.into();
let original_rgb: Rgb<Srgb> = original.to_rgb();
let back_rgb: Rgb<Srgb> = back.to_rgb();
assert_eq!(original_rgb.red(), back_rgb.red());
assert_eq!(original_rgb.green(), back_rgb.green());
assert_eq!(original_rgb.blue(), back_rgb.blue());
}
}
mod to_rgb {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_converts_pure_cyan() {
let cmyk = Cmyk::<Srgb>::new(100.0, 0.0, 0.0, 0.0);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert_eq!(rgb.red(), 0);
assert_eq!(rgb.green(), 255);
assert_eq!(rgb.blue(), 255);
}
#[test]
fn it_converts_pure_magenta() {
let cmyk = Cmyk::<Srgb>::new(0.0, 100.0, 0.0, 0.0);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert_eq!(rgb.red(), 255);
assert_eq!(rgb.green(), 0);
assert_eq!(rgb.blue(), 255);
}
#[test]
fn it_converts_pure_yellow() {
let cmyk = Cmyk::<Srgb>::new(0.0, 0.0, 100.0, 0.0);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert_eq!(rgb.red(), 255);
assert_eq!(rgb.green(), 255);
assert_eq!(rgb.blue(), 0);
}
#[test]
fn it_converts_white() {
let cmyk = Cmyk::<Srgb>::new(0.0, 0.0, 0.0, 0.0);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert_eq!(rgb.red(), 255);
assert_eq!(rgb.green(), 255);
assert_eq!(rgb.blue(), 255);
}
#[test]
fn it_converts_black() {
let cmyk = Cmyk::<Srgb>::new(0.0, 0.0, 0.0, 100.0);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert_eq!(rgb.red(), 0);
assert_eq!(rgb.green(), 0);
assert_eq!(rgb.blue(), 0);
}
#[test]
fn it_converts_with_key() {
let cmyk = Cmyk::<Srgb>::new(0.0, 0.0, 0.0, 50.0);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert_eq!(rgb.red(), rgb.green());
assert_eq!(rgb.green(), rgb.blue());
}
#[test]
fn it_roundtrips_preserving_color() {
let original = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let rgb: Rgb<Srgb> = original.to_rgb();
let back: Cmyk<Srgb> = rgb.into();
let back_rgb: Rgb<Srgb> = back.to_rgb();
assert_eq!(rgb.red(), back_rgb.red());
assert_eq!(rgb.green(), back_rgb.green());
assert_eq!(rgb.blue(), back_rgb.blue());
}
#[test]
fn it_preserves_alpha() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0).with_alpha(0.3);
let rgb: Rgb<Srgb> = cmyk.to_rgb();
assert!((rgb.alpha() - 0.3).abs() < 1e-10);
}
}
mod to_xyz {
use super::*;
#[test]
fn it_converts_to_xyz_via_rgb() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let xyz = cmyk.to_xyz();
assert!(xyz.x().is_finite());
assert!(xyz.y().is_finite());
assert!(xyz.z().is_finite());
}
#[test]
fn it_roundtrips_preserving_color() {
let original = Cmyk::<Srgb>::new(25.0, 50.0, 75.0, 10.0);
let xyz = original.to_xyz();
let back: Cmyk<Srgb> = xyz.into();
let original_rgb: Rgb<Srgb> = original.to_rgb();
let back_rgb: Rgb<Srgb> = back.to_rgb();
assert_eq!(original_rgb.red(), back_rgb.red());
assert_eq!(original_rgb.green(), back_rgb.green());
assert_eq!(original_rgb.blue(), back_rgb.blue());
}
}
mod with_c {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_new_c() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 10.0);
let result = cmyk.with_c(0.75);
assert_eq!(result.c(), 0.75);
assert_eq!(result.m(), cmyk.m());
assert_eq!(result.y(), cmyk.y());
assert_eq!(result.k(), cmyk.k());
}
}
mod with_c_decremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_c() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
let result = cmyk.with_c_decremented_by(0.2);
assert!((result.c() - 0.3).abs() < 1e-10);
assert_eq!(cmyk.c(), 0.5);
}
}
mod with_c_incremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_c() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 0.0);
let result = cmyk.with_c_incremented_by(0.25);
assert_eq!(result.c(), 0.5);
}
}
mod with_c_scaled_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_scaled_c() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 0.0);
let result = cmyk.with_c_scaled_by(2.0);
assert_eq!(result.c(), 0.5);
}
}
mod with_cyan {
use super::*;
#[test]
fn it_returns_cmyk_with_new_cyan_in_percent() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 10.0);
let result = cmyk.with_cyan(75.0);
assert!((result.cyan() - 75.0).abs() < 1e-10);
assert_eq!(result.m(), cmyk.m());
assert_eq!(result.y(), cmyk.y());
assert_eq!(result.k(), cmyk.k());
}
}
mod with_cyan_decremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_cyan() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
let result = cmyk.with_cyan_decremented_by(20.0);
assert!((result.cyan() - 30.0).abs() < 1e-10);
}
}
mod with_cyan_incremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_cyan() {
let cmyk = Cmyk::<Srgb>::new(25.0, 50.0, 50.0, 0.0);
let result = cmyk.with_cyan_incremented_by(25.0);
assert!((result.cyan() - 50.0).abs() < 1e-10);
}
}
mod with_k {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_new_k() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 10.0);
let result = cmyk.with_k(0.75);
assert_eq!(result.k(), 0.75);
assert_eq!(result.c(), cmyk.c());
assert_eq!(result.m(), cmyk.m());
assert_eq!(result.y(), cmyk.y());
}
}
mod with_k_decremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_k() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 50.0);
let result = cmyk.with_k_decremented_by(0.2);
assert!((result.k() - 0.3).abs() < 1e-10);
assert_eq!(cmyk.k(), 0.5);
}
}
mod with_k_incremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_k() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 25.0);
let result = cmyk.with_k_incremented_by(0.25);
assert_eq!(result.k(), 0.5);
}
}
mod with_k_scaled_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_scaled_k() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 25.0);
let result = cmyk.with_k_scaled_by(2.0);
assert_eq!(result.k(), 0.5);
}
}
mod with_key {
use super::*;
#[test]
fn it_returns_cmyk_with_new_key_in_percent() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 10.0);
let result = cmyk.with_key(75.0);
assert!((result.key() - 75.0).abs() < 1e-10);
assert_eq!(result.c(), cmyk.c());
assert_eq!(result.m(), cmyk.m());
assert_eq!(result.y(), cmyk.y());
}
}
mod with_key_decremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_key() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 50.0);
let result = cmyk.with_key_decremented_by(20.0);
assert!((result.key() - 30.0).abs() < 1e-10);
}
}
mod with_key_incremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_key() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 25.0);
let result = cmyk.with_key_incremented_by(25.0);
assert!((result.key() - 50.0).abs() < 1e-10);
}
}
mod with_m {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_new_m() {
let cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 10.0);
let result = cmyk.with_m(0.75);
assert_eq!(result.m(), 0.75);
assert_eq!(result.c(), cmyk.c());
assert_eq!(result.y(), cmyk.y());
assert_eq!(result.k(), cmyk.k());
}
}
mod with_m_decremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_m() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
let result = cmyk.with_m_decremented_by(0.2);
assert!((result.m() - 0.3).abs() < 1e-10);
assert_eq!(cmyk.m(), 0.5);
}
}
mod with_m_incremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_m() {
let cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 0.0);
let result = cmyk.with_m_incremented_by(0.25);
assert_eq!(result.m(), 0.5);
}
}
mod with_m_scaled_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_scaled_m() {
let cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 0.0);
let result = cmyk.with_m_scaled_by(2.0);
assert_eq!(result.m(), 0.5);
}
}
mod with_magenta {
use super::*;
#[test]
fn it_returns_cmyk_with_new_magenta_in_percent() {
let cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 10.0);
let result = cmyk.with_magenta(75.0);
assert!((result.magenta() - 75.0).abs() < 1e-10);
assert_eq!(result.c(), cmyk.c());
assert_eq!(result.y(), cmyk.y());
assert_eq!(result.k(), cmyk.k());
}
}
mod with_magenta_decremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_magenta() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
let result = cmyk.with_magenta_decremented_by(20.0);
assert!((result.magenta() - 30.0).abs() < 1e-10);
}
}
mod with_magenta_incremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_magenta() {
let cmyk = Cmyk::<Srgb>::new(50.0, 25.0, 50.0, 0.0);
let result = cmyk.with_magenta_incremented_by(25.0);
assert!((result.magenta() - 50.0).abs() < 1e-10);
}
}
mod with_y {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_new_y() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 10.0);
let result = cmyk.with_y(0.75);
assert_eq!(result.y(), 0.75);
assert_eq!(result.c(), cmyk.c());
assert_eq!(result.m(), cmyk.m());
assert_eq!(result.k(), cmyk.k());
}
}
mod with_y_decremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_y() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
let result = cmyk.with_y_decremented_by(0.2);
assert!((result.y() - 0.3).abs() < 1e-10);
assert_eq!(cmyk.y(), 0.5);
}
}
mod with_y_incremented_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_y() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 0.0);
let result = cmyk.with_y_incremented_by(0.25);
assert_eq!(result.y(), 0.5);
}
}
mod with_y_scaled_by {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn it_returns_cmyk_with_scaled_y() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 0.0);
let result = cmyk.with_y_scaled_by(2.0);
assert_eq!(result.y(), 0.5);
}
}
mod with_yellow {
use super::*;
#[test]
fn it_returns_cmyk_with_new_yellow_in_percent() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 10.0);
let result = cmyk.with_yellow(75.0);
assert!((result.yellow() - 75.0).abs() < 1e-10);
assert_eq!(result.c(), cmyk.c());
assert_eq!(result.m(), cmyk.m());
assert_eq!(result.k(), cmyk.k());
}
}
mod with_yellow_decremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_decremented_yellow() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 50.0, 0.0);
let result = cmyk.with_yellow_decremented_by(20.0);
assert!((result.yellow() - 30.0).abs() < 1e-10);
}
}
mod with_yellow_incremented_by {
use super::*;
#[test]
fn it_returns_cmyk_with_incremented_yellow() {
let cmyk = Cmyk::<Srgb>::new(50.0, 50.0, 25.0, 0.0);
let result = cmyk.with_yellow_incremented_by(25.0);
assert!((result.yellow() - 50.0).abs() < 1e-10);
}
}
}