aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorXidorn Quan <me@upsuper.org>2017-05-27 20:06:05 +1000
committerXidorn Quan <me@upsuper.org>2017-05-27 20:45:58 +1000
commit1df685dc40ffae8ffeb1c086a67c4ea66bbdaeb3 (patch)
treeb705d1700b452574ed5b2fd9ddfe4f4585a1bd17 /components
parent9f4a78c2d063d4f21e4100f88663718c75ae373d (diff)
downloadservo-1df685dc40ffae8ffeb1c086a67c4ea66bbdaeb3.tar.gz
servo-1df685dc40ffae8ffeb1c086a67c4ea66bbdaeb3.zip
Add support for symbols() function.
Diffstat (limited to 'components')
-rw-r--r--components/style/counter_style/mod.rs15
-rw-r--r--components/style/gecko/values.rs29
-rw-r--r--components/style/values/generics/mod.rs70
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(")")
+ }
}
}
}