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 yellow() -> Self {
 45        Self(ColorU::from_u32(0xffff00ff))
 46    }
 47
 48    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
 49        Self(ColorU::new(r, g, b, a))
 50    }
 51
 52    pub fn from_u32(rgba: u32) -> Self {
 53        Self(ColorU::from_u32(rgba))
 54    }
 55
 56    pub fn blend(source: Color, dest: Color) -> Color {
 57        // Skip blending if we don't need it.
 58        if source.a == 255 {
 59            return source;
 60        } else if source.a == 0 {
 61            return dest;
 62        }
 63
 64        let source = source.0.to_f32();
 65        let dest = dest.0.to_f32();
 66
 67        let a = source.a() + (dest.a() * (1. - source.a()));
 68        let r = ((source.r() * source.a()) + (dest.r() * dest.a() * (1. - source.a()))) / a;
 69        let g = ((source.g() * source.a()) + (dest.g() * dest.a() * (1. - source.a()))) / a;
 70        let b = ((source.b() * source.a()) + (dest.b() * dest.a() * (1. - source.a()))) / a;
 71
 72        Self(ColorF::new(r, g, b, a).to_u8())
 73    }
 74
 75    pub fn fade_out(&mut self, fade: f32) {
 76        let fade = fade.clamp(0., 1.);
 77        self.0.a = (self.0.a as f32 * (1. - fade)) as u8;
 78    }
 79}
 80
 81impl<'de> Deserialize<'de> for Color {
 82    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 83    where
 84        D: Deserializer<'de>,
 85    {
 86        let literal: Cow<str> = Deserialize::deserialize(deserializer)?;
 87        if let Some(digits) = literal.strip_prefix('#') {
 88            if let Ok(value) = u32::from_str_radix(digits, 16) {
 89                if digits.len() == 6 {
 90                    return Ok(Color::from_u32((value << 8) | 0xFF));
 91                } else if digits.len() == 8 {
 92                    return Ok(Color::from_u32(value));
 93                }
 94            }
 95        }
 96        Err(de::Error::invalid_value(
 97            Unexpected::Str(literal.as_ref()),
 98            &"#RRGGBB[AA]",
 99        ))
100    }
101}
102
103impl ToJson for Color {
104    fn to_json(&self) -> serde_json::Value {
105        json!(format!(
106            "0x{:x}{:x}{:x}{:x}",
107            self.0.r, self.0.g, self.0.b, self.0.a
108        ))
109    }
110}
111
112impl Deref for Color {
113    type Target = ColorU;
114    fn deref(&self) -> &Self::Target {
115        &self.0
116    }
117}
118
119impl DerefMut for Color {
120    fn deref_mut(&mut self) -> &mut Self::Target {
121        &mut self.0
122    }
123}
124
125impl fmt::Debug for Color {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        self.0.fmt(f)
128    }
129}