@@ -10,21 +10,22 @@ use super::{BasicParseError, ParseError, Parser, ToCss, Token};
10
10
#[ cfg( feature = "serde" ) ]
11
11
use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
12
12
13
+ const OPAQUE : f32 = 1.0 ;
14
+
13
15
/// https://w3c.github.io/csswg-drafts/css-color-4/#serializing-alpha-values
14
16
#[ inline]
15
- fn serialize_alpha ( dest : & mut impl fmt:: Write , alpha : u8 , legacy_syntax : bool ) -> fmt:: Result {
17
+ fn serialize_alpha ( dest : & mut impl fmt:: Write , alpha : f32 , legacy_syntax : bool ) -> fmt:: Result {
16
18
// If the alpha component is full opaque, don't emit the alpha value in CSS.
17
- if alpha == 255 {
19
+ if alpha == OPAQUE {
18
20
return Ok ( ( ) ) ;
19
21
}
20
22
21
23
dest. write_str ( if legacy_syntax { ", " } else { " / " } ) ?;
22
24
23
25
// Try first with two decimal places, then with three.
24
- let alpha_f32 = alpha as f32 / 255.0 ;
25
- let mut rounded_alpha = ( alpha_f32 * 100. ) . round ( ) / 100. ;
26
- if clamp_unit_f32 ( rounded_alpha) != alpha {
27
- rounded_alpha = ( alpha_f32 * 1000. ) . round ( ) / 1000. ;
26
+ let mut rounded_alpha = ( alpha * 100. ) . round ( ) / 100. ;
27
+ if clamp_unit_f32 ( rounded_alpha) != clamp_unit_f32 ( alpha) {
28
+ rounded_alpha = ( alpha * 1000. ) . round ( ) / 1000. ;
28
29
}
29
30
30
31
rounded_alpha. to_css ( dest)
@@ -41,7 +42,7 @@ pub struct RGBA {
41
42
/// The blue component.
42
43
pub blue : u8 ,
43
44
/// The alpha component.
44
- pub alpha : u8 ,
45
+ pub alpha : f32 ,
45
46
}
46
47
47
48
impl RGBA {
@@ -54,19 +55,19 @@ impl RGBA {
54
55
clamp_unit_f32 ( red) ,
55
56
clamp_unit_f32 ( green) ,
56
57
clamp_unit_f32 ( blue) ,
57
- clamp_unit_f32 ( alpha) ,
58
+ alpha. max ( 0.0 ) . min ( 1.0 ) ,
58
59
)
59
60
}
60
61
61
62
/// Returns a transparent color.
62
63
#[ inline]
63
64
pub fn transparent ( ) -> Self {
64
- Self :: new ( 0 , 0 , 0 , 0 )
65
+ Self :: new ( 0 , 0 , 0 , 0.0 )
65
66
}
66
67
67
68
/// Same thing, but with `u8` values instead of floats in the 0 to 1 range.
68
69
#[ inline]
69
- pub const fn new ( red : u8 , green : u8 , blue : u8 , alpha : u8 ) -> Self {
70
+ pub const fn new ( red : u8 , green : u8 , blue : u8 , alpha : f32 ) -> Self {
70
71
Self {
71
72
red,
72
73
green,
@@ -96,7 +97,7 @@ impl RGBA {
96
97
/// Returns the alpha channel in a floating point number form, from 0 to 1.
97
98
#[ inline]
98
99
pub fn alpha_f32 ( & self ) -> f32 {
99
- self . alpha as f32 / 255.0
100
+ self . alpha
100
101
}
101
102
102
103
/// Parse a color hash, without the leading '#' character.
@@ -107,25 +108,25 @@ impl RGBA {
107
108
from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?,
108
109
from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?,
109
110
from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?,
110
- from_hex ( value[ 6 ] ) ? * 16 + from_hex ( value[ 7 ] ) ?,
111
+ ( from_hex ( value[ 6 ] ) ? * 16 + from_hex ( value[ 7 ] ) ?) as f32 / 255.0 ,
111
112
) ,
112
113
6 => Self :: new (
113
114
from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?,
114
115
from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?,
115
116
from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?,
116
- 255 ,
117
+ OPAQUE ,
117
118
) ,
118
119
4 => Self :: new (
119
120
from_hex ( value[ 0 ] ) ? * 17 ,
120
121
from_hex ( value[ 1 ] ) ? * 17 ,
121
122
from_hex ( value[ 2 ] ) ? * 17 ,
122
- from_hex ( value[ 3 ] ) ? * 17 ,
123
+ ( from_hex ( value[ 3 ] ) ? * 17 ) as f32 / 255.0 ,
123
124
) ,
124
125
3 => Self :: new (
125
126
from_hex ( value[ 0 ] ) ? * 17 ,
126
127
from_hex ( value[ 1 ] ) ? * 17 ,
127
128
from_hex ( value[ 2 ] ) ? * 17 ,
128
- 255 ,
129
+ OPAQUE ,
129
130
) ,
130
131
_ => return Err ( ( ) ) ,
131
132
} )
@@ -158,7 +159,7 @@ impl ToCss for RGBA {
158
159
where
159
160
W : fmt:: Write ,
160
161
{
161
- let has_alpha = self . alpha != 255 ;
162
+ let has_alpha = self . alpha != OPAQUE ;
162
163
163
164
dest. write_str ( if has_alpha { "rgba(" } else { "rgb(" } ) ?;
164
165
self . red . to_css ( dest) ?;
@@ -187,7 +188,7 @@ pub struct LAB {
187
188
/// The b-axis component.
188
189
pub b : f32 ,
189
190
/// The alpha component.
190
- pub alpha : u8 ,
191
+ pub alpha : f32 ,
191
192
}
192
193
193
194
/// Color specified by lightness, a- and b-axis components.
@@ -201,14 +202,14 @@ pub struct OKLAB {
201
202
/// The b-axis component.
202
203
pub b : f32 ,
203
204
/// The alpha component.
204
- pub alpha : u8 ,
205
+ pub alpha : f32 ,
205
206
}
206
207
207
208
macro_rules! impl_lab_like {
208
209
( $cls: ident, $fname: literal) => {
209
210
impl $cls {
210
211
/// Construct a new Lab color format with lightness, a, b and alpha components.
211
- pub fn new( lightness: f32 , a: f32 , b: f32 , alpha: u8 ) -> Self {
212
+ pub fn new( lightness: f32 , a: f32 , b: f32 , alpha: f32 ) -> Self {
212
213
Self {
213
214
lightness,
214
215
a,
@@ -275,7 +276,7 @@ pub struct LCH {
275
276
/// The hue component.
276
277
pub hue : f32 ,
277
278
/// The alpha component.
278
- pub alpha : u8 ,
279
+ pub alpha : f32 ,
279
280
}
280
281
281
282
/// Color specified by lightness, chroma and hue components.
@@ -289,14 +290,14 @@ pub struct OKLCH {
289
290
/// The hue component.
290
291
pub hue : f32 ,
291
292
/// The alpha component.
292
- pub alpha : u8 ,
293
+ pub alpha : f32 ,
293
294
}
294
295
295
296
macro_rules! impl_lch_like {
296
297
( $cls: ident, $fname: literal) => {
297
298
impl $cls {
298
299
/// Construct a new color with lightness, chroma and hue components.
299
- pub fn new( lightness: f32 , chroma: f32 , hue: f32 , alpha: u8 ) -> Self {
300
+ pub fn new( lightness: f32 , chroma: f32 , hue: f32 , alpha: f32 ) -> Self {
300
301
Self {
301
302
lightness,
302
303
chroma,
@@ -373,7 +374,7 @@ pub enum AbsoluteColor {
373
374
374
375
impl AbsoluteColor {
375
376
/// Return the alpha component of any of the schemes within.
376
- pub fn alpha ( & self ) -> u8 {
377
+ pub fn alpha ( & self ) -> f32 {
377
378
match self {
378
379
Self :: RGBA ( c) => c. alpha ,
379
380
Self :: LAB ( c) => c. alpha ,
@@ -401,11 +402,11 @@ impl ToCss for AbsoluteColor {
401
402
402
403
#[ inline]
403
404
pub ( crate ) const fn rgb ( red : u8 , green : u8 , blue : u8 ) -> Color {
404
- rgba ( red, green, blue, 255 )
405
+ rgba ( red, green, blue, OPAQUE )
405
406
}
406
407
407
408
#[ inline]
408
- pub ( crate ) const fn rgba ( red : u8 , green : u8 , blue : u8 , alpha : u8 ) -> Color {
409
+ pub ( crate ) const fn rgba ( red : u8 , green : u8 , blue : u8 , alpha : f32 ) -> Color {
409
410
Color :: Absolute ( AbsoluteColor :: RGBA ( RGBA :: new ( red, green, blue, alpha) ) )
410
411
}
411
412
@@ -744,7 +745,7 @@ pub fn parse_color_keyword(ident: &str) -> Result<Color, ()> {
744
745
"whitesmoke" => rgb( 245 , 245 , 245 ) ,
745
746
"yellowgreen" => rgb( 154 , 205 , 50 ) ,
746
747
747
- "transparent" => rgba( 0 , 0 , 0 , 0 ) ,
748
+ "transparent" => rgba( 0 , 0 , 0 , 0.0 ) ,
748
749
"currentcolor" => Color :: CurrentColor ,
749
750
}
750
751
}
@@ -839,7 +840,7 @@ fn parse_alpha<'i, 't, ComponentParser>(
839
840
component_parser : & ComponentParser ,
840
841
arguments : & mut Parser < ' i , ' t > ,
841
842
uses_commas : bool ,
842
- ) -> Result < u8 , ParseError < ' i , ComponentParser :: Error > >
843
+ ) -> Result < f32 , ParseError < ' i , ComponentParser :: Error > >
843
844
where
844
845
ComponentParser : ColorComponentParser < ' i > ,
845
846
{
@@ -849,21 +850,21 @@ where
849
850
} else {
850
851
arguments. expect_delim ( '/' ) ?;
851
852
} ;
852
- clamp_unit_f32 (
853
- component_parser
854
- . parse_number_or_percentage ( arguments ) ?
855
- . unit_value ( ) ,
856
- )
853
+ component_parser
854
+ . parse_number_or_percentage ( arguments ) ?
855
+ . unit_value ( )
856
+ . max ( 0.0 )
857
+ . min ( OPAQUE )
857
858
} else {
858
- 255
859
+ OPAQUE
859
860
} )
860
861
}
861
862
862
863
#[ inline]
863
864
fn parse_rgb_components_rgb < ' i , ' t , ComponentParser > (
864
865
component_parser : & ComponentParser ,
865
866
arguments : & mut Parser < ' i , ' t > ,
866
- ) -> Result < ( u8 , u8 , u8 , u8 ) , ParseError < ' i , ComponentParser :: Error > >
867
+ ) -> Result < ( u8 , u8 , u8 , f32 ) , ParseError < ' i , ComponentParser :: Error > >
867
868
where
868
869
ComponentParser : ColorComponentParser < ' i > ,
869
870
{
@@ -1014,7 +1015,7 @@ fn parse_lab_like<'i, 't, ComponentParser>(
1014
1015
arguments : & mut Parser < ' i , ' t > ,
1015
1016
lightness_range : f32 ,
1016
1017
a_b_range : f32 ,
1017
- into_color : fn ( l : f32 , a : f32 , b : f32 , alpha : u8 ) -> Color ,
1018
+ into_color : fn ( l : f32 , a : f32 , b : f32 , alpha : f32 ) -> Color ,
1018
1019
) -> Result < Color , ParseError < ' i , ComponentParser :: Error > >
1019
1020
where
1020
1021
ComponentParser : ColorComponentParser < ' i > ,
@@ -1047,7 +1048,7 @@ fn parse_lch_like<'i, 't, ComponentParser>(
1047
1048
arguments : & mut Parser < ' i , ' t > ,
1048
1049
lightness_range : f32 ,
1049
1050
chroma_range : f32 ,
1050
- into_color : fn ( l : f32 , c : f32 , h : f32 , alpha : u8 ) -> Color ,
1051
+ into_color : fn ( l : f32 , c : f32 , h : f32 , alpha : f32 ) -> Color ,
1051
1052
) -> Result < Color , ParseError < ' i , ComponentParser :: Error > >
1052
1053
where
1053
1054
ComponentParser : ColorComponentParser < ' i > ,
0 commit comments