1use crate::{Hsv, round_dp};
2use core::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq)]
11pub struct Hwb {
12 pub hue: f32,
13 pub whiteness: f32,
14 pub blackness: f32,
15 pub alpha: f32,
16}
17
18impl Hwb {
19 pub fn new(hue: f32, whiteness: f32, blackness: f32, alpha: f32) -> Self {
20 Self {
21 hue: hue.rem_euclid(360.0),
22 whiteness: whiteness.clamp(0.0, 100.0),
23 blackness: blackness.clamp(0.0, 100.0),
24 alpha: alpha.clamp(0.0, 100.0),
25 }
26 }
27}
28
29impl fmt::Display for Hwb {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 let Self { hue, whiteness, blackness, alpha } = self;
32 write!(
33 f,
34 "hwb({} {} {}",
35 round_dp(*hue as f64, 2),
36 round_dp(*whiteness as f64, 3),
37 round_dp(*blackness as f64, 3)
38 )?;
39 if *alpha < 100.0 {
40 write!(f, " / {}", round_dp(*alpha as f64, 2))?;
41 }
42 write!(f, ")")
43 }
44}
45
46impl From<Hsv> for Hwb {
47 fn from(value: Hsv) -> Self {
48 let Hsv { hue, saturation, value, alpha } = value;
49 let s = saturation / 100.0;
50 let v = value / 100.0;
51 let whiteness = (1.0 - s) * v;
52 let blackness = 1.0 - v;
53 Hwb::new(hue, whiteness * 100.0, blackness * 100.0, alpha)
54 }
55}
56
57impl From<Hwb> for Hsv {
58 fn from(value: Hwb) -> Self {
59 let Hwb { hue, whiteness, blackness, alpha } = value;
60 let w = whiteness / 100.0;
61 let b = blackness / 100.0;
62 let sum = w + b;
63 let (s, v) = if sum >= 1.0 {
64 (0.0, w / sum)
65 } else {
66 let v = 1.0 - b;
67 let s = if v == 0.0 { 0.0 } else { 1.0 - w / v };
68 (s, v)
69 };
70 Hsv::new(hue, s * 100.0, v * 100.0, alpha)
71 }
72}