use core::ops::{Add, Mul, Sub};
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Hash)]
#[repr(C)]
pub struct ColorRgba8 {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
const _: () = assert!(core::mem::size_of::<ColorRgba8>() == 4);
impl ColorRgba8 {
pub const BLACK: Self = Self::from_rgba(0, 0, 0, 255);
pub const WHITE: Self = Self::from_rgba(255, 255, 255, 255);
pub const TRANSPARENT: Self = Self::from_rgba(0, 0, 0, 0);
pub const MAGENTA: Self = Self::from_rgb(255, 0, 255);
#[inline]
#[must_use]
pub const fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r, g, b, a }
}
#[inline]
#[must_use]
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b, a: 255 }
}
#[inline]
#[must_use]
pub fn to_linear(self) -> Rgb {
Rgb {
r: f32::from(self.r) / 255.0,
g: f32::from(self.g) / 255.0,
b: f32::from(self.b) / 255.0,
}
}
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
pub struct Rgb {
pub r: f32,
pub g: f32,
pub b: f32,
}
impl Rgb {
pub const BLACK: Self = Self::new(0.0, 0.0, 0.0);
pub const WHITE: Self = Self::new(1.0, 1.0, 1.0);
#[inline]
#[must_use]
pub const fn new(r: f32, g: f32, b: f32) -> Self {
Self { r, g, b }
}
#[inline]
#[must_use]
#[expect(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
pub fn to_rgba8(self) -> ColorRgba8 {
ColorRgba8 {
r: (self.r * 255.0) as u8,
g: (self.g * 255.0) as u8,
b: (self.b * 255.0) as u8,
a: 255,
}
}
}
impl Add for Rgb {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Self::new(self.r + rhs.r, self.g + rhs.g, self.b + rhs.b)
}
}
impl Sub for Rgb {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Self::new(self.r - rhs.r, self.g - rhs.g, self.b - rhs.b)
}
}
impl Mul<f32> for Rgb {
type Output = Self;
#[inline]
fn mul(self, rhs: f32) -> Self {
Self::new(self.r * rhs, self.g * rhs, self.b * rhs)
}
}
impl Mul for Rgb {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
Self::new(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b)
}
}