11use cssparser:: * ;
22use crate :: values:: {
3- length:: { LengthPercentage , LengthPercentageOrAuto } ,
3+ length:: LengthPercentageOrAuto ,
44 position:: * ,
5- percentage:: Percentage ,
65 color:: CssColor ,
76 image:: Image
87} ;
@@ -13,150 +12,6 @@ use itertools::izip;
1312use crate :: printer:: Printer ;
1413use smallvec:: SmallVec ;
1514
16- /// https://www.w3.org/TR/css-backgrounds-3/#background-position
17- #[ derive( Debug , Clone , PartialEq ) ]
18- pub struct BackgroundPosition {
19- x : HorizontalPosition ,
20- y : VerticalPosition
21- }
22-
23- impl Default for BackgroundPosition {
24- fn default ( ) -> BackgroundPosition {
25- BackgroundPosition {
26- x : HorizontalPosition :: Length ( LengthPercentage :: Percentage ( Percentage ( 0.0 ) ) ) ,
27- y : VerticalPosition :: Length ( LengthPercentage :: Percentage ( Percentage ( 0.0 ) ) )
28- }
29- }
30- }
31-
32- impl Parse for BackgroundPosition {
33- fn parse < ' i , ' t > ( input : & mut Parser < ' i , ' t > ) -> Result < Self , ParseError < ' i , ( ) > > {
34- match input. try_parse ( HorizontalPosition :: parse) {
35- Ok ( HorizontalPosition :: Center ) => {
36- // Try parsing a vertical position next.
37- if let Ok ( y) = input. try_parse ( VerticalPosition :: parse) {
38- return Ok ( BackgroundPosition {
39- x : HorizontalPosition :: Center ,
40- y
41- } )
42- }
43-
44- // If it didn't work, assume the first actually represents a y position,
45- // and the next is an x position. e.g. `center left` rather than `left center`.
46- let x = input
47- . try_parse ( HorizontalPosition :: parse)
48- . unwrap_or ( HorizontalPosition :: Center ) ;
49- let y = VerticalPosition :: Center ;
50- return Ok ( BackgroundPosition { x, y } )
51- } ,
52- Ok ( x @ HorizontalPosition :: Length ( _) ) => {
53- // If we got a length as the first component, then the second must
54- // be a keyword or length (not a side offset).
55- if let Ok ( y_keyword) = input. try_parse ( VerticalPositionKeyword :: parse) {
56- let y = VerticalPosition :: Side ( y_keyword, None ) ;
57- return Ok ( BackgroundPosition { x, y } ) ;
58- }
59- if let Ok ( y_lp) = input. try_parse ( LengthPercentage :: parse) {
60- let y = VerticalPosition :: Length ( y_lp) ;
61- return Ok ( BackgroundPosition { x, y } ) ;
62- }
63- let y = VerticalPosition :: Center ;
64- let _ = input. try_parse ( |i| i. expect_ident_matching ( "center" ) ) ;
65- return Ok ( BackgroundPosition { x, y } ) ;
66- }
67- Ok ( HorizontalPosition :: Side ( x_keyword, lp) ) => {
68- // If we got a horizontal side keyword (and optional offset), expect another for the vertical side.
69- // e.g. `left center` or `left 20px center`
70- if input. try_parse ( |i| i. expect_ident_matching ( "center" ) ) . is_ok ( ) {
71- let x = HorizontalPosition :: Side ( x_keyword, lp) ;
72- let y = VerticalPosition :: Center ;
73- return Ok ( BackgroundPosition { x, y } ) ;
74- }
75-
76- // e.g. `left top`, `left top 20px`, `left 20px top`, or `left 20px top 20px`
77- if let Ok ( y_keyword) = input. try_parse ( VerticalPositionKeyword :: parse) {
78- let y_lp = input. try_parse ( LengthPercentage :: parse) . ok ( ) ;
79- let x = HorizontalPosition :: Side ( x_keyword, lp) ;
80- let y = VerticalPosition :: Side ( y_keyword, y_lp) ;
81- return Ok ( BackgroundPosition { x, y } ) ;
82- }
83-
84- // If we didn't get a vertical side keyword (e.g. `left 20px`), then apply the offset to the vertical side.
85- let x = HorizontalPosition :: Side ( x_keyword, None ) ;
86- let y = lp. map_or ( VerticalPosition :: Center , VerticalPosition :: Length ) ;
87- return Ok ( BackgroundPosition { x, y } ) ;
88- }
89- _ => { }
90- }
91-
92- // If the horizontal position didn't parse, then it must be out of order. Try vertical position keyword.
93- let y_keyword = VerticalPositionKeyword :: parse ( input) ?;
94- let lp_and_x_pos: Result < _ , ParseError < ( ) > > = input. try_parse ( |i| {
95- let y_lp = i. try_parse ( LengthPercentage :: parse) . ok ( ) ;
96- if let Ok ( x_keyword) = i. try_parse ( HorizontalPositionKeyword :: parse) {
97- let x_lp = i. try_parse ( LengthPercentage :: parse) . ok ( ) ;
98- let x_pos = HorizontalPosition :: Side ( x_keyword, x_lp) ;
99- return Ok ( ( y_lp, x_pos) ) ;
100- }
101- i. expect_ident_matching ( "center" ) ?;
102- let x_pos = HorizontalPosition :: Center ;
103- Ok ( ( y_lp, x_pos) )
104- } ) ;
105-
106- if let Ok ( ( y_lp, x) ) = lp_and_x_pos {
107- let y = VerticalPosition :: Side ( y_keyword, y_lp) ;
108- return Ok ( BackgroundPosition { x, y } ) ;
109- }
110-
111- let x = HorizontalPosition :: Center ;
112- let y = VerticalPosition :: Side ( y_keyword, None ) ;
113- Ok ( BackgroundPosition { x, y } )
114- }
115- }
116-
117- impl ToCss for BackgroundPosition {
118- fn to_css < W > ( & self , dest : & mut Printer < W > ) -> std:: fmt:: Result where W : std:: fmt:: Write {
119- match ( & self . x , & self . y ) {
120- (
121- x_pos @ & HorizontalPosition :: Side ( _, Some ( _) ) ,
122- & VerticalPosition :: Length ( ref y_lp) ,
123- ) => {
124- x_pos. to_css ( dest) ?;
125- dest. write_str ( " top " ) ?;
126- y_lp. to_css ( dest)
127- } ,
128- (
129- & HorizontalPosition :: Length ( ref x_lp) ,
130- y_pos @ & VerticalPosition :: Side ( _, Some ( _) ) ,
131- ) => {
132- dest. write_str ( "left " ) ?;
133- x_lp. to_css ( dest) ?;
134- dest. write_str ( " " ) ?;
135- y_pos. to_css ( dest)
136- } ,
137- (
138- & HorizontalPosition :: Length ( ref x_lp) ,
139- & VerticalPosition :: Center
140- ) => {
141- // `center` is assumed if omitted.
142- x_lp. to_css ( dest)
143- } ,
144- (
145- & HorizontalPosition :: Length ( ref x_lp) ,
146- & VerticalPosition :: Length ( LengthPercentage :: Percentage ( Percentage ( y_lp) ) )
147- ) if y_lp == 0.5 => {
148- // 50% is equivalent to `center`, which may be omitted.
149- x_lp. to_css ( dest)
150- } ,
151- ( x_pos, y_pos) => {
152- x_pos. to_css ( dest) ?;
153- dest. write_str ( " " ) ?;
154- y_pos. to_css ( dest)
155- } ,
156- }
157- }
158- }
159-
16015/// https://www.w3.org/TR/css-backgrounds-3/#background-size
16116#[ derive( Debug , Clone , PartialEq ) ]
16217pub enum BackgroundSize {
@@ -302,7 +157,7 @@ enum_property!(BackgroundBox,
302157pub struct Background {
303158 image : Image ,
304159 color : CssColor ,
305- position : BackgroundPosition ,
160+ position : Position ,
306161 repeat : BackgroundRepeat ,
307162 size : BackgroundSize ,
308163 attachment : BackgroundAttachment ,
@@ -313,7 +168,7 @@ pub struct Background {
313168impl Parse for Background {
314169 fn parse < ' i , ' t > ( input : & mut Parser < ' i , ' t > ) -> Result < Self , ParseError < ' i , ( ) > > {
315170 let mut color: Option < CssColor > = None ;
316- let mut position: Option < BackgroundPosition > = None ;
171+ let mut position: Option < Position > = None ;
317172 let mut size: Option < BackgroundSize > = None ;
318173 let mut image: Option < Image > = None ;
319174 let mut repeat: Option < BackgroundRepeat > = None ;
@@ -331,7 +186,7 @@ impl Parse for Background {
331186 }
332187
333188 if position. is_none ( ) {
334- if let Ok ( value) = input. try_parse ( BackgroundPosition :: parse) {
189+ if let Ok ( value) = input. try_parse ( Position :: parse) {
335190 position = Some ( value) ;
336191
337192 size = input. try_parse ( |input| {
@@ -417,7 +272,7 @@ impl ToCss for Background {
417272 needs_space = true ;
418273 }
419274
420- if self . position != BackgroundPosition :: default ( ) || self . size != BackgroundSize :: default ( ) {
275+ if self . position != Position :: default ( ) || self . size != BackgroundSize :: default ( ) {
421276 if needs_space {
422277 dest. write_str ( " " ) ?;
423278 }
@@ -537,7 +392,7 @@ impl PropertyHandler for BackgroundHandler {
537392 CssColor :: default ( )
538393 } ,
539394 image,
540- position : BackgroundPosition {
395+ position : Position {
541396 x : x_position,
542397 y : y_position
543398 } ,
@@ -563,7 +418,7 @@ impl PropertyHandler for BackgroundHandler {
563418
564419 match ( & mut x_positions, & mut y_positions) {
565420 ( Some ( x_positions) , Some ( y_positions) ) if x_positions. len ( ) == y_positions. len ( ) => {
566- let positions = izip ! ( x_positions. drain( ..) , y_positions. drain( ..) ) . map ( |( x, y) | BackgroundPosition { x, y} ) . collect ( ) ;
421+ let positions = izip ! ( x_positions. drain( ..) , y_positions. drain( ..) ) . map ( |( x, y) | Position { x, y} ) . collect ( ) ;
567422 decls. push ( Property :: BackgroundPosition ( positions) )
568423 }
569424 _ => {
0 commit comments