1use std::i64;
2use tiny_skia::Color;
3
4const HEX_COLOR_LENGTH: usize = 7;
5const HEX_COLOR_WITH_ALPHA_LENGTH: usize = 9;
6
7pub struct RgbaColor(Color);
8
9pub fn is_valid_hex_color(color: &str) -> bool {
10 (color.len() == HEX_COLOR_LENGTH || color.len() == HEX_COLOR_WITH_ALPHA_LENGTH)
11 && color.starts_with("#")
12}
13
14fn parse_color_to_rgba_hex(hex: &str) -> String {
15 if !is_valid_hex_color(&hex) || hex.len() == HEX_COLOR_WITH_ALPHA_LENGTH {
16 hex.to_string()
17 } else {
18 format!("{}ff", hex)
19 }
20}
21
22pub fn parse_hex_to_cosmic_color(hex: &str) -> cosmic_text::Color {
23 let color: RgbaColor = hex.into();
24
25 color.into()
26}
27
28impl Into<RgbaColor> for &str {
29 fn into(self) -> RgbaColor {
30 if !is_valid_hex_color(&self) {
31 panic!("Invalid hex color: {}", self);
32 }
33
34 let rgba_hex_color = parse_color_to_rgba_hex(&self);
35 let hex_color = &rgba_hex_color.to_lowercase()[1..rgba_hex_color.len()];
37 let chars = hex_color.chars().collect::<Vec<char>>();
38 let splits = &chars
39 .chunks(2)
40 .map(|chunk| i64::from_str_radix(&chunk.iter().collect::<String>(), 16).unwrap())
41 .collect::<Vec<_>>();
42
43 RgbaColor(Color::from_rgba8(
44 splits[0] as u8,
45 splits[1] as u8,
46 splits[2] as u8,
47 splits[3] as u8,
48 ))
49 }
50}
51
52impl From<RgbaColor> for cosmic_text::Color {
53 fn from(value: RgbaColor) -> Self {
54 let color = value.0.to_color_u8();
55
56 cosmic_text::Color::rgba(color.red(), color.green(), color.blue(), color.alpha())
57 }
58}
59
60impl From<RgbaColor> for Color {
61 fn from(value: RgbaColor) -> Self {
62 value.0
63 }
64}