/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! Specified types for CSS values related to backgrounds. use crate::parser::{Parse, ParserContext}; use crate::values::generics::background::BackgroundSize as GenericBackgroundSize; use crate::values::specified::length::{ NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto, }; use cssparser::Parser; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError, ToCss}; /// A specified value for the `background-size` property. pub type BackgroundSize = GenericBackgroundSize; impl Parse for BackgroundSize { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { if let Ok(width) = input.try_parse(|i| NonNegativeLengthPercentageOrAuto::parse(context, i)) { let height = input .try_parse(|i| NonNegativeLengthPercentageOrAuto::parse(context, i)) .unwrap_or(NonNegativeLengthPercentageOrAuto::auto()); return Ok(GenericBackgroundSize::ExplicitSize { width, height }); } Ok(try_match_ident_ignore_ascii_case! { input, "cover" => GenericBackgroundSize::Cover, "contain" => GenericBackgroundSize::Contain, }) } } /// One of the keywords for `background-repeat`. #[derive( Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] #[allow(missing_docs)] #[value_info(other_values = "repeat-x,repeat-y")] pub enum BackgroundRepeatKeyword { Repeat, Space, Round, NoRepeat, } /// The value of the `background-repeat` property, with `repeat-x` / `repeat-y` /// represented as the combination of `no-repeat` and `repeat` in the opposite /// axes. /// /// https://drafts.csswg.org/css-backgrounds/#the-background-repeat #[derive( Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem, )] pub struct BackgroundRepeat(pub BackgroundRepeatKeyword, pub BackgroundRepeatKeyword); impl BackgroundRepeat { /// Returns the `repeat repeat` value. pub fn repeat() -> Self { BackgroundRepeat( BackgroundRepeatKeyword::Repeat, BackgroundRepeatKeyword::Repeat, ) } } impl ToCss for BackgroundRepeat { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, { match (self.0, self.1) { (BackgroundRepeatKeyword::Repeat, BackgroundRepeatKeyword::NoRepeat) => { dest.write_str("repeat-x") }, (BackgroundRepeatKeyword::NoRepeat, BackgroundRepeatKeyword::Repeat) => { dest.write_str("repeat-y") }, (horizontal, vertical) => { horizontal.to_css(dest)?; if horizontal != vertical { dest.write_char(' ')?; vertical.to_css(dest)?; } Ok(()) }, } } } impl Parse for BackgroundRepeat { fn parse<'i, 't>( _context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { let ident = input.expect_ident_cloned()?; match_ignore_ascii_case! { &ident, "repeat-x" => { return Ok(BackgroundRepeat(BackgroundRepeatKeyword::Repeat, BackgroundRepeatKeyword::NoRepeat)); }, "repeat-y" => { return Ok(BackgroundRepeat(BackgroundRepeatKeyword::NoRepeat, BackgroundRepeatKeyword::Repeat)); }, _ => {}, } let horizontal = match BackgroundRepeatKeyword::from_ident(&ident) { Ok(h) => h, Err(()) => { return Err( input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())) ); }, }; let vertical = input.try_parse(BackgroundRepeatKeyword::parse).ok(); Ok(BackgroundRepeat(horizontal, vertical.unwrap_or(horizontal))) } }