Skip to content

Commit

Permalink
Add Color::from_hex
Browse files Browse the repository at this point in the history
  • Loading branch information
vladh committed Jun 30, 2024
1 parent 2ac80f8 commit b49f0b5
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions core/src/color.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
use palette::rgb::{Srgb, Srgba};

#[derive(Debug, thiserror::Error)]
/// Errors that can occur when constructing a [`Color`].
pub enum ColorError {
#[error("The specified hex string is invalid. See supported formats.")]
/// The specified hex string is invalid. See supported formats.
InvalidHex,
}

/// A color in the `sRGB` color space.
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Color {
Expand Down Expand Up @@ -88,6 +96,41 @@ impl Color {
}
}

/// Creates a [`Color`] from a hex string. Supported formats are #aabbcc, #abc, #aabbccff. The
/// “#” is optional. Both uppercase and lowercase are supported.
pub fn from_hex(s: &str) -> Result<Color, ColorError> {
let mut hex = s.replace('#', "").to_lowercase();
let mut n_chars = hex.chars().count();

if n_chars == 3 || n_chars == 4 {
hex = hex
.chars()
.map(|c| c.to_string().repeat(2))
.collect::<Vec<String>>()
.join("");
n_chars *= 2;
} else if n_chars != 6 && n_chars != 8 {
return Err(ColorError::InvalidHex);
}

let Ok(num) = usize::from_str_radix(&hex, 16) else {
return Err(ColorError::InvalidHex);
};

if n_chars == 8 {
let r = (num >> 24) as f32 / 255.0;
let g = ((num >> 16) & 0x00FF) as f32 / 255.0;
let b = ((num >> 8) & 0x0000FF) as f32 / 255.0;
let a = (num & 0x000000FF) as f32 / 255.0;
Ok(Color::from_rgba(r, g, b, a))
} else {
let r = (num >> 16) as f32 / 255.0;
let g = ((num >> 8) & 0x00FF) as f32 / 255.0;
let b = (num & 0x0000FF) as f32 / 255.0;
Ok(Color::from_rgb(r, g, b))
}
}

/// Creates a [`Color`] from its linear RGBA components.
pub fn from_linear_rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
// As described in:
Expand Down

0 comments on commit b49f0b5

Please sign in to comment.