diff options
author | Xidorn Quan <me@upsuper.org> | 2017-05-27 20:06:05 +1000 |
---|---|---|
committer | Xidorn Quan <me@upsuper.org> | 2017-05-27 20:45:58 +1000 |
commit | 1df685dc40ffae8ffeb1c086a67c4ea66bbdaeb3 (patch) | |
tree | b705d1700b452574ed5b2fd9ddfe4f4585a1bd17 /components | |
parent | 9f4a78c2d063d4f21e4100f88663718c75ae373d (diff) | |
download | servo-1df685dc40ffae8ffeb1c086a67c4ea66bbdaeb3.tar.gz servo-1df685dc40ffae8ffeb1c086a67c4ea66bbdaeb3.zip |
Add support for symbols() function.
Diffstat (limited to 'components')
-rw-r--r-- | components/style/counter_style/mod.rs | 15 | ||||
-rw-r--r-- | components/style/gecko/values.rs | 29 | ||||
-rw-r--r-- | components/style/values/generics/mod.rs | 70 |
3 files changed, 97 insertions, 17 deletions
diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 20cd638b758..a018f9b8286 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -337,7 +337,7 @@ impl ToCss for System { } /// https://drafts.csswg.org/css-counter-styles/#typedef-symbol -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Symbol { /// <string> String(String), @@ -367,6 +367,17 @@ impl ToCss for Symbol { } } +impl Symbol { + /// Returns whether this symbol is allowed in symbols() function. + pub fn is_allowed_in_symbols(&self) -> bool { + match self { + // Identifier is not allowed. + &Symbol::Ident(_) => false, + _ => true, + } + } +} + /// https://drafts.csswg.org/css-counter-styles/#counter-style-negative #[derive(Debug, Clone)] pub struct Negative(pub Symbol, pub Option<Symbol>); @@ -495,7 +506,7 @@ impl ToCss for Fallback { } /// https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Symbols(pub Vec<Symbol>); impl Parse for Symbols { diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index cb288e866fb..f2a92e1ec89 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -7,11 +7,12 @@ //! Different kind of helpers to interact with Gecko values. use app_units::Au; +use counter_style::Symbol; use cssparser::RGBA; -use gecko_bindings::bindings; use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord}; use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius}; use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; +use nsstring::{nsACString, nsCString}; use std::cmp::max; use values::{Auto, Either, ExtremumLength, None_, Normal}; use values::computed::{Angle, LengthOrPercentage, LengthOrPercentageOrAuto}; @@ -397,12 +398,26 @@ pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au { impl CounterStyleOrNone { /// Convert this counter style to a Gecko CounterStylePtr. pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) { - let ptr = match self { - CounterStyleOrNone::None_ => atom!("none"), - CounterStyleOrNone::Name(name) => name.0, - }; - unsafe { - bindings::Gecko_SetCounterStyleToName(gecko_value, ptr.into_addrefed()); + use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name; + use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols; + match self { + CounterStyleOrNone::None_ => unsafe { + set_name(gecko_value, atom!("none").into_addrefed()); + }, + CounterStyleOrNone::Name(name) => unsafe { + set_name(gecko_value, name.0.into_addrefed()); + }, + CounterStyleOrNone::Symbols(symbols_type, symbols) => { + let symbols: Vec<_> = symbols.0.iter().map(|symbol| match *symbol { + Symbol::String(ref s) => nsCString::from(s), + Symbol::Ident(_) => unreachable!("Should not have identifier in symbols()"), + }).collect(); + let symbols: Vec<_> = symbols.iter() + .map(|symbol| symbol as &nsACString as *const _) + .collect(); + unsafe { set_symbols(gecko_value, symbols_type.to_gecko_keyword(), + symbols.as_ptr(), symbols.len() as u32) }; + } } } } diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 1efc617b0b0..0bb4107bfc3 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -5,7 +5,7 @@ //! Generic types that share their serialization implementations //! for both specified and computed values. -use counter_style::parse_counter_style_name; +use counter_style::{Symbols, parse_counter_style_name}; use cssparser::Parser; use euclid::size::Size2D; use parser::{Parse, ParserContext}; @@ -63,16 +63,43 @@ impl<L: ToCss> ToCss for BorderRadiusSize<L> { } } +// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type +define_css_keyword_enum! { SymbolsType: + "cyclic" => Cyclic, + "numeric" => Numeric, + "alphabetic" => Alphabetic, + "symbolic" => Symbolic, + "fixed" => Fixed, +} +add_impls_for_keyword_enum!(SymbolsType); + +#[cfg(feature = "gecko")] +impl SymbolsType { + /// Convert symbols type to their corresponding Gecko values. + pub fn to_gecko_keyword(self) -> u8 { + use gecko_bindings::structs; + match self { + SymbolsType::Cyclic => structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as u8, + SymbolsType::Numeric => structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as u8, + SymbolsType::Alphabetic => structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as u8, + SymbolsType::Symbolic => structs::NS_STYLE_COUNTER_SYSTEM_SYMBOLIC as u8, + SymbolsType::Fixed => structs::NS_STYLE_COUNTER_SYSTEM_FIXED as u8, + } + } +} + /// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style /// /// Since wherever <counter-style> is used, 'none' is a valid value as /// well, we combine them into one type to make code simpler. -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum CounterStyleOrNone { /// none None_, /// <counter-style-name> Name(CustomIdent), + /// symbols() + Symbols(SymbolsType, Symbols), } impl CounterStyleOrNone { @@ -90,12 +117,32 @@ impl CounterStyleOrNone { no_viewport_percentage!(CounterStyleOrNone); impl Parse for CounterStyleOrNone { - fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> { - input.try(|input| { - parse_counter_style_name(input).map(CounterStyleOrNone::Name) - }).or_else(|_| { - input.expect_ident_matching("none").map(|_| CounterStyleOrNone::None_) - }) + fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { + if let Ok(name) = input.try(|i| parse_counter_style_name(i)) { + return Ok(CounterStyleOrNone::Name(name)); + } + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(CounterStyleOrNone::None_); + } + if input.try(|i| i.expect_function_matching("symbols")).is_ok() { + return input.parse_nested_block(|input| { + let symbols_type = input.try(|i| SymbolsType::parse(i)) + .unwrap_or(SymbolsType::Symbolic); + let symbols = Symbols::parse(context, input)?; + // There must be at least two symbols for alphabetic or + // numeric system. + if (symbols_type == SymbolsType::Alphabetic || + symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 { + return Err(()); + } + // Identifier is not allowed in symbols() function. + if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) { + return Err(()); + } + Ok(CounterStyleOrNone::Symbols(symbols_type, symbols)) + }); + } + Err(()) } } @@ -105,6 +152,13 @@ impl ToCss for CounterStyleOrNone { match self { &CounterStyleOrNone::None_ => dest.write_str("none"), &CounterStyleOrNone::Name(ref name) => name.to_css(dest), + &CounterStyleOrNone::Symbols(ref symbols_type, ref symbols) => { + dest.write_str("symbols(")?; + symbols_type.to_css(dest)?; + dest.write_str(" ")?; + symbols.to_css(dest)?; + dest.write_str(")") + } } } } |