@@ -16,16 +16,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
16
16
17
17
const OPAQUE : f32 = 1.0 ;
18
18
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
-
29
19
/// Serialize the alpha copmonent of a color according to the specification.
30
20
/// <https://drafts.csswg.org/css-color-4/#serializing-alpha-values>
31
21
#[ inline]
@@ -55,6 +45,34 @@ pub fn serialize_color_alpha(
55
45
rounded_alpha. to_css ( dest)
56
46
}
57
47
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
+
58
76
// Guaratees hue in [0..360)
59
77
fn normalize_hue ( hue : f32 ) -> f32 {
60
78
// <https://drafts.csswg.org/css-values/#angles>
@@ -363,11 +381,11 @@ macro_rules! impl_lab_like {
363
381
{
364
382
dest. write_str( $fname) ?;
365
383
dest. write_str( "(" ) ?;
366
- serialize_none_or ( dest , & self . lightness) ?;
384
+ ModernComponent ( & self . lightness) . to_css ( dest ) ?;
367
385
dest. write_char( ' ' ) ?;
368
- serialize_none_or ( dest , & self . a) ?;
386
+ ModernComponent ( & self . a) . to_css ( dest ) ?;
369
387
dest. write_char( ' ' ) ?;
370
- serialize_none_or ( dest , & self . b) ?;
388
+ ModernComponent ( & self . b) . to_css ( dest ) ?;
371
389
serialize_color_alpha( dest, self . alpha, false ) ?;
372
390
dest. write_char( ')' )
373
391
}
@@ -454,11 +472,11 @@ macro_rules! impl_lch_like {
454
472
{
455
473
dest. write_str( $fname) ?;
456
474
dest. write_str( "(" ) ?;
457
- serialize_none_or ( dest , & self . lightness) ?;
475
+ ModernComponent ( & self . lightness) . to_css ( dest ) ?;
458
476
dest. write_char( ' ' ) ?;
459
- serialize_none_or ( dest , & self . chroma) ?;
477
+ ModernComponent ( & self . chroma) . to_css ( dest ) ?;
460
478
dest. write_char( ' ' ) ?;
461
- serialize_none_or ( dest , & self . hue) ?;
479
+ ModernComponent ( & self . hue) . to_css ( dest ) ?;
462
480
serialize_color_alpha( dest, self . alpha, false ) ?;
463
481
dest. write_char( ')' )
464
482
}
@@ -579,11 +597,11 @@ impl ToCss for ColorFunction {
579
597
dest. write_str ( "color(" ) ?;
580
598
self . color_space . to_css ( dest) ?;
581
599
dest. write_char ( ' ' ) ?;
582
- serialize_none_or ( dest , & self . c1 ) ?;
600
+ ModernComponent ( & self . c1 ) . to_css ( dest ) ?;
583
601
dest. write_char ( ' ' ) ?;
584
- serialize_none_or ( dest , & self . c2 ) ?;
602
+ ModernComponent ( & self . c2 ) . to_css ( dest ) ?;
585
603
dest. write_char ( ' ' ) ?;
586
- serialize_none_or ( dest , & self . c3 ) ?;
604
+ ModernComponent ( & self . c3 ) . to_css ( dest ) ?;
587
605
588
606
serialize_color_alpha ( dest, self . alpha , false ) ?;
589
607
@@ -1495,7 +1513,7 @@ where
1495
1513
P :: parse_number_or_percentage,
1496
1514
) ?;
1497
1515
1498
- let lightness = lightness. map ( |l| l. value ( lightness_range) . max ( 0.0 ) ) ;
1516
+ let lightness = lightness. map ( |l| l. value ( lightness_range) ) ;
1499
1517
let a = a. map ( |a| a. value ( a_b_range) ) ;
1500
1518
let b = b. map ( |b| b. value ( a_b_range) ) ;
1501
1519
@@ -1521,8 +1539,8 @@ where
1521
1539
P :: parse_angle_or_number,
1522
1540
) ?;
1523
1541
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) ) ;
1526
1544
let hue = hue. map ( |h| normalize_hue ( h. degrees ( ) ) ) ;
1527
1545
1528
1546
Ok ( into_color ( lightness, chroma, hue, alpha) )
@@ -1591,3 +1609,45 @@ where
1591
1609
1592
1610
Ok ( ( r1, r2, r3, alpha) )
1593
1611
}
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