Skip to main content

valo_geometry/
color.rs

1/// `Color` is a straight-alpha sRGB color.
2///
3/// Components conventionally range from zero to one but are not clamped by the
4/// constructors. Valo premultiplies at the GPU boundary and blends in sRGB space.
5#[derive(Clone, Copy, Debug, Default, PartialEq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct Color {
8    /// `r` is the straight red component.
9    pub r: f32,
10    /// `g` is the straight green component.
11    pub g: f32,
12    /// `b` is the straight blue component.
13    pub b: f32,
14    /// `a` is the alpha component.
15    pub a: f32,
16}
17
18impl Color {
19    /// `TRANSPARENT` is transparent black.
20    pub const TRANSPARENT: Color = Color::rgba(0.0, 0.0, 0.0, 0.0);
21    /// `BLACK` is opaque black.
22    pub const BLACK: Color = Color::rgba(0.0, 0.0, 0.0, 1.0);
23    /// `WHITE` is opaque white.
24    pub const WHITE: Color = Color::rgba(1.0, 1.0, 1.0, 1.0);
25
26    /// `rgba` creates a color without clamping its components.
27    pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
28        Self { r, g, b, a }
29    }
30
31    /// `rgb` creates an opaque color without clamping its components.
32    pub const fn rgb(r: f32, g: f32, b: f32) -> Self {
33        Self { r, g, b, a: 1.0 }
34    }
35
36    /// `from_rgba8` converts 8-bit sRGB components to floating point.
37    pub fn from_rgba8(r: u8, g: u8, b: u8, a: u8) -> Self {
38        Self {
39            r: r as f32 / 255.0,
40            g: g as f32 / 255.0,
41            b: b as f32 / 255.0,
42            a: a as f32 / 255.0,
43        }
44    }
45
46    /// `with_alpha` replaces the alpha component without changing RGB.
47    pub fn with_alpha(self, a: f32) -> Self {
48        Self { a, ..self }
49    }
50
51    /// `components` returns straight components as `[r, g, b, a]`.
52    pub fn components(self) -> [f32; 4] {
53        [self.r, self.g, self.b, self.a]
54    }
55
56    /// `premultiplied` returns `[r × a, g × a, b × a, a]`.
57    pub fn premultiplied(self) -> [f32; 4] {
58        [self.r * self.a, self.g * self.a, self.b * self.a, self.a]
59    }
60
61    /// `is_opaque` reports whether alpha is at least one.
62    pub fn is_opaque(self) -> bool {
63        self.a >= 1.0
64    }
65}