1use core::fmt;
2mod channels;
3mod chromaticity;
4mod color_space;
5mod conversion;
6mod distance;
7mod gamut;
8mod hex;
9mod hsb;
10mod hsl;
11mod hwb;
12mod interpolation_space;
13mod lab;
14mod lch;
15mod matrix;
16mod mix;
17mod named;
18mod oklab;
19mod oklch;
20mod rgb;
21mod rgb_space;
22mod round;
23mod srgb;
24#[cfg(test)]
25mod tests;
26mod transfer;
27mod wcag;
28mod xyz;
29
30pub use channels::{Channel, ToAlpha};
31pub use chromaticity::Chromaticity;
32pub use color_space::ColorSpace;
33pub use distance::ColorDistance;
34pub use gamut::Gamut;
35pub use hex::Hex;
36pub use hsb::Hsv;
37pub use hsl::Hsl;
38pub use hwb::Hwb;
39pub use interpolation_space::{HueInterpolation, InterpolationSpace};
40pub use lab::Lab;
41pub use lch::Lch;
42pub use matrix::Matrix3;
43pub use mix::ColorMix;
44pub use named::{Named, ToNamedError};
45pub use oklab::Oklab;
46pub use oklch::Oklch;
47pub use rgb::{A98Rgb, DisplayP3, LinearRgb, ProphotoRgb, Rec2020, Srgb};
48pub use rgb_space::RgbSpace;
49pub(crate) use round::{Alpha, Number};
50pub use round::{PerceptualRound, round_dp};
51pub use transfer::Transfer;
52pub use wcag::{WcagColorContrast, WcagLevel};
53pub use xyz::{XyzD50, XyzD65};
54
55macro_rules! color {
56 (settable: $($settable:ident),+ $(,)?; via_srgb: $($via_srgb:ident),+ $(,)?;) => {
57 #[derive(Debug, Clone, Copy, PartialEq)]
59 pub enum Color {
60 $($settable($settable),)+
61 $($via_srgb($via_srgb),)+
62 }
63
64 impl Color {
65 pub fn with_alpha(self, alpha: f32) -> Self {
69 let alpha = alpha.clamp(0.0, 100.0);
70 match self {
71 $(Self::$settable(mut c) => {
72 c.alpha = alpha;
73 Self::$settable(c)
74 })+
75 $(Self::$via_srgb(c) => {
76 let mut srgb = Srgb::from(c);
77 srgb.alpha = alpha;
78 Self::Srgb(srgb)
79 })+
80 }
81 }
82 }
83
84 impl fmt::Display for Color {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 match self {
87 $(Self::$settable(c) => fmt::Display::fmt(c, f),)+
88 $(Self::$via_srgb(c) => fmt::Display::fmt(c, f),)+
89 }
90 }
91 }
92
93 impl ToAlpha for Color {
94 fn to_alpha(&self) -> f32 {
95 match self {
96 $(Self::$settable(c) => c.to_alpha(),)+
97 $(Self::$via_srgb(c) => c.to_alpha(),)+
98 }
99 }
100 }
101
102 impl Color {
103 fn convert<T>(self) -> T
104 where
105 $(T: From<$settable>,)+
106 $(T: From<$via_srgb>,)+
107 {
108 match self {
109 $(Color::$settable(c) => c.into(),)+
110 $(Color::$via_srgb(c) => c.into(),)+
111 }
112 }
113 }
114
115 $(impl From<Color> for $settable {
116 fn from(value: Color) -> Self {
117 value.convert()
118 }
119 })+
120
121 impl From<Color> for Hex {
122 fn from(value: Color) -> Self {
123 value.convert()
124 }
125 }
126
127 $(impl From<$settable> for Color {
128 fn from(c: $settable) -> Self {
129 Color::$settable(c)
130 }
131 })+
132
133 $(impl From<$via_srgb> for Color {
134 fn from(c: $via_srgb) -> Self {
135 Color::$via_srgb(c)
136 }
137 })+
138 };
139}
140
141color! {
142 settable: A98Rgb, DisplayP3, Hsv, Hsl, Hwb, Lab, Lch, LinearRgb, Oklab, Oklch, ProphotoRgb, Rec2020, Srgb, XyzD50, XyzD65;
143 via_srgb: Hex, Named;
144}
145
146pub const COLOR_EPSILON: f64 = 0.0072;