1use crate::{Alpha, Chromaticity, Matrix3, Number, ToAlpha};
2use core::fmt;
3
4macro_rules! xyz_color {
5 ($(#[$meta:meta])* $ty:ident, $css:literal, $white:ident) => {
6 $(#[$meta])*
7 #[derive(Debug, Clone, Copy, PartialEq)]
13 pub struct $ty {
14 pub x: f64,
15 pub y: f64,
16 pub z: f64,
17 pub alpha: f32,
18 }
19
20 impl $ty {
21 pub const WHITE: Chromaticity = Chromaticity::$white;
23
24 pub fn new(x: f64, y: f64, z: f64, alpha: f32) -> Self {
25 Self { x, y, z, alpha: alpha.clamp(0.0, 100.0) }
26 }
27 }
28
29 impl ToAlpha for $ty {
30 fn to_alpha(&self) -> f32 {
31 self.alpha
32 }
33 }
34
35 impl fmt::Display for $ty {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 let Self { x, y, z, alpha } = *self;
38 write!(f, concat!("color(", $css, " {} {} {}{})"), Number(x / 100.0), Number(y / 100.0), Number(z / 100.0), Alpha(alpha))
39 }
40 }
41 };
42}
43
44xyz_color!(
45 XyzD50,
48 "xyz-d50",
49 D50
50);
51
52xyz_color!(
53 XyzD65,
56 "xyz-d65",
57 D65
58);
59
60const D50_TO_D65: Matrix3 = XyzD50::WHITE.adapt_to(XyzD65::WHITE);
61const D65_TO_D50: Matrix3 = XyzD65::WHITE.adapt_to(XyzD50::WHITE);
62
63impl From<XyzD50> for XyzD65 {
64 fn from(value: XyzD50) -> Self {
65 let XyzD50 { x, y, z, alpha } = value;
66 let [x, y, z] = D50_TO_D65.transform([x, y, z]);
67 XyzD65::new(x, y, z, alpha)
68 }
69}
70
71impl From<XyzD65> for XyzD50 {
72 fn from(value: XyzD65) -> Self {
73 let XyzD65 { x, y, z, alpha } = value;
74 let [x, y, z] = D65_TO_D50.transform([x, y, z]);
75 XyzD50::new(x, y, z, alpha)
76 }
77}