use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
/// Utility type for manpulating RGBA colors
///
/// `Color` is a simple color type composed of 4 components: Red, Green, Blue, Alpha
///
/// # Example
///
/// There are 3 basic ways to construct a color
///
/// ```
/// use sfml::graphics::Color;
/// let color1 = Color::rgb(255, 0, 0); // from red/green/blue values
/// let color2 = Color::rgba(255, 255, 255, 128); // from red/green/blue/alpha (transparency)
/// let color3 = Color::GREEN; // from one of the associated color constants
/// ```
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
pub struct Color {
/// Red component
pub r: u8,
/// Green component
pub g: u8,
/// Blue component
pub b: u8,
/// Alpha component (transparency)
pub a: u8,
}
impl Color {
/// Construct a color from its 3 RGB components
///
/// # Arguments
/// * red - Red component (0 .. 255)
/// * green - -Green component (0 .. 255)
/// * blue - Blue component (0 .. 255)
///
/// Return Color object constructed from the components
#[must_use]
pub const fn rgb(red: u8, green: u8, blue: u8) -> Self {
Self {
r: red,
g: green,
b: blue,
a: 255,
}
}
/// Construct a color from its 4 RGBA components
///
/// # Arguments
/// * red - Red component (0 .. 255)
/// * green - -Green component (0 .. 255)
/// * blue - Blue component (0 .. 255)
/// * alpha - Alpha component (0 .. 255)
///
/// Return Color object constructed from the components
#[must_use]
pub const fn rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
Self {
r: red,
g: green,
b: blue,
a: alpha,
}
}
/// Black predefined color
pub const BLACK: Self = Self::rgb(0, 0, 0);
/// White predefined color
pub const WHITE: Self = Self::rgb(255, 255, 255);
/// Red predefined color
pub const RED: Self = Self::rgb(255, 0, 0);
/// Green predefined color
pub const GREEN: Self = Self::rgb(0, 255, 0);
/// Blue predefined color
pub const BLUE: Self = Self::rgb(0, 0, 255);
/// Yellow predefined color
pub const YELLOW: Self = Self::rgb(255, 255, 0);
/// Magenta predefined color
pub const MAGENTA: Self = Self::rgb(255, 0, 255);
/// Cyan predifined color
pub const CYAN: Self = Self::rgb(0, 255, 255);
/// Tranparent predefined color
pub const TRANSPARENT: Self = Self::rgba(0, 0, 0, 0);
}
impl From<u32> for Color {
/// Construct the color from 32-bit unsigned integer.
///
/// The number should contain the components in RGBA order.
#[allow(clippy::cast_possible_truncation)]
fn from(src: u32) -> Self {
Self {
r: ((src & 0xff000000) >> 24) as u8,
g: ((src & 0x00ff0000) >> 16) as u8,
b: ((src & 0x0000ff00) >> 8) as u8,
a: (src & 0x000000ff) as u8,
}
}
}
impl From<Color> for u32 {
fn from(src: Color) -> Self {
((src.r as u32) << 24) | ((src.g as u32) << 16) | ((src.b as u32) << 8) | (src.a as u32)
}
}
impl Add for Color {
type Output = Self;
/// Calculate the component-wise saturated addition of two colors.
fn add(self, other: Self) -> Self {
Self {
r: self.r.saturating_add(other.r),
g: self.g.saturating_add(other.g),
b: self.b.saturating_add(other.b),
a: self.a.saturating_add(other.a),
}
}
}
impl AddAssign for Color {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl Sub for Color {
type Output = Self;
/// Component-wise subtraction of two colors. Components below 0 are clamped to 0.
fn sub(self, other: Self) -> Self {
Self {
r: self.r.saturating_sub(other.r),
g: self.g.saturating_sub(other.g),
b: self.b.saturating_sub(other.b),
a: self.a.saturating_sub(other.a),
}
}
}
impl SubAssign for Color {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl Mul for Color {
type Output = Color;
/// Calculate the component-wise modulated multiplication of two colors.
///
/// For each `X` in `rgba`, `result.X = a.X * b.X / 255`.
#[allow(clippy::cast_possible_truncation)]
fn mul(self, other: Color) -> Color {
let (r1, r2) = (self.r as u16, other.r as u16);
let (g1, g2) = (self.g as u16, other.g as u16);
let (b1, b2) = (self.b as u16, other.b as u16);
let (a1, a2) = (self.a as u16, other.a as u16);
Self {
r: (r1 * r2 / 255) as u8,
g: (g1 * g2 / 255) as u8,
b: (b1 * b2 / 255) as u8,
a: (a1 * a2 / 255) as u8,
}
}
}
impl MulAssign for Color {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}