@@ -435,7 +435,7 @@ impl Color {
435435 Color { red, green, blue, alpha } . to_linear_srgb ( ) . map_rgb ( |channel| channel * alpha)
436436 }
437437
438- /// Create a [Color] from a hue, saturation, lightness and alpha (all between 0 and 1)
438+ /// Create a [Color] from a hue, saturation, lightness, and alpha (all between 0 and 1)
439439 ///
440440 /// # Examples
441441 /// ```
@@ -477,6 +477,25 @@ impl Color {
477477 Color { red, green, blue, alpha }
478478 }
479479
480+ /// Create a [Color] from hue, saturation, value, and alpha (all between 0 and 1).
481+ pub fn from_hsva ( hue : f32 , saturation : f32 , value : f32 , alpha : f32 ) -> Color {
482+ let h_prime = ( hue * 6. ) % 6. ;
483+ let i = h_prime as i32 ;
484+ let f = h_prime - i as f32 ;
485+ let p = value * ( 1. - saturation) ;
486+ let q = value * ( 1. - f * saturation) ;
487+ let t = value * ( 1. - ( 1. - f) * saturation) ;
488+ let ( red, green, blue) = match i % 6 {
489+ 0 => ( value, t, p) ,
490+ 1 => ( q, value, p) ,
491+ 2 => ( p, value, t) ,
492+ 3 => ( p, q, value) ,
493+ 4 => ( t, p, value) ,
494+ _ => ( value, p, q) ,
495+ } ;
496+ Color { red, green, blue, alpha }
497+ }
498+
480499 /// Return the `red` component.
481500 ///
482501 /// # Examples
@@ -922,11 +941,27 @@ impl Color {
922941 [ hue, saturation, lightness, self . alpha ]
923942 }
924943
925- // TODO: Readd formatting
944+ // TODO: This incorrectly handles gamma/linear and premultiplied alpha. For now, this can only be used for overlay drawing, not artwork.
945+ // TODO: Remove this function and have overlays directly use the hex colors and not use the `Color` struct at all.
946+ /// Creates a color from a 6-character RGB hex string (without a # prefix).
947+ ///
948+ /// ```
949+ /// use core_types::color::Color;
950+ /// let color = Color::from_rgb_hex_for_overlays("7C67FA").unwrap();
951+ /// ```
952+ pub fn from_rgb_hex_for_overlays ( color_str : & str ) -> Option < Color > {
953+ if color_str. len ( ) != 6 {
954+ return None ;
955+ }
956+ let r = u8:: from_str_radix ( & color_str[ 0 ..2 ] , 16 ) . ok ( ) ?;
957+ let g = u8:: from_str_radix ( & color_str[ 2 ..4 ] , 16 ) . ok ( ) ?;
958+ let b = u8:: from_str_radix ( & color_str[ 4 ..6 ] , 16 ) . ok ( ) ?;
959+
960+ Some ( Color :: from_rgb8_srgb ( r, g, b) )
961+ }
926962
927- /// Creates a color from a 8-character RGBA hex string (without a # prefix).
963+ /// Creates a color from an 8-character RGBA hex string (without a # prefix).
928964 ///
929- /// # Examples
930965 /// ```
931966 /// use core_types::color::Color;
932967 /// let color = Color::from_rgba_str("7C67FA61").unwrap();
@@ -935,12 +970,12 @@ impl Color {
935970 if color_str. len ( ) != 8 {
936971 return None ;
937972 }
938- let r = u8:: from_str_radix ( & color_str[ 0 ..2 ] , 16 ) . ok ( ) ?;
939- let g = u8:: from_str_radix ( & color_str[ 2 ..4 ] , 16 ) . ok ( ) ?;
940- let b = u8:: from_str_radix ( & color_str[ 4 ..6 ] , 16 ) . ok ( ) ?;
941- let a = u8:: from_str_radix ( & color_str[ 6 ..8 ] , 16 ) . ok ( ) ?;
973+ let red = u8:: from_str_radix ( & color_str[ 0 ..2 ] , 16 ) . ok ( ) ? as f32 / 255. ;
974+ let green = u8:: from_str_radix ( & color_str[ 2 ..4 ] , 16 ) . ok ( ) ? as f32 / 255. ;
975+ let blue = u8:: from_str_radix ( & color_str[ 4 ..6 ] , 16 ) . ok ( ) ? as f32 / 255. ;
976+ let alpha = u8:: from_str_radix ( & color_str[ 6 ..8 ] , 16 ) . ok ( ) ? as f32 / 255. ;
942977
943- Some ( Color :: from_rgba8_srgb ( r , g , b , a ) )
978+ Some ( Color { red , green , blue , alpha } )
944979 }
945980
946981 /// Creates a color from a 6-character RGB hex string (without a # prefix).
@@ -953,11 +988,23 @@ impl Color {
953988 if color_str. len ( ) != 6 {
954989 return None ;
955990 }
956- let r = u8:: from_str_radix ( & color_str[ 0 ..2 ] , 16 ) . ok ( ) ?;
957- let g = u8:: from_str_radix ( & color_str[ 2 ..4 ] , 16 ) . ok ( ) ?;
958- let b = u8:: from_str_radix ( & color_str[ 4 ..6 ] , 16 ) . ok ( ) ?;
991+ let red = u8:: from_str_radix ( & color_str[ 0 ..2 ] , 16 ) . ok ( ) ? as f32 / 255. ;
992+ let green = u8:: from_str_radix ( & color_str[ 2 ..4 ] , 16 ) . ok ( ) ? as f32 / 255. ;
993+ let blue = u8:: from_str_radix ( & color_str[ 4 ..6 ] , 16 ) . ok ( ) ? as f32 / 255. ;
959994
960- Some ( Color :: from_rgb8_srgb ( r, g, b) )
995+ Some ( Color { red, green, blue, alpha : 1. } )
996+ }
997+
998+ /// Creates a color from a hex color code string with an optional `#` prefix, such as `#RRGGBB`, `RRGGBB`, `#RRGGBBAA`, or `RRGGBBAA`.
999+ /// Returns `None` for invalid or unrecognized strings.
1000+ #[ cfg( feature = "std" ) ]
1001+ pub fn from_hex_str ( hex : & str ) -> Option < Color > {
1002+ let hex = hex. trim ( ) . trim_start_matches ( '#' ) ;
1003+ match hex. len ( ) {
1004+ 6 => Color :: from_rgb_str ( hex) ,
1005+ 8 => Color :: from_rgba_str ( hex) ,
1006+ _ => None ,
1007+ }
9611008 }
9621009
9631010 /// Linearly interpolates between two colors based on t.
0 commit comments