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 serde::{
 10    de::{self, Unexpected},
 11    Deserialize, Deserializer,
 12};
 13use serde_json::json;
 14
 15#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
 16#[repr(transparent)]
 17pub struct Color(ColorU);
 18
 19impl Color {
 20    pub fn transparent_black() -> Self {
 21        Self(ColorU::transparent_black())
 22    }
 23
 24    pub fn black() -> Self {
 25        Self(ColorU::black())
 26    }
 27
 28    pub fn white() -> Self {
 29        Self(ColorU::white())
 30    }
 31
 32    pub fn red() -> Self {
 33        Self(ColorU::from_u32(0xff0000ff))
 34    }
 35
 36    pub fn green() -> Self {
 37        Self(ColorU::from_u32(0x00ff00ff))
 38    }
 39
 40    pub fn blue() -> Self {
 41        Self(ColorU::from_u32(0x0000ffff))
 42    }
 43
 44    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
 45        Self(ColorU::new(r, g, b, a))
 46    }
 47
 48    pub fn from_u32(rgba: u32) -> Self {
 49        Self(ColorU::from_u32(rgba))
 50    }
 51
 52    pub fn blend(source: Color, dest: Color) -> Color {
 53        // Skip blending if we don't need it.
 54        if source.a == 255 {
 55            return source;
 56        } else if source.a == 0 {
 57            return dest;
 58        }
 59
 60        let source = source.0.to_f32();
 61        let dest = dest.0.to_f32();
 62
 63        let a = source.a() + (dest.a() * (1. - source.a()));
 64        let r = ((source.r() * source.a()) + (dest.r() * dest.a() * (1. - source.a()))) / a;
 65        let g = ((source.g() * source.a()) + (dest.g() * dest.a() * (1. - source.a()))) / a;
 66        let b = ((source.b() * source.a()) + (dest.b() * dest.a() * (1. - source.a()))) / a;
 67
 68        Self(ColorF::new(r, g, b, a).to_u8())
 69    }
 70
 71    pub fn fade_out(&mut self, fade: f32) {
 72        let fade = fade.clamp(0., 1.);
 73        self.0.a = (self.0.a as f32 * (1. - fade)) as u8;
 74    }
 75}
 76
 77impl<'de> Deserialize<'de> for Color {
 78    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 79    where
 80        D: Deserializer<'de>,
 81    {
 82        let literal: Cow<str> = Deserialize::deserialize(deserializer)?;
 83        if let Some(digits) = literal.strip_prefix('#') {
 84            if let Ok(value) = u32::from_str_radix(digits, 16) {
 85                if digits.len() == 6 {
 86                    return Ok(Color::from_u32((value << 8) | 0xFF));
 87                } else if digits.len() == 8 {
 88                    return Ok(Color::from_u32(value));
 89                }
 90            }
 91        }
 92        Err(de::Error::invalid_value(
 93            Unexpected::Str(literal.as_ref()),
 94            &"#RRGGBB[AA]",
 95        ))
 96    }
 97}
 98
 99impl ToJson for Color {
100    fn to_json(&self) -> serde_json::Value {
101        json!(format!(
102            "0x{:x}{:x}{:x}{:x}",
103            self.0.r, self.0.g, self.0.b, self.0.a
104        ))
105    }
106}
107
108impl Deref for Color {
109    type Target = ColorU;
110    fn deref(&self) -> &Self::Target {
111        &self.0
112    }
113}
114
115impl DerefMut for Color {
116    fn deref_mut(&mut self) -> &mut Self::Target {
117        &mut self.0
118    }
119}
120
121impl fmt::Debug for Color {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        self.0.fmt(f)
124    }
125}