@@ -8,39 +8,46 @@ use serde::{Deserialize, Serialize};
88
99use std:: marker:: PhantomData ;
1010
11- /// Common trait for all color representations.
11+ /// Any color representation
1212pub trait Color {
13+ /// Normalize this color representation to the backend color
1314 fn to_backend_color ( & self ) -> BackendColor ;
1415
16+ /// Convert the RGB representation to the standard RGB tuple
1517 #[ inline( always) ]
1618 fn rgb ( & self ) -> ( u8 , u8 , u8 ) {
1719 self . to_backend_color ( ) . rgb
1820 }
1921
22+ /// Get the alpha channel of the color
2023 #[ inline( always) ]
2124 fn alpha ( & self ) -> f64 {
2225 self . to_backend_color ( ) . alpha
2326 }
2427
28+ /// Mix the color with given opacity
2529 fn mix ( & self , value : f64 ) -> RGBAColor {
2630 let ( r, g, b) = self . rgb ( ) ;
2731 let a = self . alpha ( ) * value;
2832 RGBAColor ( r, g, b, a)
2933 }
3034
35+ /// Convert the color into the RGBA color which is internally used by Plotters
3136 fn to_rgba ( & self ) -> RGBAColor {
3237 let ( r, g, b) = self . rgb ( ) ;
3338 let a = self . alpha ( ) ;
3439 RGBAColor ( r, g, b, a)
3540 }
3641
42+ /// Make a filled style form the color
3743 fn filled ( & self ) -> ShapeStyle
3844 where
3945 Self : Sized ,
4046 {
4147 Into :: < ShapeStyle > :: into ( self ) . filled ( )
4248 }
4349
50+ /// Make a shape style with stroke width from a color
4451 fn stroke_width ( & self , width : u32 ) -> ShapeStyle
4552 where
4653 Self : Sized ,
@@ -55,6 +62,10 @@ impl<T: Color> Color for &'_ T {
5562 }
5663}
5764
65+ /// The RGBA representation of the color, Plotters use RGBA as the internal representation
66+ /// of color
67+ ///
68+ /// If you want to directly create a RGB color with transparency use [RGBColor::mix]
5869#[ derive( Copy , Clone , PartialEq , Debug , Default ) ]
5970#[ cfg_attr( feature = "serialization" , derive( Serialize , Deserialize ) ) ]
6071pub struct RGBAColor ( pub u8 , pub u8 , pub u8 , pub f64 ) ;
@@ -75,11 +86,13 @@ impl From<RGBColor> for RGBAColor {
7586 }
7687}
7788
89+ /// A color in the given palette
7890#[ derive( Copy , Clone , Eq , PartialEq , Hash , Debug , Default ) ]
7991#[ cfg_attr( feature = "serialization" , derive( Serialize , Deserialize ) ) ]
8092pub struct PaletteColor < P : Palette > ( usize , PhantomData < P > ) ;
8193
8294impl < P : Palette > PaletteColor < P > {
95+ /// Pick a color from the palette
8396 pub fn pick ( idx : usize ) -> PaletteColor < P > {
8497 PaletteColor ( idx % P :: COLORS . len ( ) , PhantomData )
8598 }
@@ -95,6 +108,7 @@ impl<P: Palette> Color for PaletteColor<P> {
95108 }
96109}
97110
111+ /// The color described by its RGB value
98112#[ derive( Copy , Clone , Eq , PartialEq , Hash , Debug , Default ) ]
99113#[ cfg_attr( feature = "serialization" , derive( Serialize , Deserialize ) ) ]
100114pub struct RGBColor ( pub u8 , pub u8 , pub u8 ) ;
@@ -114,13 +128,13 @@ impl Color for RGBColor {
114128 }
115129 }
116130}
117-
118131impl BackendStyle for RGBColor {
119132 fn color ( & self ) -> BackendColor {
120133 self . to_backend_color ( )
121134 }
122135}
123136
137+ /// The color described by HSL color space
124138#[ derive( Copy , Clone , PartialEq , Debug , Default ) ]
125139#[ cfg_attr( feature = "serialization" , derive( Serialize , Deserialize ) ) ]
126140pub struct HSLColor ( pub f64 , pub f64 , pub f64 ) ;
@@ -136,18 +150,23 @@ impl Color for HSLColor {
136150 #[ inline( always) ]
137151 #[ allow( clippy:: many_single_char_names) ]
138152 fn to_backend_color ( & self ) -> BackendColor {
153+ // Hue: do not clamp; normalize
154+ // - If >1.0, treat as degrees (divide by 360), then wrap to [0,1)
155+ // - Else, wrap value to [0,1) to accept negatives
139156 let h = if self . 0 > 1.0 {
140157 ( self . 0 / 360.0 ) . rem_euclid ( 1.0 )
141158 } else {
142159 self . 0 . rem_euclid ( 1.0 )
143160 } ;
161+
162+ // Saturation & lightness remain clamped to valid ranges
144163 let s = self . 1 . clamp ( 0.0 , 1.0 ) ;
145164 let l = self . 2 . clamp ( 0.0 , 1.0 ) ;
146165
147166 if s == 0.0 {
148- let v = ( l * 255.0 ) . round ( ) as u8 ;
167+ let value = ( l * 255.0 ) . round ( ) as u8 ;
149168 return BackendColor {
150- rgb : ( v , v , v ) ,
169+ rgb : ( value , value , value ) ,
151170 alpha : 1.0 ,
152171 } ;
153172 }
@@ -159,8 +178,13 @@ impl Color for HSLColor {
159178 } ;
160179 let p = 2.0 * l - q;
161180
162- let cvt = |t : f64 | {
163- let t = t. rem_euclid ( 1.0 ) ;
181+ let cvt = |mut t| {
182+ if t < 0.0 {
183+ t += 1.0 ;
184+ }
185+ if t > 1.0 {
186+ t -= 1.0 ;
187+ }
164188 let value = if t < 1.0 / 6.0 {
165189 p + ( q - p) * 6.0 * t
166190 } else if t < 1.0 / 2.0 {
0 commit comments