1use crate::{Hsv, ToAlpha, 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 ToAlpha for Hwb {
30 fn to_alpha(&self) -> f32 {
31 self.alpha
32 }
33}
34
35impl fmt::Display for Hwb {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 let Self { hue, whiteness, blackness, alpha } = self;
38 write!(
39 f,
40 "hwb({} {} {}",
41 round_dp(*hue as f64, 2),
42 round_dp(*whiteness as f64, 3),
43 round_dp(*blackness as f64, 3)
44 )?;
45 if *alpha < 100.0 {
46 write!(f, " / {}", round_dp(*alpha as f64, 2))?;
47 }
48 write!(f, ")")
49 }
50}
51
52impl From<Hsv> for Hwb {
53 fn from(value: Hsv) -> Self {
54 let Hsv { hue, saturation, value, alpha } = value;
55 let s = saturation / 100.0;
56 let v = value / 100.0;
57 let whiteness = (1.0 - s) * v;
58 let blackness = 1.0 - v;
59 Hwb::new(hue, whiteness * 100.0, blackness * 100.0, alpha)
60 }
61}
62
63impl From<Hwb> for Hsv {
64 fn from(value: Hwb) -> Self {
65 let Hwb { hue, whiteness, blackness, alpha } = value;
66 let w = whiteness / 100.0;
67 let b = blackness / 100.0;
68 let sum = w + b;
69 let (s, v) = if sum >= 1.0 {
70 (0.0, w / sum)
71 } else {
72 let v = 1.0 - b;
73 let s = if v == 0.0 { 0.0 } else { 1.0 - w / v };
74 (s, v)
75 };
76 Hsv::new(hue, s * 100.0, v * 100.0, alpha)
77 }
78}