mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Add support for symbols() function.
This commit is contained in:
parent
9f4a78c2d0
commit
1df685dc40
3 changed files with 97 additions and 17 deletions
|
@ -337,7 +337,7 @@ impl ToCss for System {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-counter-styles/#typedef-symbol
|
/// https://drafts.csswg.org/css-counter-styles/#typedef-symbol
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Symbol {
|
pub enum Symbol {
|
||||||
/// <string>
|
/// <string>
|
||||||
String(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
|
/// https://drafts.csswg.org/css-counter-styles/#counter-style-negative
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Negative(pub Symbol, pub Option<Symbol>);
|
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
|
/// 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>);
|
pub struct Symbols(pub Vec<Symbol>);
|
||||||
|
|
||||||
impl Parse for Symbols {
|
impl Parse for Symbols {
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
//! Different kind of helpers to interact with Gecko values.
|
//! Different kind of helpers to interact with Gecko values.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
use counter_style::Symbol;
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use gecko_bindings::bindings;
|
|
||||||
use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord};
|
use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord};
|
||||||
use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
|
use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
|
||||||
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
|
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
|
||||||
|
use nsstring::{nsACString, nsCString};
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use values::{Auto, Either, ExtremumLength, None_, Normal};
|
use values::{Auto, Either, ExtremumLength, None_, Normal};
|
||||||
use values::computed::{Angle, LengthOrPercentage, LengthOrPercentageOrAuto};
|
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 {
|
impl CounterStyleOrNone {
|
||||||
/// Convert this counter style to a Gecko CounterStylePtr.
|
/// Convert this counter style to a Gecko CounterStylePtr.
|
||||||
pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) {
|
pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) {
|
||||||
let ptr = match self {
|
use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
|
||||||
CounterStyleOrNone::None_ => atom!("none"),
|
use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
|
||||||
CounterStyleOrNone::Name(name) => name.0,
|
match self {
|
||||||
};
|
CounterStyleOrNone::None_ => unsafe {
|
||||||
unsafe {
|
set_name(gecko_value, atom!("none").into_addrefed());
|
||||||
bindings::Gecko_SetCounterStyleToName(gecko_value, ptr.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) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! Generic types that share their serialization implementations
|
//! Generic types that share their serialization implementations
|
||||||
//! for both specified and computed values.
|
//! 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 cssparser::Parser;
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use parser::{Parse, ParserContext};
|
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
|
/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
|
||||||
///
|
///
|
||||||
/// Since wherever <counter-style> is used, 'none' is a valid value as
|
/// Since wherever <counter-style> is used, 'none' is a valid value as
|
||||||
/// well, we combine them into one type to make code simpler.
|
/// well, we combine them into one type to make code simpler.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum CounterStyleOrNone {
|
pub enum CounterStyleOrNone {
|
||||||
/// none
|
/// none
|
||||||
None_,
|
None_,
|
||||||
/// <counter-style-name>
|
/// <counter-style-name>
|
||||||
Name(CustomIdent),
|
Name(CustomIdent),
|
||||||
|
/// symbols()
|
||||||
|
Symbols(SymbolsType, Symbols),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CounterStyleOrNone {
|
impl CounterStyleOrNone {
|
||||||
|
@ -90,12 +117,32 @@ impl CounterStyleOrNone {
|
||||||
no_viewport_percentage!(CounterStyleOrNone);
|
no_viewport_percentage!(CounterStyleOrNone);
|
||||||
|
|
||||||
impl Parse for CounterStyleOrNone {
|
impl Parse for CounterStyleOrNone {
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
input.try(|input| {
|
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
||||||
parse_counter_style_name(input).map(CounterStyleOrNone::Name)
|
return Ok(CounterStyleOrNone::Name(name));
|
||||||
}).or_else(|_| {
|
}
|
||||||
input.expect_ident_matching("none").map(|_| CounterStyleOrNone::None_)
|
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 {
|
match self {
|
||||||
&CounterStyleOrNone::None_ => dest.write_str("none"),
|
&CounterStyleOrNone::None_ => dest.write_str("none"),
|
||||||
&CounterStyleOrNone::Name(ref name) => name.to_css(dest),
|
&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(")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue