1use std::{
2 borrow::Cow,
3 fmt,
4 ops::{Deref, DerefMut},
5};
6
7use crate::json::ToJson;
8use pathfinder_color::{ColorF, ColorU};
9use schemars::JsonSchema;
10use serde::{
11 de::{self, Unexpected},
12 Deserialize, Deserializer,
13};
14use serde_json::json;
15
16#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, JsonSchema)]
17#[repr(transparent)]
18pub struct Color(#[schemars(with = "String")] pub ColorU);
19
20pub fn color(rgba: u32) -> Color {
21 Color::from_u32(rgba)
22}
23
24pub fn rgb(r: f32, g: f32, b: f32) -> Color {
25 Color(ColorF::new(r, g, b, 1.).to_u8())
26}
27
28pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
29 Color(ColorF::new(r, g, b, a).to_u8())
30}
31
32pub fn transparent_black() -> Color {
33 Color(ColorU::transparent_black())
34}
35
36pub fn black() -> Color {
37 Color(ColorU::black())
38}
39
40pub fn white() -> Color {
41 Color(ColorU::white())
42}
43
44pub fn red() -> Color {
45 color(0xff0000ff)
46}
47
48pub fn green() -> Color {
49 color(0x00ff00ff)
50}
51
52pub fn blue() -> Color {
53 color(0x0000ffff)
54}
55
56pub fn yellow() -> Color {
57 color(0xffff00ff)
58}
59
60impl Color {
61 pub fn transparent_black() -> Self {
62 transparent_black()
63 }
64
65 pub fn black() -> Self {
66 black()
67 }
68
69 pub fn white() -> Self {
70 white()
71 }
72
73 pub fn red() -> Self {
74 Color::from_u32(0xff0000ff)
75 }
76
77 pub fn green() -> Self {
78 Color::from_u32(0x00ff00ff)
79 }
80
81 pub fn blue() -> Self {
82 Color::from_u32(0x0000ffff)
83 }
84
85 pub fn yellow() -> Self {
86 Color::from_u32(0xffff00ff)
87 }
88
89 pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
90 Self(ColorU::new(r, g, b, a))
91 }
92
93 pub fn from_u32(rgba: u32) -> Self {
94 Self(ColorU::from_u32(rgba))
95 }
96
97 pub fn blend(source: Color, dest: Color) -> Color {
98 // Skip blending if we don't need it.
99 if source.a == 255 {
100 return source;
101 } else if source.a == 0 {
102 return dest;
103 }
104
105 let source = source.0.to_f32();
106 let dest = dest.0.to_f32();
107
108 let a = source.a() + (dest.a() * (1. - source.a()));
109 let r = ((source.r() * source.a()) + (dest.r() * dest.a() * (1. - source.a()))) / a;
110 let g = ((source.g() * source.a()) + (dest.g() * dest.a() * (1. - source.a()))) / a;
111 let b = ((source.b() * source.a()) + (dest.b() * dest.a() * (1. - source.a()))) / a;
112
113 Self(ColorF::new(r, g, b, a).to_u8())
114 }
115
116 pub fn fade_out(&mut self, fade: f32) {
117 let fade = fade.clamp(0., 1.);
118 self.0.a = (self.0.a as f32 * (1. - fade)) as u8;
119 }
120}
121
122impl<'de> Deserialize<'de> for Color {
123 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
124 where
125 D: Deserializer<'de>,
126 {
127 let literal: Cow<str> = Deserialize::deserialize(deserializer)?;
128 if let Some(digits) = literal.strip_prefix('#') {
129 if let Ok(value) = u32::from_str_radix(digits, 16) {
130 if digits.len() == 6 {
131 return Ok(Color::from_u32((value << 8) | 0xFF));
132 } else if digits.len() == 8 {
133 return Ok(Color::from_u32(value));
134 }
135 }
136 }
137 Err(de::Error::invalid_value(
138 Unexpected::Str(literal.as_ref()),
139 &"#RRGGBB[AA]",
140 ))
141 }
142}
143
144impl From<u32> for Color {
145 fn from(value: u32) -> Self {
146 Self(ColorU::from_u32(value))
147 }
148}
149
150impl ToJson for Color {
151 fn to_json(&self) -> serde_json::Value {
152 json!(format!(
153 "0x{:x}{:x}{:x}{:x}",
154 self.0.r, self.0.g, self.0.b, self.0.a
155 ))
156 }
157}
158
159impl Deref for Color {
160 type Target = ColorU;
161 fn deref(&self) -> &Self::Target {
162 &self.0
163 }
164}
165
166impl DerefMut for Color {
167 fn deref_mut(&mut self) -> &mut Self::Target {
168 &mut self.0
169 }
170}
171
172impl fmt::Debug for Color {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 self.0.fmt(f)
175 }
176}