use crate::sys;
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Color {
pub r: f32,
pub g: f32,
pub b: f32,
pub a: f32,
}
impl Color {
pub const TRANSPARENT: Self = Self::rgbaf(0.0, 0.0, 0.0, 0.0);
pub const BLACK: Self = Self::rgbaf(0.0, 0.0, 0.0, 1.0);
pub const WHITE: Self = Self::rgbaf(1.0, 1.0, 1.0, 1.0);
pub const RED: Self = Self::rgbaf(1.0, 0.0, 0.0, 1.0);
pub const GREEN: Self = Self::rgbaf(0.0, 1.0, 0.0, 1.0);
pub const BLUE: Self = Self::rgbaf(0.0, 0.0, 1.0, 1.0);
pub const YELLOW: Self = Self::rgbaf(1.0, 1.0, 0.0, 1.0);
pub const CYAN: Self = Self::rgbaf(0.0, 1.0, 1.0, 1.0);
pub const MAGENTA: Self = Self::rgbaf(1.0, 0.0, 1.0, 1.0);
}
impl Color {
#[inline]
pub fn rgb(r: u8, g: u8, b: u8) -> Self {
Self {
r: r as f32 / 255.0,
g: g as f32 / 255.0,
b: b as f32 / 255.0,
a: 1.0,
}
}
#[inline]
pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self {
r: r as f32 / 255.0,
g: g as f32 / 255.0,
b: b as f32 / 255.0,
a: a as f32 / 255.0,
}
}
#[inline]
pub fn rgbf(r: f32, g: f32, b: f32) -> Self {
Self { r, g, b, a: 1.0 }
}
#[inline]
pub const fn rgbaf(r: f32, g: f32, b: f32, a: f32) -> Self {
Self { r, g, b, a }
}
#[inline]
pub fn hex(rgba: u32) -> Self {
Self::rgba(
((rgba >> 24) & 0xFF) as u8,
((rgba >> 16) & 0xFF) as u8,
((rgba >> 8) & 0xFF) as u8,
(rgba & 0xFF) as u8,
)
}
pub fn css(s: &str) -> Option<Self> {
let s = s.strip_prefix('#').unwrap_or(s);
match s.len() {
6 => {
let v = u32::from_str_radix(s, 16).ok()?;
Some(Self::hex((v << 8) | 0xFF))
}
8 => {
let v = u32::from_str_radix(s, 16).ok()?;
Some(Self::hex(v))
}
_ => None,
}
}
#[inline]
pub fn hsl(h: f32, s: f32, l: f32) -> Self {
unsafe { std::mem::transmute(sys::nvgHSL(h, s, l)) }
}
#[inline]
pub fn hsla(h: f32, s: f32, l: f32, a: u8) -> Self {
unsafe { std::mem::transmute(sys::nvgHSLA(h, s, l, a)) }
}
}
impl Color {
#[inline]
pub fn with_alpha(self, a: f32) -> Self {
Self { a, ..self }
}
#[inline]
pub fn lerp(self, other: Self, t: f32) -> Self {
unsafe { std::mem::transmute(sys::nvgLerpRGBA(self.into_raw(), other.into_raw(), t)) }
}
#[inline]
pub fn darken(self, factor: f32) -> Self {
Self {
r: self.r * factor,
g: self.g * factor,
b: self.b * factor,
a: self.a,
}
}
#[inline]
pub fn lighten(self, factor: f32) -> Self {
self.lerp(Color::WHITE.with_alpha(self.a), factor)
}
}
impl Color {
#[inline]
pub(crate) fn into_raw(self) -> sys::NVGcolor {
unsafe { std::mem::transmute(self) }
}
#[inline]
#[allow(dead_code)]
pub(crate) fn from_raw(raw: sys::NVGcolor) -> Self {
unsafe { std::mem::transmute(raw) }
}
}
impl From<(u8, u8, u8)> for Color {
fn from((r, g, b): (u8, u8, u8)) -> Self {
Self::rgb(r, g, b)
}
}
impl From<(u8, u8, u8, u8)> for Color {
fn from((r, g, b, a): (u8, u8, u8, u8)) -> Self {
Self::rgba(r, g, b, a)
}
}
impl From<u32> for Color {
fn from(hex: u32) -> Self {
Self::hex(hex)
}
}