chromashift/
hex.rs

1use crate::{Srgb, ToAlpha};
2use core::fmt;
3
4/// An Hex representation of the sRGB colour space.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct Hex(u32);
7
8const fn is_shorthand_byte(byte: u8) -> bool {
9	(byte >> 4) == (byte & 0xF)
10}
11
12impl Hex {
13	pub const fn new(hex: u32) -> Self {
14		Self(hex)
15	}
16
17	pub fn can_use_3_digit(self) -> bool {
18		let Srgb { red, green, blue, .. } = self.into();
19		!self.has_alpha() && is_shorthand_byte(red) && is_shorthand_byte(green) && is_shorthand_byte(blue)
20	}
21
22	pub fn can_use_4_digit(self) -> bool {
23		let Srgb { red, green, blue, alpha } = self.into();
24		is_shorthand_byte(red)
25			&& is_shorthand_byte(green)
26			&& is_shorthand_byte(blue)
27			&& is_shorthand_byte(((alpha as u32 * 255) / 100) as u8)
28	}
29
30	pub const fn has_alpha(&self) -> bool {
31		self.0 & 0xFF != 0xFF
32	}
33}
34
35impl ToAlpha for Hex {
36	fn to_alpha(&self) -> f32 {
37		((self.0 & 0xFF) as f32 / 255.0) * 100.0
38	}
39}
40
41impl fmt::Display for Hex {
42	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43		let Srgb { red, green, blue, alpha } = (*self).into();
44		let alpha = (alpha as u32 * 255) / 100;
45		if self.can_use_3_digit() {
46			write!(f, "#{:x}{:x}{:x}", red & 0xF, green & 0xF, blue & 0xF)
47		} else if self.can_use_4_digit() {
48			write!(f, "#{:x}{:x}{:x}{:x}", red & 0xF, green & 0xF, blue & 0xF, alpha & 0xF)
49		} else if self.has_alpha() {
50			write!(f, "#{red:02x}{green:02x}{blue:02x}{alpha:02x}")
51		} else {
52			write!(f, "#{red:02x}{green:02x}{blue:02x}")
53		}
54	}
55}
56
57impl From<Hex> for Srgb {
58	fn from(value: Hex) -> Self {
59		let hex = value.0;
60		let r = ((hex >> 24) & 0xFF) as u8;
61		let g = ((hex >> 16) & 0xFF) as u8;
62		let b = ((hex >> 8) & 0xFF) as u8;
63		let alpha = (((hex & 0xFF) * 100) / 255) as f32;
64		Srgb::new(r, g, b, alpha)
65	}
66}
67
68impl From<Srgb> for Hex {
69	fn from(value: Srgb) -> Self {
70		let Srgb { red, green, blue, alpha } = value;
71		Hex::new(((red as u32) << 24) | ((green as u32) << 16) | ((blue as u32) << 8) | ((alpha as u32 * 255) / 100))
72	}
73}