@@ -10,21 +10,22 @@ use super::{BasicParseError, ParseError, Parser, ToCss, Token};
1010#[ cfg( feature = "serde" ) ]
1111use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
1212
13+ const OPAQUE : f32 = 1.0 ;
14+
1315/// https://w3c.github.io/csswg-drafts/css-color-4/#serializing-alpha-values
1416#[ 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 {
1618 // If the alpha component is full opaque, don't emit the alpha value in CSS.
17- if alpha == 255 {
19+ if alpha == OPAQUE {
1820 return Ok ( ( ) ) ;
1921 }
2022
2123 dest. write_str ( if legacy_syntax { ", " } else { " / " } ) ?;
2224
2325 // 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. ;
2829 }
2930
3031 rounded_alpha. to_css ( dest)
@@ -41,7 +42,7 @@ pub struct RGBA {
4142 /// The blue component.
4243 pub blue : u8 ,
4344 /// The alpha component.
44- pub alpha : u8 ,
45+ pub alpha : f32 ,
4546}
4647
4748impl RGBA {
@@ -54,19 +55,19 @@ impl RGBA {
5455 clamp_unit_f32 ( red) ,
5556 clamp_unit_f32 ( green) ,
5657 clamp_unit_f32 ( blue) ,
57- clamp_unit_f32 ( alpha) ,
58+ alpha. max ( 0.0 ) . min ( 1.0 ) ,
5859 )
5960 }
6061
6162 /// Returns a transparent color.
6263 #[ inline]
6364 pub fn transparent ( ) -> Self {
64- Self :: new ( 0 , 0 , 0 , 0 )
65+ Self :: new ( 0 , 0 , 0 , 0.0 )
6566 }
6667
6768 /// Same thing, but with `u8` values instead of floats in the 0 to 1 range.
6869 #[ 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 {
7071 Self {
7172 red,
7273 green,
@@ -96,7 +97,7 @@ impl RGBA {
9697 /// Returns the alpha channel in a floating point number form, from 0 to 1.
9798 #[ inline]
9899 pub fn alpha_f32 ( & self ) -> f32 {
99- self . alpha as f32 / 255.0
100+ self . alpha
100101 }
101102
102103 /// Parse a color hash, without the leading '#' character.
@@ -107,25 +108,25 @@ impl RGBA {
107108 from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?,
108109 from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?,
109110 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 ,
111112 ) ,
112113 6 => Self :: new (
113114 from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?,
114115 from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?,
115116 from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?,
116- 255 ,
117+ OPAQUE ,
117118 ) ,
118119 4 => Self :: new (
119120 from_hex ( value[ 0 ] ) ? * 17 ,
120121 from_hex ( value[ 1 ] ) ? * 17 ,
121122 from_hex ( value[ 2 ] ) ? * 17 ,
122- from_hex ( value[ 3 ] ) ? * 17 ,
123+ ( from_hex ( value[ 3 ] ) ? * 17 ) as f32 / 255.0 ,
123124 ) ,
124125 3 => Self :: new (
125126 from_hex ( value[ 0 ] ) ? * 17 ,
126127 from_hex ( value[ 1 ] ) ? * 17 ,
127128 from_hex ( value[ 2 ] ) ? * 17 ,
128- 255 ,
129+ OPAQUE ,
129130 ) ,
130131 _ => return Err ( ( ) ) ,
131132 } )
@@ -158,7 +159,7 @@ impl ToCss for RGBA {
158159 where
159160 W : fmt:: Write ,
160161 {
161- let has_alpha = self . alpha != 255 ;
162+ let has_alpha = self . alpha != OPAQUE ;
162163
163164 dest. write_str ( if has_alpha { "rgba(" } else { "rgb(" } ) ?;
164165 self . red . to_css ( dest) ?;
@@ -187,7 +188,7 @@ pub struct LAB {
187188 /// The b-axis component.
188189 pub b : f32 ,
189190 /// The alpha component.
190- pub alpha : u8 ,
191+ pub alpha : f32 ,
191192}
192193
193194/// Color specified by lightness, a- and b-axis components.
@@ -201,14 +202,14 @@ pub struct OKLAB {
201202 /// The b-axis component.
202203 pub b : f32 ,
203204 /// The alpha component.
204- pub alpha : u8 ,
205+ pub alpha : f32 ,
205206}
206207
207208macro_rules! impl_lab_like {
208209 ( $cls: ident, $fname: literal) => {
209210 impl $cls {
210211 /// 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 {
212213 Self {
213214 lightness,
214215 a,
@@ -275,7 +276,7 @@ pub struct LCH {
275276 /// The hue component.
276277 pub hue : f32 ,
277278 /// The alpha component.
278- pub alpha : u8 ,
279+ pub alpha : f32 ,
279280}
280281
281282/// Color specified by lightness, chroma and hue components.
@@ -289,14 +290,14 @@ pub struct OKLCH {
289290 /// The hue component.
290291 pub hue : f32 ,
291292 /// The alpha component.
292- pub alpha : u8 ,
293+ pub alpha : f32 ,
293294}
294295
295296macro_rules! impl_lch_like {
296297 ( $cls: ident, $fname: literal) => {
297298 impl $cls {
298299 /// 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 {
300301 Self {
301302 lightness,
302303 chroma,
@@ -373,7 +374,7 @@ pub enum AbsoluteColor {
373374
374375impl AbsoluteColor {
375376 /// Return the alpha component of any of the schemes within.
376- pub fn alpha ( & self ) -> u8 {
377+ pub fn alpha ( & self ) -> f32 {
377378 match self {
378379 Self :: RGBA ( c) => c. alpha ,
379380 Self :: LAB ( c) => c. alpha ,
@@ -401,11 +402,11 @@ impl ToCss for AbsoluteColor {
401402
402403#[ inline]
403404pub ( crate ) const fn rgb ( red : u8 , green : u8 , blue : u8 ) -> Color {
404- rgba ( red, green, blue, 255 )
405+ rgba ( red, green, blue, OPAQUE )
405406}
406407
407408#[ 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 {
409410 Color :: Absolute ( AbsoluteColor :: RGBA ( RGBA :: new ( red, green, blue, alpha) ) )
410411}
411412
@@ -744,7 +745,7 @@ pub fn parse_color_keyword(ident: &str) -> Result<Color, ()> {
744745 "whitesmoke" => rgb( 245 , 245 , 245 ) ,
745746 "yellowgreen" => rgb( 154 , 205 , 50 ) ,
746747
747- "transparent" => rgba( 0 , 0 , 0 , 0 ) ,
748+ "transparent" => rgba( 0 , 0 , 0 , 0.0 ) ,
748749 "currentcolor" => Color :: CurrentColor ,
749750 }
750751 }
@@ -839,7 +840,7 @@ fn parse_alpha<'i, 't, ComponentParser>(
839840 component_parser : & ComponentParser ,
840841 arguments : & mut Parser < ' i , ' t > ,
841842 uses_commas : bool ,
842- ) -> Result < u8 , ParseError < ' i , ComponentParser :: Error > >
843+ ) -> Result < f32 , ParseError < ' i , ComponentParser :: Error > >
843844where
844845 ComponentParser : ColorComponentParser < ' i > ,
845846{
@@ -849,21 +850,21 @@ where
849850 } else {
850851 arguments. expect_delim ( '/' ) ?;
851852 } ;
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 )
857858 } else {
858- 255
859+ OPAQUE
859860 } )
860861}
861862
862863#[ inline]
863864fn parse_rgb_components_rgb < ' i , ' t , ComponentParser > (
864865 component_parser : & ComponentParser ,
865866 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 > >
867868where
868869 ComponentParser : ColorComponentParser < ' i > ,
869870{
@@ -1014,7 +1015,7 @@ fn parse_lab_like<'i, 't, ComponentParser>(
10141015 arguments : & mut Parser < ' i , ' t > ,
10151016 lightness_range : f32 ,
10161017 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 ,
10181019) -> Result < Color , ParseError < ' i , ComponentParser :: Error > >
10191020where
10201021 ComponentParser : ColorComponentParser < ' i > ,
@@ -1047,7 +1048,7 @@ fn parse_lch_like<'i, 't, ComponentParser>(
10471048 arguments : & mut Parser < ' i , ' t > ,
10481049 lightness_range : f32 ,
10491050 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 ,
10511052) -> Result < Color , ParseError < ' i , ComponentParser :: Error > >
10521053where
10531054 ComponentParser : ColorComponentParser < ' i > ,
0 commit comments