Merge branch 'master' into feature/canvas-interaction
This commit is contained in:
commit
67b2ccb4d5
8 changed files with 621 additions and 5 deletions
|
|
@ -1,10 +1,16 @@
|
|||
#[cfg(feature = "palette")]
|
||||
use palette::rgb::{Srgb, Srgba};
|
||||
|
||||
/// A color in the sRGB color space.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
pub struct Color {
|
||||
/// Red component, 0.0 - 1.0
|
||||
pub r: f32,
|
||||
/// Green component, 0.0 - 1.0
|
||||
pub g: f32,
|
||||
/// Blue component, 0.0 - 1.0
|
||||
pub b: f32,
|
||||
/// Transparency, 0.0 - 1.0
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
|
|
@ -33,11 +39,45 @@ impl Color {
|
|||
a: 0.0,
|
||||
};
|
||||
|
||||
/// Creates a new [`Color`].
|
||||
///
|
||||
/// In debug mode, it will panic if the values are not in the correct
|
||||
/// range: 0.0 - 1.0
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
pub fn new(r: f32, g: f32, b: f32, a: f32) -> Color {
|
||||
debug_assert!(
|
||||
(0.0..=1.0).contains(&r),
|
||||
"Red component must be on [0, 1]"
|
||||
);
|
||||
debug_assert!(
|
||||
(0.0..=1.0).contains(&g),
|
||||
"Green component must be on [0, 1]"
|
||||
);
|
||||
debug_assert!(
|
||||
(0.0..=1.0).contains(&b),
|
||||
"Blue component must be on [0, 1]"
|
||||
);
|
||||
debug_assert!(
|
||||
(0.0..=1.0).contains(&a),
|
||||
"Alpha component must be on [0, 1]"
|
||||
);
|
||||
|
||||
Color { r, g, b, a }
|
||||
}
|
||||
|
||||
/// Creates a [`Color`] from its RGB components.
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
pub const fn from_rgb(r: f32, g: f32, b: f32) -> Color {
|
||||
Color { r, g, b, a: 1.0 }
|
||||
Color::from_rgba(r, g, b, 1.0f32)
|
||||
}
|
||||
|
||||
/// Creates a [`Color`] from its RGBA components.
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
pub const fn from_rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
|
||||
Color { r, g, b, a }
|
||||
}
|
||||
|
||||
/// Creates a [`Color`] from its RGB8 components.
|
||||
|
|
@ -80,16 +120,114 @@ impl Color {
|
|||
self.a,
|
||||
]
|
||||
}
|
||||
|
||||
/// Inverts the [`Color`] in-place.
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
pub fn invert(&mut self) {
|
||||
self.r = 1.0f32 - self.r;
|
||||
self.b = 1.0f32 - self.g;
|
||||
self.g = 1.0f32 - self.b;
|
||||
}
|
||||
|
||||
/// Returns the inverted [`Color`].
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
pub fn inverse(self) -> Color {
|
||||
Color::new(1.0f32 - self.r, 1.0f32 - self.g, 1.0f32 - self.b, self.a)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for Color {
|
||||
fn from([r, g, b]: [f32; 3]) -> Self {
|
||||
Color { r, g, b, a: 1.0 }
|
||||
Color::new(r, g, b, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 4]> for Color {
|
||||
fn from([r, g, b, a]: [f32; 4]) -> Self {
|
||||
Color { r, g, b, a }
|
||||
Color::new(r, g, b, a)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "palette")]
|
||||
/// Converts from palette's `Srgba` type to a [`Color`].
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
impl From<Srgba> for Color {
|
||||
fn from(srgba: Srgba) -> Self {
|
||||
Color::new(srgba.red, srgba.green, srgba.blue, srgba.alpha)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "palette")]
|
||||
/// Converts from [`Color`] to palette's `Srgba` type.
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
impl From<Color> for Srgba {
|
||||
fn from(c: Color) -> Self {
|
||||
Srgba::new(c.r, c.g, c.b, c.a)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "palette")]
|
||||
/// Converts from palette's `Srgb` type to a [`Color`].
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
impl From<Srgb> for Color {
|
||||
fn from(srgb: Srgb) -> Self {
|
||||
Color::new(srgb.red, srgb.green, srgb.blue, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "palette")]
|
||||
/// Converts from [`Color`] to palette's `Srgb` type.
|
||||
///
|
||||
/// [`Color`]: struct.Color.html
|
||||
/// [`Srgb`]: ../palette/rgb/type.Srgb.html
|
||||
impl From<Color> for Srgb {
|
||||
fn from(c: Color) -> Self {
|
||||
Srgb::new(c.r, c.g, c.b)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "palette")]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use palette::Blend;
|
||||
|
||||
#[test]
|
||||
fn srgba_traits() {
|
||||
let c = Color::from_rgb(0.5, 0.4, 0.3);
|
||||
// Round-trip conversion to the palette:Srgba type
|
||||
let s: Srgba = c.into();
|
||||
let r: Color = s.into();
|
||||
assert_eq!(c, r);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn color_manipulation() {
|
||||
let c1 = Color::from_rgb(0.5, 0.4, 0.3);
|
||||
let c2 = Color::from_rgb(0.2, 0.5, 0.3);
|
||||
|
||||
// Convert to linear color for manipulation
|
||||
let l1 = Srgba::from(c1).into_linear();
|
||||
let l2 = Srgba::from(c2).into_linear();
|
||||
|
||||
// Take the lighter of each of the RGB components
|
||||
let lighter = l1.lighten(l2);
|
||||
|
||||
// Convert back to our Color
|
||||
let r: Color = Srgba::from_linear(lighter).into();
|
||||
assert_eq!(
|
||||
r,
|
||||
Color {
|
||||
r: 0.5,
|
||||
g: 0.5,
|
||||
b: 0.3,
|
||||
a: 1.0
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue