use crate::{math::general::NumTools, compsci::colours::rgba::RGBa};
const ARG_ERR: &str = "Arguments must range from 0 to 1.";
#[derive(Clone, Copy, PartialEq)]
pub struct CMYK {
cyan: f32,
magenta: f32,
yellow: f32,
black: f32
}
impl CMYK {
#[inline]
#[must_use]
pub fn new(cyan: f32,
magenta: f32,
yellow: f32,
black: f32) -> CMYK {
if !cyan.is_in_range(0.0, 1.0) ||
!magenta.is_in_range(0.0, 1.0) ||
!yellow.is_in_range(0.0, 1.0) ||
!black.is_in_range(0.0, 1.0)
{ panic!("{}", ARG_ERR); }
CMYK { cyan, magenta, yellow, black }
}
#[inline]
#[must_use]
pub fn from_rgba_struct(rgb: &RGBa) -> CMYK {
let r: f32 = rgb.red as f32 / 255.0;
let g: f32 = rgb.green as f32 / 255.0;
let b: f32 = rgb.blue as f32 / 255.0;
let k: f32 = 1.0 - r.min(g).min(b);
let c: f32 = (1.0 - r - k) / (1.0 - k);
let m: f32 = (1.0 - g - k) / (1.0 - k);
let y: f32 = (1.0 - b - k) / (1.0 - k);
CMYK { cyan: c,
magenta: m,
yellow: y,
black: k }
}
#[inline]
#[must_use]
pub fn from_rgb_vals(red: u8, green: u8, blue: u8) -> CMYK {
CMYK::from_rgba_struct(&RGBa::new(red, green, blue, 255))
}
#[inline]
#[must_use]
pub const fn cyan(&self) -> f32 {
self.cyan
}
#[inline]
#[must_use]
pub const fn magenta(&self) -> f32 {
self.magenta
}
#[inline]
#[must_use]
pub const fn yellow(&self) -> f32 {
self.yellow
}
#[inline]
#[must_use]
pub const fn black(&self) -> f32 {
self.black
}
#[inline]
pub fn set_cyan(&mut self, value: f32) {
if !value.is_in_range(0.0, 1.0)
{ panic!("{}", ARG_ERR); }
self.cyan = value;
}
#[inline]
pub fn set_magenta(&mut self, value: f32) {
if !value.is_in_range(0.0, 1.0)
{ panic!("{}", ARG_ERR); }
self.magenta = value;
}
#[inline]
pub fn set_yellow(&mut self, value: f32) {
if !value.is_in_range(0.0, 1.0)
{ panic!("{}", ARG_ERR); }
self.yellow = value;
}
#[inline]
pub fn set_black(&mut self, value: f32) {
if !value.is_in_range(0.0, 1.0)
{ panic!("{}", ARG_ERR); }
self.black = value;
}
pub const SOLID_RED: CMYK = CMYK { cyan: 0.0, magenta: 1.0, yellow: 1.0, black: 0.0 };
pub const SOLID_GREEN: CMYK = CMYK { cyan: 1.0, magenta: 0.0, yellow: 1.0, black: 0.0 };
pub const SOLID_BLUE: CMYK = CMYK { cyan: 1.0, magenta: 1.0, yellow: 0.0, black: 0.0 };
pub const SOLID_WHITE: CMYK = CMYK { cyan: 0.0, magenta: 0.0, yellow: 0.0, black: 0.0 };
pub const SOLID_BLACK: CMYK = CMYK { cyan: 0.0, magenta: 1.0, yellow: 1.0, black: 1.0 };
pub const LIBRAPID_SOLID_BLUE: CMYK = CMYK { cyan: 0.44, magenta: 0.55, yellow: 0.0, black: 0.0 };
pub const LIBRAPID_SOLID_RED: CMYK = CMYK { cyan: 0.0, magenta: 0.79, yellow: 1.0, black: 0.0 };
}
impl std::fmt::Display for CMYK {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}; {}; {}; {})", self.cyan(),
self.magenta(),
self.yellow(),
self.black())
}
}
impl std::fmt::Debug for CMYK {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "(C: {}; M: {}; Y: {}; K: {})", self.cyan(),
self.magenta(),
self.yellow(),
self.black())
}
}
impl IntoIterator for CMYK {
type Item = f32;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
vec![self.cyan(), self.magenta(), self.yellow(), self.black()].into_iter()
}
}