@@ -16,16 +16,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
1616
1717const OPAQUE : f32 = 1.0 ;
1818
19- fn serialize_none_or < T > ( dest : & mut impl fmt:: Write , value : & Option < T > ) -> fmt:: Result
20- where
21- T : ToCss ,
22- {
23- match value {
24- Some ( v) => v. to_css ( dest) ,
25- None => dest. write_str ( "none" ) ,
26- }
27- }
28-
2919/// Serialize the alpha copmonent of a color according to the specification.
3020/// <https://drafts.csswg.org/css-color-4/#serializing-alpha-values>
3121#[ inline]
@@ -55,6 +45,34 @@ pub fn serialize_color_alpha(
5545 rounded_alpha. to_css ( dest)
5646}
5747
48+ /// A [`ModernComponent`] can serialize to `none`, `nan`, `infinity` and
49+ /// floating point values.
50+ struct ModernComponent < ' a > ( & ' a Option < f32 > ) ;
51+
52+ impl < ' a > ToCss for ModernComponent < ' a > {
53+ fn to_css < W > ( & self , dest : & mut W ) -> fmt:: Result
54+ where
55+ W : fmt:: Write ,
56+ {
57+ if let Some ( value) = self . 0 {
58+ if value. is_finite ( ) {
59+ value. to_css ( dest)
60+ } else if value. is_nan ( ) {
61+ dest. write_str ( "calc(NaN)" )
62+ } else {
63+ debug_assert ! ( value. is_infinite( ) ) ;
64+ if value. is_sign_negative ( ) {
65+ dest. write_str ( "calc(-infinity)" )
66+ } else {
67+ dest. write_str ( "calc(infinity)" )
68+ }
69+ }
70+ } else {
71+ dest. write_str ( "none" )
72+ }
73+ }
74+ }
75+
5876// Guaratees hue in [0..360)
5977fn normalize_hue ( hue : f32 ) -> f32 {
6078 // <https://drafts.csswg.org/css-values/#angles>
@@ -363,11 +381,11 @@ macro_rules! impl_lab_like {
363381 {
364382 dest. write_str( $fname) ?;
365383 dest. write_str( "(" ) ?;
366- serialize_none_or ( dest , & self . lightness) ?;
384+ ModernComponent ( & self . lightness) . to_css ( dest ) ?;
367385 dest. write_char( ' ' ) ?;
368- serialize_none_or ( dest , & self . a) ?;
386+ ModernComponent ( & self . a) . to_css ( dest ) ?;
369387 dest. write_char( ' ' ) ?;
370- serialize_none_or ( dest , & self . b) ?;
388+ ModernComponent ( & self . b) . to_css ( dest ) ?;
371389 serialize_color_alpha( dest, self . alpha, false ) ?;
372390 dest. write_char( ')' )
373391 }
@@ -454,11 +472,11 @@ macro_rules! impl_lch_like {
454472 {
455473 dest. write_str( $fname) ?;
456474 dest. write_str( "(" ) ?;
457- serialize_none_or ( dest , & self . lightness) ?;
475+ ModernComponent ( & self . lightness) . to_css ( dest ) ?;
458476 dest. write_char( ' ' ) ?;
459- serialize_none_or ( dest , & self . chroma) ?;
477+ ModernComponent ( & self . chroma) . to_css ( dest ) ?;
460478 dest. write_char( ' ' ) ?;
461- serialize_none_or ( dest , & self . hue) ?;
479+ ModernComponent ( & self . hue) . to_css ( dest ) ?;
462480 serialize_color_alpha( dest, self . alpha, false ) ?;
463481 dest. write_char( ')' )
464482 }
@@ -579,11 +597,11 @@ impl ToCss for ColorFunction {
579597 dest. write_str ( "color(" ) ?;
580598 self . color_space . to_css ( dest) ?;
581599 dest. write_char ( ' ' ) ?;
582- serialize_none_or ( dest , & self . c1 ) ?;
600+ ModernComponent ( & self . c1 ) . to_css ( dest ) ?;
583601 dest. write_char ( ' ' ) ?;
584- serialize_none_or ( dest , & self . c2 ) ?;
602+ ModernComponent ( & self . c2 ) . to_css ( dest ) ?;
585603 dest. write_char ( ' ' ) ?;
586- serialize_none_or ( dest , & self . c3 ) ?;
604+ ModernComponent ( & self . c3 ) . to_css ( dest ) ?;
587605
588606 serialize_color_alpha ( dest, self . alpha , false ) ?;
589607
@@ -1495,7 +1513,7 @@ where
14951513 P :: parse_number_or_percentage,
14961514 ) ?;
14971515
1498- let lightness = lightness. map ( |l| l. value ( lightness_range) . max ( 0.0 ) ) ;
1516+ let lightness = lightness. map ( |l| l. value ( lightness_range) ) ;
14991517 let a = a. map ( |a| a. value ( a_b_range) ) ;
15001518 let b = b. map ( |b| b. value ( a_b_range) ) ;
15011519
@@ -1521,8 +1539,8 @@ where
15211539 P :: parse_angle_or_number,
15221540 ) ?;
15231541
1524- let lightness = lightness. map ( |l| l. value ( lightness_range) . max ( 0.0 ) ) ;
1525- let chroma = chroma. map ( |c| c. value ( chroma_range) . max ( 0.0 ) ) ;
1542+ let lightness = lightness. map ( |l| l. value ( lightness_range) ) ;
1543+ let chroma = chroma. map ( |c| c. value ( chroma_range) ) ;
15261544 let hue = hue. map ( |h| normalize_hue ( h. degrees ( ) ) ) ;
15271545
15281546 Ok ( into_color ( lightness, chroma, hue, alpha) )
@@ -1591,3 +1609,45 @@ where
15911609
15921610 Ok ( ( r1, r2, r3, alpha) )
15931611}
1612+
1613+ #[ cfg( test) ]
1614+ mod tests {
1615+ use super :: * ;
1616+
1617+ #[ test]
1618+ fn serialize_modern_components ( ) {
1619+ // None.
1620+ assert_eq ! ( ModernComponent ( & None ) . to_css_string( ) , "none" . to_string( ) ) ;
1621+
1622+ // Finite values.
1623+ assert_eq ! (
1624+ ModernComponent ( & Some ( 10.0 ) ) . to_css_string( ) ,
1625+ "10" . to_string( )
1626+ ) ;
1627+ assert_eq ! (
1628+ ModernComponent ( & Some ( -10.0 ) ) . to_css_string( ) ,
1629+ "-10" . to_string( )
1630+ ) ;
1631+ assert_eq ! ( ModernComponent ( & Some ( 0.0 ) ) . to_css_string( ) , "0" . to_string( ) ) ;
1632+ assert_eq ! (
1633+ ModernComponent ( & Some ( -0.0 ) ) . to_css_string( ) ,
1634+ "0" . to_string( )
1635+ ) ;
1636+
1637+ // Infinite values.
1638+ assert_eq ! (
1639+ ModernComponent ( & Some ( f32 :: INFINITY ) ) . to_css_string( ) ,
1640+ "calc(infinity)" . to_string( )
1641+ ) ;
1642+ assert_eq ! (
1643+ ModernComponent ( & Some ( f32 :: NEG_INFINITY ) ) . to_css_string( ) ,
1644+ "calc(-infinity)" . to_string( )
1645+ ) ;
1646+
1647+ // NaN.
1648+ assert_eq ! (
1649+ ModernComponent ( & Some ( f32 :: NAN ) ) . to_css_string( ) ,
1650+ "calc(NaN)" . to_string( )
1651+ ) ;
1652+ }
1653+ }
0 commit comments