1use std::ops::Mul;
2
3use freya_engine::prelude::{
4 SkColor,
5 SkColor4f,
6 SkHSV,
7 SkRGB,
8};
9
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Default, Hash)]
19pub struct Color(u32);
20
21impl Mul<f32> for Color {
22 type Output = Color;
23 fn mul(self, rhs: f32) -> Self::Output {
24 (
25 (self.r() as f32 * rhs) as u8,
26 (self.g() as f32 * rhs) as u8,
27 (self.b() as f32 * rhs) as u8,
28 self.a(),
29 )
30 .into()
31 }
32}
33
34impl Color {
35 pub fn mul_if(self, check: bool, var: f32) -> Self {
36 if check { self * var } else { self }
37 }
38}
39
40impl From<(u8, u8, u8)> for Color {
41 fn from((r, g, b): (u8, u8, u8)) -> Self {
42 Color::from_rgb(r, g, b)
43 }
44}
45
46impl From<(u8, u8, u8, f32)> for Color {
47 fn from((r, g, b, a): (u8, u8, u8, f32)) -> Self {
48 Color::from_af32rgb(a, r, g, b)
49 }
50}
51
52impl From<(u8, u8, u8, u8)> for Color {
53 fn from((r, g, b, a): (u8, u8, u8, u8)) -> Self {
54 Color::from_argb(a, r, g, b)
55 }
56}
57
58impl From<u32> for Color {
59 fn from(value: u32) -> Self {
60 Color(value)
61 }
62}
63
64impl From<Color> for u32 {
65 fn from(value: Color) -> Self {
66 value.0
67 }
68}
69
70impl From<Color> for SkColor {
71 fn from(value: Color) -> Self {
72 Self::new(value.0)
73 }
74}
75
76impl From<Color> for SkColor4f {
77 fn from(value: Color) -> Self {
78 SkColor4f::new(
79 value.r() as f32,
80 value.g() as f32,
81 value.b() as f32,
82 value.a() as f32,
83 )
84 }
85}
86
87impl From<SkColor> for Color {
88 fn from(value: SkColor) -> Self {
89 let a = value.a();
90 let r = value.r();
91 let g = value.g();
92 let b = value.b();
93 Color::from_argb(a, r, g, b)
94 }
95}
96
97impl Color {
98 pub const TRANSPARENT: Self = Color::new(0);
99 pub const BLACK: Self = Color::new(4278190080);
100 pub const DARK_GRAY: Self = Color::new(4282664004);
101 pub const GRAY: Self = Color::new(4287137928);
102 pub const LIGHT_GRAY: Self = Color::new(4291611852);
103 pub const DARK_GREY: Self = Color::new(4282664004);
104 pub const GREY: Self = Color::new(4287137928);
105 pub const LIGHT_GREY: Self = Color::new(4291611852);
106 pub const WHITE: Self = Color::new(4294967295);
107 pub const RED: Self = Color::new(4294901760);
108 pub const GREEN: Self = Color::new(4278255360);
109 pub const BLUE: Self = Color::new(4278190335);
110 pub const YELLOW: Self = Color::new(4294967040);
111 pub const CYAN: Self = Color::new(4278255615);
112 pub const MAGENTA: Self = Color::new(4294902015);
113
114 pub const fn new(value: u32) -> Self {
115 Self(value)
116 }
117
118 pub const fn from_af32rgb(a: f32, r: u8, g: u8, b: u8) -> Self {
119 Self::from_argb((255. * a) as u8, r, g, b)
120 }
121
122 pub const fn from_argb(a: u8, r: u8, g: u8, b: u8) -> Self {
123 Self(((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32))
124 }
125
126 pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
127 Self::from_argb(255, r, g, b)
128 }
129
130 pub fn from_hsv(h: f32, s: f32, v: f32) -> Self {
131 SkHSV { h, s, v }.to_color(255).into()
132 }
133
134 pub fn from_hex(hex: &str) -> Option<Self> {
135 let s = if let Some(stripped) = hex.strip_prefix('#') {
136 stripped
137 } else if let Some(stripped) = hex.strip_prefix("0x") {
138 stripped
139 } else {
140 hex
141 };
142
143 match s.len() {
144 6 => {
145 u32::from_str_radix(s, 16).ok().map(|rgb| {
147 let r = ((rgb >> 16) & 0xFF) as u8;
148 let g = ((rgb >> 8) & 0xFF) as u8;
149 let b = (rgb & 0xFF) as u8;
150 Color::from_rgb(r, g, b)
151 })
152 }
153 8 => {
154 u32::from_str_radix(s, 16).ok().map(|rgba| {
156 let r = ((rgba >> 24) & 0xFF) as u8;
157 let g = ((rgba >> 16) & 0xFF) as u8;
158 let b = ((rgba >> 8) & 0xFF) as u8;
159 let a = (rgba & 0xFF) as u8;
160 Color::from_argb(a, r, g, b)
161 })
162 }
163 _ => None,
164 }
165 }
166
167 pub fn with_a(self, a: u8) -> Self {
168 let color: SkColor = self.into();
169 color.with_a(a).into()
170 }
171
172 pub fn a(self) -> u8 {
173 (self.0 >> 24) as _
174 }
175
176 pub fn r(self) -> u8 {
177 (self.0 >> 16) as _
178 }
179
180 pub fn g(self) -> u8 {
181 (self.0 >> 8) as _
182 }
183
184 pub fn b(self) -> u8 {
185 self.0 as _
186 }
187
188 pub fn to_rgb(self) -> SkRGB {
189 let color: SkColor = self.into();
190 color.to_rgb()
191 }
192
193 pub fn to_hsv(self) -> SkHSV {
194 let color: SkColor = self.into();
195 color.to_hsv()
196 }
197
198 pub fn with_h(self, h: f32) -> Color {
199 let color: SkColor = self.into();
200 let hsv = color.to_hsv();
201 Self::from_hsv(h, hsv.s, hsv.v)
202 }
203
204 pub fn with_s(self, s: f32) -> Color {
205 let color: SkColor = self.into();
206 let hsv = color.to_hsv();
207 Self::from_hsv(hsv.h, s, hsv.v)
208 }
209
210 pub fn with_v(self, v: f32) -> Color {
211 let color: SkColor = self.into();
212 let hsv = color.to_hsv();
213 Self::from_hsv(hsv.h, hsv.s, v)
214 }
215
216 pub fn to_hex_string(&self) -> String {
217 format!(
218 "#{:02X}{:02X}{:02X}{:02X}",
219 self.a(),
220 self.r(),
221 self.g(),
222 self.b(),
223 )
224 }
225
226 pub fn to_rgb_string(&self) -> String {
227 format!(
228 "rgb({:?}, {:?}, {:?}, {:?})",
229 self.r(),
230 self.g(),
231 self.b(),
232 self.a() as f32 / 100.
233 )
234 }
235
236 pub fn pretty(&self) -> String {
237 self.to_rgb_string()
238 }
239}