color.rs

  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}