@@ -63,101 +63,49 @@ fn normalize_hue(hue: f32) -> f32 {
63
63
#[ repr( C ) ]
64
64
pub struct RGBA {
65
65
/// The red component.
66
- pub red : u8 ,
66
+ pub red : Option < u8 > ,
67
67
/// The green component.
68
- pub green : u8 ,
68
+ pub green : Option < u8 > ,
69
69
/// The blue component.
70
- pub blue : u8 ,
70
+ pub blue : Option < u8 > ,
71
71
/// The alpha component.
72
- pub alpha : f32 ,
72
+ pub alpha : Option < f32 > ,
73
73
}
74
74
75
75
impl RGBA {
76
76
/// Constructs a new RGBA value from float components. It expects the red,
77
77
/// green, blue and alpha channels in that order, and all values will be
78
78
/// clamped to the 0.0 ... 1.0 range.
79
79
#[ inline]
80
- pub fn from_floats ( red : f32 , green : f32 , blue : f32 , alpha : f32 ) -> Self {
80
+ pub fn from_floats (
81
+ red : Option < f32 > ,
82
+ green : Option < f32 > ,
83
+ blue : Option < f32 > ,
84
+ alpha : Option < f32 > ,
85
+ ) -> Self {
81
86
Self :: new (
82
- clamp_unit_f32 ( red ) ,
83
- clamp_unit_f32 ( green ) ,
84
- clamp_unit_f32 ( blue ) ,
85
- alpha. max ( 0.0 ) . min ( 1.0 ) ,
87
+ red . map ( |r| clamp_unit_f32 ( r ) ) ,
88
+ green . map ( |g| clamp_unit_f32 ( g ) ) ,
89
+ blue . map ( |b| clamp_unit_f32 ( b ) ) ,
90
+ alpha. map ( |a| a . clamp ( 0.0 , OPAQUE ) ) ,
86
91
)
87
92
}
88
93
89
- /// Returns a transparent color.
90
- #[ inline]
91
- pub fn transparent ( ) -> Self {
92
- Self :: new ( 0 , 0 , 0 , 0.0 )
93
- }
94
-
95
94
/// Same thing, but with `u8` values instead of floats in the 0 to 1 range.
96
95
#[ inline]
97
- pub const fn new ( red : u8 , green : u8 , blue : u8 , alpha : f32 ) -> Self {
96
+ pub const fn new (
97
+ red : Option < u8 > ,
98
+ green : Option < u8 > ,
99
+ blue : Option < u8 > ,
100
+ alpha : Option < f32 > ,
101
+ ) -> Self {
98
102
Self {
99
103
red,
100
104
green,
101
105
blue,
102
106
alpha,
103
107
}
104
108
}
105
-
106
- /// Returns the red channel in a floating point number form, from 0 to 1.
107
- #[ inline]
108
- pub fn red_f32 ( & self ) -> f32 {
109
- self . red as f32 / 255.0
110
- }
111
-
112
- /// Returns the green channel in a floating point number form, from 0 to 1.
113
- #[ inline]
114
- pub fn green_f32 ( & self ) -> f32 {
115
- self . green as f32 / 255.0
116
- }
117
-
118
- /// Returns the blue channel in a floating point number form, from 0 to 1.
119
- #[ inline]
120
- pub fn blue_f32 ( & self ) -> f32 {
121
- self . blue as f32 / 255.0
122
- }
123
-
124
- /// Returns the alpha channel in a floating point number form, from 0 to 1.
125
- #[ inline]
126
- pub fn alpha_f32 ( & self ) -> f32 {
127
- self . alpha
128
- }
129
-
130
- /// Parse a color hash, without the leading '#' character.
131
- #[ inline]
132
- pub fn parse_hash ( value : & [ u8 ] ) -> Result < Self , ( ) > {
133
- Ok ( match value. len ( ) {
134
- 8 => Self :: new (
135
- from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?,
136
- from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?,
137
- from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?,
138
- ( from_hex ( value[ 6 ] ) ? * 16 + from_hex ( value[ 7 ] ) ?) as f32 / 255.0 ,
139
- ) ,
140
- 6 => Self :: new (
141
- from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?,
142
- from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?,
143
- from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?,
144
- OPAQUE ,
145
- ) ,
146
- 4 => Self :: new (
147
- from_hex ( value[ 0 ] ) ? * 17 ,
148
- from_hex ( value[ 1 ] ) ? * 17 ,
149
- from_hex ( value[ 2 ] ) ? * 17 ,
150
- ( from_hex ( value[ 3 ] ) ? * 17 ) as f32 / 255.0 ,
151
- ) ,
152
- 3 => Self :: new (
153
- from_hex ( value[ 0 ] ) ? * 17 ,
154
- from_hex ( value[ 1 ] ) ? * 17 ,
155
- from_hex ( value[ 2 ] ) ? * 17 ,
156
- OPAQUE ,
157
- ) ,
158
- _ => return Err ( ( ) ) ,
159
- } )
160
- }
161
109
}
162
110
163
111
#[ cfg( feature = "serde" ) ]
@@ -186,17 +134,17 @@ impl ToCss for RGBA {
186
134
where
187
135
W : fmt:: Write ,
188
136
{
189
- let has_alpha = self . alpha != OPAQUE ;
137
+ let has_alpha = self . alpha . unwrap_or ( 0.0 ) != OPAQUE ;
190
138
191
139
dest. write_str ( if has_alpha { "rgba(" } else { "rgb(" } ) ?;
192
- self . red . to_css ( dest) ?;
140
+ self . red . unwrap_or ( 0 ) . to_css ( dest) ?;
193
141
dest. write_str ( ", " ) ?;
194
- self . green . to_css ( dest) ?;
142
+ self . green . unwrap_or ( 0 ) . to_css ( dest) ?;
195
143
dest. write_str ( ", " ) ?;
196
- self . blue . to_css ( dest) ?;
144
+ self . blue . unwrap_or ( 0 ) . to_css ( dest) ?;
197
145
198
146
// Legacy syntax does not allow none components.
199
- serialize_alpha ( dest, Some ( self . alpha ) , true ) ?;
147
+ serialize_alpha ( dest, Some ( self . alpha . unwrap_or ( 0.0 ) ) , true ) ?;
200
148
201
149
dest. write_char ( ')' )
202
150
}
@@ -242,7 +190,7 @@ impl ToCss for Hsl {
242
190
self . lightness . unwrap_or ( 0.0 ) ,
243
191
) ;
244
192
245
- RGBA :: from_floats ( red, green, blue, self . alpha . unwrap_or ( 0.0 ) ) . to_css ( dest)
193
+ RGBA :: from_floats ( Some ( red) , Some ( green) , Some ( blue) , self . alpha ) . to_css ( dest)
246
194
}
247
195
}
248
196
@@ -307,7 +255,7 @@ impl ToCss for Hwb {
307
255
self . blackness . unwrap_or ( 0.0 ) ,
308
256
) ;
309
257
310
- RGBA :: from_floats ( red, green, blue, self . alpha . unwrap_or ( 0.0 ) ) . to_css ( dest)
258
+ RGBA :: from_floats ( Some ( red) , Some ( green) , Some ( blue) , self . alpha ) . to_css ( dest)
311
259
}
312
260
}
313
261
@@ -836,7 +784,7 @@ pub trait FromParsedColor {
836
784
fn from_current_color ( ) -> Self ;
837
785
838
786
/// Construct a new color from red, green, blue and alpha components.
839
- fn from_rgba ( red : u8 , green : u8 , blue : u8 , alpha : f32 ) -> Self ;
787
+ fn from_rgba ( red : Option < u8 > , green : Option < u8 > , blue : Option < u8 > , alpha : Option < f32 > ) -> Self ;
840
788
841
789
/// Construct a new color from hue, saturation, lightness and alpha components.
842
790
fn from_hsl (
@@ -892,6 +840,42 @@ pub trait FromParsedColor {
892
840
) -> Self ;
893
841
}
894
842
843
+ /// Parse a color hash, without the leading '#' character.
844
+ #[ inline]
845
+
846
+ pub fn parse_hash_color < ' i , ' t , P > ( value : & [ u8 ] ) -> Result < P :: Output , ( ) >
847
+ where
848
+ P : ColorParser < ' i > ,
849
+ {
850
+ Ok ( match value. len ( ) {
851
+ 8 => P :: Output :: from_rgba (
852
+ Some ( from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?) ,
853
+ Some ( from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?) ,
854
+ Some ( from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?) ,
855
+ Some ( ( from_hex ( value[ 6 ] ) ? * 16 + from_hex ( value[ 7 ] ) ?) as f32 / 255.0 ) ,
856
+ ) ,
857
+ 6 => P :: Output :: from_rgba (
858
+ Some ( from_hex ( value[ 0 ] ) ? * 16 + from_hex ( value[ 1 ] ) ?) ,
859
+ Some ( from_hex ( value[ 2 ] ) ? * 16 + from_hex ( value[ 3 ] ) ?) ,
860
+ Some ( from_hex ( value[ 4 ] ) ? * 16 + from_hex ( value[ 5 ] ) ?) ,
861
+ Some ( OPAQUE ) ,
862
+ ) ,
863
+ 4 => P :: Output :: from_rgba (
864
+ Some ( from_hex ( value[ 0 ] ) ? * 17 ) ,
865
+ Some ( from_hex ( value[ 1 ] ) ? * 17 ) ,
866
+ Some ( from_hex ( value[ 2 ] ) ? * 17 ) ,
867
+ Some ( ( from_hex ( value[ 3 ] ) ? * 17 ) as f32 / 255.0 ) ,
868
+ ) ,
869
+ 3 => P :: Output :: from_rgba (
870
+ Some ( from_hex ( value[ 0 ] ) ? * 17 ) ,
871
+ Some ( from_hex ( value[ 1 ] ) ? * 17 ) ,
872
+ Some ( from_hex ( value[ 2 ] ) ? * 17 ) ,
873
+ Some ( OPAQUE ) ,
874
+ ) ,
875
+ _ => return Err ( ( ) ) ,
876
+ } )
877
+ }
878
+
895
879
/// Parse a CSS color with the specified [`ColorComponentParser`] and return a
896
880
/// new color value on success.
897
881
pub fn parse_color_with < ' i , ' t , P > (
@@ -904,8 +888,9 @@ where
904
888
let location = input. current_source_location ( ) ;
905
889
let token = input. next ( ) ?;
906
890
match * token {
907
- Token :: Hash ( ref value) | Token :: IDHash ( ref value) => RGBA :: parse_hash ( value. as_bytes ( ) )
908
- . map ( |rgba| P :: Output :: from_rgba ( rgba. red , rgba. green , rgba. blue , rgba. alpha ) ) ,
891
+ Token :: Hash ( ref value) | Token :: IDHash ( ref value) => {
892
+ parse_hash_color :: < P > ( value. as_bytes ( ) )
893
+ }
909
894
Token :: Ident ( ref value) => parse_color_keyword ( & * value) ,
910
895
Token :: Function ( ref name) => {
911
896
let name = name. clone ( ) ;
@@ -925,7 +910,7 @@ impl FromParsedColor for Color {
925
910
}
926
911
927
912
#[ inline]
928
- fn from_rgba ( red : u8 , green : u8 , blue : u8 , alpha : f32 ) -> Self {
913
+ fn from_rgba ( red : Option < u8 > , green : Option < u8 > , blue : Option < u8 > , alpha : Option < f32 > ) -> Self {
929
914
Color :: Rgba ( RGBA :: new ( red, green, blue, alpha) )
930
915
}
931
916
@@ -1164,10 +1149,10 @@ where
1164
1149
}
1165
1150
1166
1151
match_ignore_ascii_case ! { ident ,
1167
- "transparent" => Ok ( Output :: from_rgba( 0 , 0 , 0 , 0.0 ) ) ,
1152
+ "transparent" => Ok ( Output :: from_rgba( Some ( 0 ) , Some ( 0 ) , Some ( 0 ) , Some ( 0.0 ) ) ) ,
1168
1153
"currentcolor" => Ok ( Output :: from_current_color( ) ) ,
1169
1154
_ => keyword( ident)
1170
- . map( |( r, g, b) | Output :: from_rgba( * r , * g , * b , 1.0 ) )
1155
+ . map( |( r, g, b) | Output :: from_rgba( Some ( * r ) , Some ( * g ) , Some ( * b ) , Some ( 1.0 ) ) )
1171
1156
. ok_or( ( ) ) ,
1172
1157
}
1173
1158
}
@@ -1317,48 +1302,47 @@ where
1317
1302
// are parsing the legacy syntax.
1318
1303
let is_legacy_syntax = maybe_red. is_some ( ) && arguments. try_parse ( |p| p. expect_comma ( ) ) . is_ok ( ) ;
1319
1304
1320
- let red: u8 ;
1321
- let green: u8 ;
1322
- let blue: u8 ;
1305
+ let red: Option < u8 > ;
1306
+ let green: Option < u8 > ;
1307
+ let blue: Option < u8 > ;
1323
1308
1324
1309
let alpha = if is_legacy_syntax {
1325
1310
match maybe_red. unwrap ( ) {
1326
1311
NumberOrPercentage :: Number { value } => {
1327
- red = clamp_floor_256_f32 ( value) ;
1328
- green = clamp_floor_256_f32 ( color_parser. parse_number ( arguments) ?) ;
1312
+ red = Some ( clamp_floor_256_f32 ( value) ) ;
1313
+ green = Some ( clamp_floor_256_f32 ( color_parser. parse_number ( arguments) ?) ) ;
1329
1314
arguments. expect_comma ( ) ?;
1330
- blue = clamp_floor_256_f32 ( color_parser. parse_number ( arguments) ?) ;
1315
+ blue = Some ( clamp_floor_256_f32 ( color_parser. parse_number ( arguments) ?) ) ;
1331
1316
}
1332
1317
NumberOrPercentage :: Percentage { unit_value } => {
1333
- red = clamp_unit_f32 ( unit_value) ;
1334
- green = clamp_unit_f32 ( color_parser. parse_percentage ( arguments) ?) ;
1318
+ red = Some ( clamp_unit_f32 ( unit_value) ) ;
1319
+ green = Some ( clamp_unit_f32 ( color_parser. parse_percentage ( arguments) ?) ) ;
1335
1320
arguments. expect_comma ( ) ?;
1336
- blue = clamp_unit_f32 ( color_parser. parse_percentage ( arguments) ?) ;
1321
+ blue = Some ( clamp_unit_f32 ( color_parser. parse_percentage ( arguments) ?) ) ;
1337
1322
}
1338
1323
}
1339
1324
1340
- parse_legacy_alpha ( color_parser, arguments) ?
1325
+ Some ( parse_legacy_alpha ( color_parser, arguments) ?)
1341
1326
} else {
1342
1327
#[ inline]
1343
- fn get_component_value ( c : & Option < NumberOrPercentage > ) -> u8 {
1344
- match * c {
1345
- Some ( NumberOrPercentage :: Number { value } ) => clamp_floor_256_f32 ( value) ,
1346
- Some ( NumberOrPercentage :: Percentage { unit_value } ) => clamp_unit_f32 ( unit_value) ,
1347
- None => 0 ,
1348
- }
1328
+ fn get_component_value ( c : Option < NumberOrPercentage > ) -> Option < u8 > {
1329
+ c. map ( |c| match c {
1330
+ NumberOrPercentage :: Number { value } => clamp_floor_256_f32 ( value) ,
1331
+ NumberOrPercentage :: Percentage { unit_value } => clamp_unit_f32 ( unit_value) ,
1332
+ } )
1349
1333
}
1350
1334
1351
- red = get_component_value ( & maybe_red) ;
1335
+ red = get_component_value ( maybe_red) ;
1352
1336
1353
- green = get_component_value ( & parse_none_or ( arguments, |p| {
1337
+ green = get_component_value ( parse_none_or ( arguments, |p| {
1354
1338
color_parser. parse_number_or_percentage ( p)
1355
1339
} ) ?) ;
1356
1340
1357
- blue = get_component_value ( & parse_none_or ( arguments, |p| {
1341
+ blue = get_component_value ( parse_none_or ( arguments, |p| {
1358
1342
color_parser. parse_number_or_percentage ( p)
1359
1343
} ) ?) ;
1360
1344
1361
- parse_modern_alpha ( color_parser, arguments) ?. unwrap_or ( 0.0 )
1345
+ parse_modern_alpha ( color_parser, arguments) ?
1362
1346
} ;
1363
1347
1364
1348
Ok ( P :: Output :: from_rgba ( red, green, blue, alpha) )
0 commit comments