style/values/specified/
background.rs1use crate::derives::*;
8use crate::parser::{Parse, ParserContext};
9use crate::values::generics::background::BackgroundSize as GenericBackgroundSize;
10use crate::values::specified::length::{
11 NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto,
12};
13use cssparser::{match_ignore_ascii_case, Parser};
14use selectors::parser::SelectorParseErrorKind;
15use std::fmt::{self, Write};
16use style_traits::{CssWriter, ParseError, ToCss};
17
18pub type BackgroundSize = GenericBackgroundSize<NonNegativeLengthPercentage>;
20
21impl Parse for BackgroundSize {
22 fn parse<'i, 't>(
23 context: &ParserContext,
24 input: &mut Parser<'i, 't>,
25 ) -> Result<Self, ParseError<'i>> {
26 if let Ok(width) = input.try_parse(|i| NonNegativeLengthPercentageOrAuto::parse(context, i))
27 {
28 let height = input
29 .try_parse(|i| NonNegativeLengthPercentageOrAuto::parse(context, i))
30 .unwrap_or(NonNegativeLengthPercentageOrAuto::auto());
31 return Ok(GenericBackgroundSize::ExplicitSize { width, height });
32 }
33 Ok(try_match_ident_ignore_ascii_case! { input,
34 "cover" => GenericBackgroundSize::Cover,
35 "contain" => GenericBackgroundSize::Contain,
36 })
37 }
38}
39
40#[derive(
42 Clone,
43 Copy,
44 Debug,
45 Eq,
46 MallocSizeOf,
47 Parse,
48 PartialEq,
49 SpecifiedValueInfo,
50 ToComputedValue,
51 ToCss,
52 ToResolvedValue,
53 ToShmem,
54)]
55#[allow(missing_docs)]
56#[value_info(other_values = "repeat-x,repeat-y")]
57pub enum BackgroundRepeatKeyword {
58 Repeat,
59 Space,
60 Round,
61 NoRepeat,
62}
63
64#[derive(
70 Clone,
71 Debug,
72 MallocSizeOf,
73 PartialEq,
74 SpecifiedValueInfo,
75 ToComputedValue,
76 ToResolvedValue,
77 ToShmem,
78)]
79pub struct BackgroundRepeat(pub BackgroundRepeatKeyword, pub BackgroundRepeatKeyword);
80
81impl BackgroundRepeat {
82 pub fn repeat() -> Self {
84 BackgroundRepeat(
85 BackgroundRepeatKeyword::Repeat,
86 BackgroundRepeatKeyword::Repeat,
87 )
88 }
89}
90
91impl ToCss for BackgroundRepeat {
92 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
93 where
94 W: Write,
95 {
96 match (self.0, self.1) {
97 (BackgroundRepeatKeyword::Repeat, BackgroundRepeatKeyword::NoRepeat) => {
98 dest.write_str("repeat-x")
99 },
100 (BackgroundRepeatKeyword::NoRepeat, BackgroundRepeatKeyword::Repeat) => {
101 dest.write_str("repeat-y")
102 },
103 (horizontal, vertical) => {
104 horizontal.to_css(dest)?;
105 if horizontal != vertical {
106 dest.write_char(' ')?;
107 vertical.to_css(dest)?;
108 }
109 Ok(())
110 },
111 }
112 }
113}
114
115impl Parse for BackgroundRepeat {
116 fn parse<'i, 't>(
117 _context: &ParserContext,
118 input: &mut Parser<'i, 't>,
119 ) -> Result<Self, ParseError<'i>> {
120 let ident = input.expect_ident_cloned()?;
121
122 match_ignore_ascii_case! { &ident,
123 "repeat-x" => {
124 return Ok(BackgroundRepeat(BackgroundRepeatKeyword::Repeat, BackgroundRepeatKeyword::NoRepeat));
125 },
126 "repeat-y" => {
127 return Ok(BackgroundRepeat(BackgroundRepeatKeyword::NoRepeat, BackgroundRepeatKeyword::Repeat));
128 },
129 _ => {},
130 }
131
132 let horizontal = match BackgroundRepeatKeyword::from_ident(&ident) {
133 Ok(h) => h,
134 Err(()) => {
135 return Err(
136 input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))
137 );
138 },
139 };
140
141 let vertical = input.try_parse(BackgroundRepeatKeyword::parse).ok();
142 Ok(BackgroundRepeat(horizontal, vertical.unwrap_or(horizontal)))
143 }
144}