@@ -220,6 +220,40 @@ pub enum SrgbColor {
220220 } ,
221221}
222222
223+ /// https://w3c.github.io/csswg-drafts/css-color-4/#hsl-to-rgb
224+ #[ inline]
225+ pub fn hsl_to_rgb ( hue : f32 , saturation : f32 , lightness : f32 ) -> ( f32 , f32 , f32 ) {
226+ let mut hue = hue;
227+
228+ if hue < 0. {
229+ hue += 1. ;
230+ }
231+
232+ let f = |n : f32 | -> f32 {
233+ let k = ( hue. mul_add ( 12. , n) ) % 12. ;
234+ let a = saturation * lightness. min ( 1. - lightness) ;
235+
236+ a. mul_add ( -( -1f32 ) . max ( ( k - 3. ) . min ( 9. - k) . min ( 1. ) ) , lightness)
237+ } ;
238+
239+ ( f ( 0. ) , f ( 8. ) , f ( 4. ) )
240+ }
241+
242+ /// https://w3c.github.io/csswg-drafts/css-color-4/#hwb-to-rgb
243+ #[ inline]
244+ pub fn hwb_to_rgb ( hue : f32 , whiteness : f32 , blackness : f32 ) -> ( f32 , f32 , f32 ) {
245+ if whiteness + blackness >= 1. {
246+ let gray = whiteness / ( whiteness + blackness) ;
247+ return ( gray, gray, gray) ;
248+ }
249+
250+ let ( red, green, blue) = hsl_to_rgb ( hue, 1. , 0.5 ) ;
251+
252+ let f = |c : f32 | -> f32 { c. mul_add ( 1. - whiteness - blackness, whiteness) } ;
253+
254+ ( f ( red) , f ( green) , f ( blue) )
255+ }
256+
223257impl SrgbColor {
224258 /// Construct an sRGB color from its component channels.
225259 pub fn new (
@@ -1539,56 +1573,6 @@ where
15391573 ) ) )
15401574}
15411575
1542- /// https://w3c.github.io/csswg-drafts/css-color-4/#hwb-to-rgb
1543- #[ inline]
1544- pub fn hwb_to_rgb ( h : f32 , w : f32 , b : f32 ) -> ( f32 , f32 , f32 ) {
1545- if w + b >= 1.0 {
1546- let gray = w / ( w + b) ;
1547- return ( gray, gray, gray) ;
1548- }
1549-
1550- let ( mut red, mut green, mut blue) = hsl_to_rgb ( h, 1.0 , 0.5 ) ;
1551- let x = 1.0 - w - b;
1552- red = red * x + w;
1553- green = green * x + w;
1554- blue = blue * x + w;
1555- ( red, green, blue)
1556- }
1557-
1558- /// https://w3c.github.io/csswg-drafts/css-color-4/#hsl-to-rgb
1559- /// except with h pre-multiplied by 3, to avoid some rounding errors.
1560- #[ inline]
1561- pub fn hsl_to_rgb ( hue : f32 , saturation : f32 , lightness : f32 ) -> ( f32 , f32 , f32 ) {
1562- fn hue_to_rgb ( m1 : f32 , m2 : f32 , mut h3 : f32 ) -> f32 {
1563- if h3 < 0. {
1564- h3 += 3.
1565- }
1566- if h3 > 3. {
1567- h3 -= 3.
1568- }
1569- if h3 * 2. < 1. {
1570- m1 + ( m2 - m1) * h3 * 2.
1571- } else if h3 * 2. < 3. {
1572- m2
1573- } else if h3 < 2. {
1574- m1 + ( m2 - m1) * ( 2. - h3) * 2.
1575- } else {
1576- m1
1577- }
1578- }
1579- let m2 = if lightness <= 0.5 {
1580- lightness * ( saturation + 1. )
1581- } else {
1582- lightness + saturation - lightness * saturation
1583- } ;
1584- let m1 = lightness * 2. - m2;
1585- let hue_times_3 = hue * 3. ;
1586- let red = hue_to_rgb ( m1, m2, hue_times_3 + 1. ) ;
1587- let green = hue_to_rgb ( m1, m2, hue_times_3) ;
1588- let blue = hue_to_rgb ( m1, m2, hue_times_3 - 1. ) ;
1589- ( red, green, blue)
1590- }
1591-
15921576#[ cfg( test) ]
15931577mod tests {
15941578 use crate :: ParserInput ;
0 commit comments