Auto merge of #20178 - servo:derive-all-the-things, r=emilio

Derive ToCss for some more stuff

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20178)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-03-03 10:17:42 -05:00 committed by GitHub
commit 0c9be9f776
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 133 additions and 233 deletions

View file

@ -8,7 +8,7 @@
use Atom; use Atom;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser}; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
use cssparser::{Parser, Token, serialize_identifier, CowRcStr}; use cssparser::{Parser, Token, CowRcStr};
use error_reporting::{ContextualParseError, ParseErrorReporter}; use error_reporting::{ContextualParseError, ParseErrorReporter};
#[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors; #[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
#[cfg(feature = "gecko")] use gecko_bindings::structs::{ nsCSSCounterDesc, nsCSSValue }; #[cfg(feature = "gecko")] use gecko_bindings::structs::{ nsCSSCounterDesc, nsCSSValue };
@ -391,12 +391,12 @@ impl ToCss for System {
/// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol> /// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol>
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue)] #[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
pub enum Symbol { pub enum Symbol {
/// <string> /// <string>
String(String), String(String),
/// <ident> /// <custom-ident>
Ident(String), Ident(CustomIdent),
// Not implemented: // Not implemented:
// /// <image> // /// <image>
// Image(Image), // Image(Image),
@ -407,24 +407,16 @@ impl Parse for Symbol {
let location = input.current_source_location(); let location = input.current_source_location();
match *input.next()? { match *input.next()? {
Token::QuotedString(ref s) => Ok(Symbol::String(s.as_ref().to_owned())), Token::QuotedString(ref s) => Ok(Symbol::String(s.as_ref().to_owned())),
Token::Ident(ref s) => Ok(Symbol::Ident(s.as_ref().to_owned())), Token::Ident(ref s) => {
Ok(Symbol::Ident(
CustomIdent::from_ident(location, s, &[])?,
))
}
ref t => Err(location.new_unexpected_token_error(t.clone())), ref t => Err(location.new_unexpected_token_error(t.clone())),
} }
} }
} }
impl ToCss for Symbol {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
Symbol::String(ref s) => s.to_css(dest),
Symbol::Ident(ref s) => serialize_identifier(s, dest),
}
}
}
impl Symbol { impl Symbol {
/// Returns whether this symbol is allowed in symbols() function. /// Returns whether this symbol is allowed in symbols() function.
pub fn is_allowed_in_symbols(&self) -> bool { pub fn is_allowed_in_symbols(&self) -> bool {
@ -550,7 +542,8 @@ impl Parse for Fallback {
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols> /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols>
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue)] #[css(iterable)]
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
pub struct Symbols(pub Vec<Symbol>); pub struct Symbols(pub Vec<Symbol>);
impl Parse for Symbols { impl Parse for Symbols {
@ -570,22 +563,6 @@ impl Parse for Symbols {
} }
} }
impl ToCss for Symbols {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut iter = self.0.iter();
let first = iter.next().expect("expected at least one symbol");
first.to_css(dest)?;
for item in iter {
dest.write_char(' ')?;
item.to_css(dest)?;
}
Ok(())
}
}
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-additive-symbols> /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-additive-symbols>
#[derive(Clone, Debug, ToCss)] #[derive(Clone, Debug, ToCss)]
pub struct AdditiveSymbols(pub Vec<AdditiveTuple>); pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);

View file

@ -313,7 +313,7 @@ impl ToNsCssValue for counter_style::Symbol {
fn convert(self, nscssvalue: &mut nsCSSValue) { fn convert(self, nscssvalue: &mut nsCSSValue) {
match self { match self {
counter_style::Symbol::String(s) => nscssvalue.set_string(&s), counter_style::Symbol::String(s) => nscssvalue.set_string(&s),
counter_style::Symbol::Ident(s) => nscssvalue.set_ident(&s), counter_style::Symbol::Ident(s) => nscssvalue.set_ident_from_atom(&s.0),
} }
} }
} }

View file

@ -4719,16 +4719,15 @@ fn static_assert() {
pub fn set_text_emphasis_style(&mut self, v: longhands::text_emphasis_style::computed_value::T) { pub fn set_text_emphasis_style(&mut self, v: longhands::text_emphasis_style::computed_value::T) {
use properties::longhands::text_emphasis_style::computed_value::T; use properties::longhands::text_emphasis_style::computed_value::T;
use properties::longhands::text_emphasis_style::ShapeKeyword; use properties::longhands::text_emphasis_style::{FillMode, ShapeKeyword};
self.clear_text_emphasis_style_if_string(); self.clear_text_emphasis_style_if_string();
let (te, s) = match v { let (te, s) = match v {
T::None => (structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE, ""), T::None => (structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE, ""),
T::Keyword(ref keyword) => { T::Keyword(ref keyword) => {
let fill = if keyword.fill { let fill = match keyword.fill {
structs::NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED FillMode::Filled => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED,
} else { FillMode::Open => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN,
structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN
}; };
let shape = match keyword.shape { let shape = match keyword.shape {
ShapeKeyword::Dot => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOT, ShapeKeyword::Dot => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOT,
@ -4763,7 +4762,7 @@ fn static_assert() {
pub fn clone_text_emphasis_style(&self) -> longhands::text_emphasis_style::computed_value::T { pub fn clone_text_emphasis_style(&self) -> longhands::text_emphasis_style::computed_value::T {
use properties::longhands::text_emphasis_style::computed_value::{T, KeywordValue}; use properties::longhands::text_emphasis_style::computed_value::{T, KeywordValue};
use properties::longhands::text_emphasis_style::ShapeKeyword; use properties::longhands::text_emphasis_style::{FillMode, ShapeKeyword};
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE as u8 { if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE as u8 {
return T::None; return T::None;
@ -4771,7 +4770,11 @@ fn static_assert() {
return T::String(self.gecko.mTextEmphasisStyleString.to_string()); return T::String(self.gecko.mTextEmphasisStyleString.to_string());
} }
let fill = self.gecko.mTextEmphasisStyle & structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN as u8 == 0; let fill = match self.gecko.mTextEmphasisStyle as u32 {
structs::NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED => FillMode::Filled,
structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN => FillMode::Open,
_ => panic!("Unexpected value in style struct for text-emphasis-style property"),
};
let shape = let shape =
match self.gecko.mTextEmphasisStyle as u32 & !structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN { match self.gecko.mTextEmphasisStyle as u32 & !structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN {
structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOT => ShapeKeyword::Dot, structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOT => ShapeKeyword::Dot,

View file

@ -26,10 +26,9 @@ use properties::{LonghandId, ShorthandId};
use servo_arc::Arc; use servo_arc::Arc;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{cmp, ptr}; use std::{cmp, ptr};
use std::fmt::{self, Write};
use std::mem::{self, ManuallyDrop}; use std::mem::{self, ManuallyDrop};
#[cfg(feature = "gecko")] use hash::FnvHashMap; #[cfg(feature = "gecko")] use hash::FnvHashMap;
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::ParseError;
use super::ComputedValues; use super::ComputedValues;
use values::{CSSFloat, CustomIdent, Either}; use values::{CSSFloat, CustomIdent, Either};
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero}; use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
@ -79,7 +78,7 @@ pub fn nscsspropertyid_is_animatable(property: nsCSSPropertyID) -> bool {
/// a shorthand with at least one transitionable longhand component, or an unsupported property. /// a shorthand with at least one transitionable longhand component, or an unsupported property.
// NB: This needs to be here because it needs all the longhands generated // NB: This needs to be here because it needs all the longhands generated
// beforehand. // beforehand.
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToCss)]
pub enum TransitionProperty { pub enum TransitionProperty {
/// A shorthand. /// A shorthand.
Shorthand(ShorthandId), Shorthand(ShorthandId),
@ -90,19 +89,6 @@ pub enum TransitionProperty {
Unsupported(CustomIdent), Unsupported(CustomIdent),
} }
impl ToCss for TransitionProperty {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
TransitionProperty::Shorthand(ref id) => dest.write_str(id.name()),
TransitionProperty::Longhand(ref id) => dest.write_str(id.name()),
TransitionProperty::Unsupported(ref id) => id.to_css(dest),
}
}
}
trivial_to_computed_value!(TransitionProperty); trivial_to_computed_value!(TransitionProperty);
impl TransitionProperty { impl TransitionProperty {

View file

@ -199,11 +199,8 @@ ${helpers.predefined_type(
animation_value_type="discrete" animation_value_type="discrete"
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-style"> spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-style">
use computed_values::writing_mode::T as WritingMode; use computed_values::writing_mode::T as WritingMode;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
pub mod computed_value { pub mod computed_value {
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
#[cfg_attr(feature = "servo", derive(ToComputedValue))] #[cfg_attr(feature = "servo", derive(ToComputedValue))]
@ -213,9 +210,9 @@ ${helpers.predefined_type(
String(String), String(String),
} }
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
pub struct KeywordValue { pub struct KeywordValue {
pub fill: bool, pub fill: super::FillMode,
pub shape: super::ShapeKeyword, pub shape: super::ShapeKeyword,
} }
} }
@ -227,55 +224,22 @@ ${helpers.predefined_type(
String(String), String(String),
} }
#[derive(Clone, Debug, MallocSizeOf, PartialEq)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
pub enum KeywordValue { pub enum KeywordValue {
Fill(bool), Fill(FillMode),
Shape(ShapeKeyword), Shape(ShapeKeyword),
FillAndShape(bool, ShapeKeyword), FillAndShape(FillMode, ShapeKeyword),
}
impl ToCss for KeywordValue {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
if let Some(fill) = self.fill() {
if fill {
dest.write_str("filled")?;
} else {
dest.write_str("open")?;
}
}
if let Some(shape) = self.shape() {
if self.fill().is_some() {
dest.write_str(" ")?;
}
shape.to_css(dest)?;
}
Ok(())
}
}
impl ToCss for computed_value::KeywordValue {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if self.fill {
dest.write_str("filled")?;
} else {
dest.write_str("open")?;
}
dest.write_str(" ")?;
self.shape.to_css(dest)
}
} }
impl KeywordValue { impl KeywordValue {
fn fill(&self) -> Option<bool> { fn fill(&self) -> Option<FillMode> {
match *self { match *self {
KeywordValue::Fill(fill) | KeywordValue::Fill(fill) |
KeywordValue::FillAndShape(fill,_) => Some(fill), KeywordValue::FillAndShape(fill, _) => Some(fill),
_ => None, _ => None,
} }
} }
fn shape(&self) -> Option<ShapeKeyword> { fn shape(&self) -> Option<ShapeKeyword> {
match *self { match *self {
KeywordValue::Shape(shape) | KeywordValue::Shape(shape) |
@ -285,6 +249,12 @@ ${helpers.predefined_type(
} }
} }
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToCss)]
pub enum FillMode {
Filled,
Open,
}
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
pub enum ShapeKeyword { pub enum ShapeKeyword {
Dot, Dot,
@ -295,7 +265,8 @@ ${helpers.predefined_type(
} }
impl ShapeKeyword { impl ShapeKeyword {
pub fn char(&self, fill: bool) -> &str { pub fn char(&self, fill: FillMode) -> &str {
let fill = fill == FillMode::Filled;
match *self { match *self {
ShapeKeyword::Dot => if fill { "\u{2022}" } else { "\u{25e6}" }, ShapeKeyword::Dot => if fill { "\u{2022}" } else { "\u{25e6}" },
ShapeKeyword::Circle => if fill { "\u{25cf}" } else { "\u{25cb}" }, ShapeKeyword::Circle => if fill { "\u{25cf}" } else { "\u{25cb}" },
@ -330,7 +301,7 @@ ${helpers.predefined_type(
ShapeKeyword::Sesame ShapeKeyword::Sesame
}; };
computed_value::T::Keyword(computed_value::KeywordValue { computed_value::T::Keyword(computed_value::KeywordValue {
fill: keyword.fill().unwrap_or(true), fill: keyword.fill().unwrap_or(FillMode::Filled),
shape: keyword.shape().unwrap_or(default_shape), shape: keyword.shape().unwrap_or(default_shape),
}) })
}, },
@ -354,8 +325,10 @@ ${helpers.predefined_type(
} }
} }
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) pub fn parse<'i, 't>(
-> Result<SpecifiedValue, ParseError<'i>> { _context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<SpecifiedValue, ParseError<'i>> {
if input.try(|input| input.expect_ident_matching("none")).is_ok() { if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(SpecifiedValue::None); return Ok(SpecifiedValue::None);
} }
@ -366,21 +339,17 @@ ${helpers.predefined_type(
} }
// Handle a pair of keywords // Handle a pair of keywords
let mut shape = input.try(ShapeKeyword::parse); let mut shape = input.try(ShapeKeyword::parse).ok();
let fill = if input.try(|input| input.expect_ident_matching("filled")).is_ok() { let fill = input.try(FillMode::parse).ok();
Some(true) if shape.is_none() {
} else if input.try(|input| input.expect_ident_matching("open")).is_ok() { shape = input.try(ShapeKeyword::parse).ok();
Some(false)
} else { None };
if shape.is_err() {
shape = input.try(ShapeKeyword::parse);
} }
// At least one of shape or fill must be handled // At least one of shape or fill must be handled
let keyword_value = match (fill, shape) { let keyword_value = match (fill, shape) {
(Some(fill), Ok(shape)) => KeywordValue::FillAndShape(fill,shape), (Some(fill), Some(shape)) => KeywordValue::FillAndShape(fill, shape),
(Some(fill), Err(_)) => KeywordValue::Fill(fill), (Some(fill), None) => KeywordValue::Fill(fill),
(None, Ok(shape)) => KeywordValue::Shape(shape), (None, Some(shape)) => KeywordValue::Shape(shape),
_ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)), _ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
}; };
Ok(SpecifiedValue::Keyword(keyword_value)) Ok(SpecifiedValue::Keyword(keyword_value))

View file

@ -800,6 +800,16 @@ pub enum LonghandId {
% endfor % endfor
} }
impl ToCss for LonghandId {
#[inline]
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
dest.write_str(self.name())
}
}
impl fmt::Debug for LonghandId { impl fmt::Debug for LonghandId {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.name()) formatter.write_str(self.name())
@ -1130,7 +1140,7 @@ where
} }
/// An identifier for a given shorthand property. /// An identifier for a given shorthand property.
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
pub enum ShorthandId { pub enum ShorthandId {
% for property in data.shorthands: % for property in data.shorthands:
/// ${property.name} /// ${property.name}
@ -1138,6 +1148,16 @@ pub enum ShorthandId {
% endfor % endfor
} }
impl ToCss for ShorthandId {
#[inline]
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
dest.write_str(self.name())
}
}
impl ShorthandId { impl ShorthandId {
/// Get the name for this shorthand property. /// Get the name for this shorthand property.
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {

View file

@ -71,7 +71,7 @@ impl DeepCloneWithLock for DocumentRule {
} }
/// A URL matching function for a `@document` rule's condition. /// A URL matching function for a `@document` rule's condition.
#[derive(Clone, Debug)] #[derive(Clone, Debug, ToCss)]
pub enum UrlMatchingFunction { pub enum UrlMatchingFunction {
/// Exact URL matching function. It evaluates to true whenever the /// Exact URL matching function. It evaluates to true whenever the
/// URL of the document being styled is exactly the URL given. /// URL of the document being styled is exactly the URL given.
@ -81,6 +81,7 @@ pub enum UrlMatchingFunction {
/// function as an initial substring (which is true when the two /// function as an initial substring (which is true when the two
/// strings are equal). When the argument is the empty string, /// strings are equal). When the argument is the empty string,
/// it evaluates to true for all documents. /// it evaluates to true for all documents.
#[css(function)]
UrlPrefix(String), UrlPrefix(String),
/// Domain matching function. It evaluates to true whenever the URL /// Domain matching function. It evaluates to true whenever the URL
/// of the document being styled has a host subcomponent and that /// of the document being styled has a host subcomponent and that
@ -88,11 +89,13 @@ pub enum UrlMatchingFunction {
/// function or a final substring of the host component is a /// function or a final substring of the host component is a
/// period (U+002E) immediately followed by the argument to the /// period (U+002E) immediately followed by the argument to the
/// domain() function. /// domain() function.
#[css(function)]
Domain(String), Domain(String),
/// Regular expression matching function. It evaluates to true /// Regular expression matching function. It evaluates to true
/// whenever the regular expression matches the entirety of the URL /// whenever the regular expression matches the entirety of the URL
/// of the document being styled. /// of the document being styled.
RegExp(String), #[css(function)]
Regexp(String),
} }
macro_rules! parse_quoted_or_unquoted_string { macro_rules! parse_quoted_or_unquoted_string {
@ -125,7 +128,7 @@ impl UrlMatchingFunction {
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::Domain) parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::Domain)
} else if input.try(|input| input.expect_function_matching("regexp")).is_ok() { } else if input.try(|input| input.expect_function_matching("regexp")).is_ok() {
input.parse_nested_block(|input| { input.parse_nested_block(|input| {
Ok(UrlMatchingFunction::RegExp(input.expect_string()?.as_ref().to_owned())) Ok(UrlMatchingFunction::Regexp(input.expect_string()?.as_ref().to_owned()))
}) })
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) { } else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
Ok(UrlMatchingFunction::Url(url)) Ok(UrlMatchingFunction::Url(url))
@ -145,14 +148,14 @@ impl UrlMatchingFunction {
UrlMatchingFunction::Url(_) => GeckoUrlMatchingFunction::eURL, UrlMatchingFunction::Url(_) => GeckoUrlMatchingFunction::eURL,
UrlMatchingFunction::UrlPrefix(_) => GeckoUrlMatchingFunction::eURLPrefix, UrlMatchingFunction::UrlPrefix(_) => GeckoUrlMatchingFunction::eURLPrefix,
UrlMatchingFunction::Domain(_) => GeckoUrlMatchingFunction::eDomain, UrlMatchingFunction::Domain(_) => GeckoUrlMatchingFunction::eDomain,
UrlMatchingFunction::RegExp(_) => GeckoUrlMatchingFunction::eRegExp, UrlMatchingFunction::Regexp(_) => GeckoUrlMatchingFunction::eRegExp,
}; };
let pattern = nsCStr::from(match *self { let pattern = nsCStr::from(match *self {
UrlMatchingFunction::Url(ref url) => url.as_str(), UrlMatchingFunction::Url(ref url) => url.as_str(),
UrlMatchingFunction::UrlPrefix(ref pat) | UrlMatchingFunction::UrlPrefix(ref pat) |
UrlMatchingFunction::Domain(ref pat) | UrlMatchingFunction::Domain(ref pat) |
UrlMatchingFunction::RegExp(ref pat) => pat, UrlMatchingFunction::Regexp(ref pat) => pat,
}); });
unsafe { unsafe {
Gecko_DocumentRule_UseForPresentation(device.pres_context(), &*pattern, func) Gecko_DocumentRule_UseForPresentation(device.pres_context(), &*pattern, func)
@ -166,34 +169,6 @@ impl UrlMatchingFunction {
} }
} }
impl ToCss for UrlMatchingFunction {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
UrlMatchingFunction::Url(ref url) => {
url.to_css(dest)
},
UrlMatchingFunction::UrlPrefix(ref url_prefix) => {
dest.write_str("url-prefix(")?;
url_prefix.to_css(dest)?;
dest.write_str(")")
},
UrlMatchingFunction::Domain(ref domain) => {
dest.write_str("domain(")?;
domain.to_css(dest)?;
dest.write_str(")")
},
UrlMatchingFunction::RegExp(ref regex) => {
dest.write_str("regexp(")?;
regex.to_css(dest)?;
dest.write_str(")")
},
}
}
}
/// A `@document` rule's condition. /// A `@document` rule's condition.
/// ///
/// <https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#at-document> /// <https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#at-document>
@ -201,7 +176,8 @@ impl ToCss for UrlMatchingFunction {
/// The `@document` rule's condition is written as a comma-separated list of /// The `@document` rule's condition is written as a comma-separated list of
/// URL matching functions, and the condition evaluates to true whenever any /// URL matching functions, and the condition evaluates to true whenever any
/// one of those functions evaluates to true. /// one of those functions evaluates to true.
#[derive(Clone, Debug)] #[css(comma, iterable)]
#[derive(Clone, Debug, ToCss)]
pub struct DocumentCondition(Vec<UrlMatchingFunction>); pub struct DocumentCondition(Vec<UrlMatchingFunction>);
impl DocumentCondition { impl DocumentCondition {
@ -219,20 +195,3 @@ impl DocumentCondition {
) )
} }
} }
impl ToCss for DocumentCondition {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut iter = self.0.iter();
let first = iter.next()
.expect("Empty DocumentCondition, should contain at least one URL matching function");
first.to_css(dest)?;
for url_matching_function in iter {
dest.write_str(", ")?;
url_matching_function.to_css(dest)?;
}
Ok(())
}
}

View file

@ -80,7 +80,7 @@ impl ToGeckoFontFeatureValues for SingleValue {
} }
/// A @font-feature-values block declaration value that keeps one or two values. /// A @font-feature-values block declaration value that keeps one or two values.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, ToCss)]
pub struct PairValues(pub u32, pub Option<u32>); pub struct PairValues(pub u32, pub Option<u32>);
impl Parse for PairValues { impl Parse for PairValues {
@ -104,20 +104,6 @@ impl Parse for PairValues {
} }
} }
impl ToCss for PairValues {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
self.0.to_css(dest)?;
if let Some(second) = self.1 {
dest.write_char(' ')?;
second.to_css(dest)?;
}
Ok(())
}
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for PairValues { impl ToGeckoFontFeatureValues for PairValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) { fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
@ -132,7 +118,8 @@ impl ToGeckoFontFeatureValues for PairValues {
} }
/// A @font-feature-values block declaration value that keeps a list of values. /// A @font-feature-values block declaration value that keeps a list of values.
#[derive(Clone, Debug, PartialEq)] #[css(iterable)]
#[derive(Clone, Debug, PartialEq, ToCss)]
pub struct VectorValues(pub Vec<u32>); pub struct VectorValues(pub Vec<u32>);
impl Parse for VectorValues { impl Parse for VectorValues {
@ -159,24 +146,6 @@ impl Parse for VectorValues {
} }
} }
impl ToCss for VectorValues {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut iter = self.0.iter();
let first = iter.next();
if let Some(first) = first {
first.to_css(dest)?;
for value in iter {
dest.write_char(' ')?;
value.to_css(dest)?;
}
}
Ok(())
}
}
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for VectorValues { impl ToGeckoFontFeatureValues for VectorValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) { fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {

View file

@ -145,24 +145,10 @@ impl KeyframePercentage {
/// A keyframes selector is a list of percentages or from/to symbols, which are /// A keyframes selector is a list of percentages or from/to symbols, which are
/// converted at parse time to percentages. /// converted at parse time to percentages.
#[derive(Clone, Debug, Eq, PartialEq)] #[css(comma, iterable)]
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
pub struct KeyframeSelector(Vec<KeyframePercentage>); pub struct KeyframeSelector(Vec<KeyframePercentage>);
impl ToCss for KeyframeSelector {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
let mut iter = self.0.iter();
iter.next().unwrap().to_css(dest)?;
for percentage in iter {
dest.write_str(", ")?;
percentage.to_css(dest)?;
}
Ok(())
}
}
impl KeyframeSelector { impl KeyframeSelector {
/// Return the list of percentages this selector contains. /// Return the list of percentages this selector contains.
#[inline] #[inline]

View file

@ -143,26 +143,14 @@ trait FromMeta: Sized {
/// See: /// See:
/// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc /// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc
/// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom /// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)]
pub enum ViewportLength { pub enum ViewportLength {
Specified(LengthOrPercentageOrAuto), Specified(LengthOrPercentageOrAuto),
ExtendToZoom ExtendToZoom
} }
impl ToCss for ViewportLength {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
match *self {
ViewportLength::Specified(ref length) => length.to_css(dest),
ViewportLength::ExtendToZoom => dest.write_str("extend-to-zoom"),
}
}
}
impl FromMeta for ViewportLength { impl FromMeta for ViewportLength {
fn from_meta(value: &str) -> Option<ViewportLength> { fn from_meta(value: &str) -> Option<ViewportLength> {
macro_rules! specified { macro_rules! specified {

View file

@ -131,6 +131,8 @@ struct CssInputAttrs {
derive_debug: bool, derive_debug: bool,
function: Option<Function>, function: Option<Function>,
comma: bool, comma: bool,
// Here because structs variants are also their whole type definition.
iterable: bool,
} }
#[darling(attributes(css), default)] #[darling(attributes(css), default)]

View file

@ -106113,6 +106113,18 @@
{} {}
] ]
], ],
"css/css-counter-styles/broken-symbols.htm": [
[
"/css/css-counter-styles/broken-symbols.htm",
[
[
"/css/css-counter-styles/broken-symbols-ref.htm",
"=="
]
],
{}
]
],
"css/css-display/display-contents-alignment-001.html": [ "css/css-display/display-contents-alignment-001.html": [
[ [
"/css/css-display/display-contents-alignment-001.html", "/css/css-display/display-contents-alignment-001.html",
@ -237304,6 +237316,11 @@
{} {}
] ]
], ],
"css/css-counter-styles/broken-symbols-ref.htm": [
[
{}
]
],
"css/css-display/OWNERS": [ "css/css-display/OWNERS": [
[ [
{} {}
@ -484992,6 +485009,14 @@
"dbfaae0538c8cd1e759b59712f53cd17388e7c48", "dbfaae0538c8cd1e759b59712f53cd17388e7c48",
"manual" "manual"
], ],
"css/css-counter-styles/broken-symbols-ref.htm": [
"c794c4b6846212f4ed27e618cdd32a28b8ce013c",
"support"
],
"css/css-counter-styles/broken-symbols.htm": [
"23cb132e8efcdd1020e12c89c9d30a333708b72e",
"reftest"
],
"css/css-counter-styles/cambodian/css3-counter-styles-158.html": [ "css/css-counter-styles/cambodian/css3-counter-styles-158.html": [
"a334bd087e7a808567daeeae419a80466a377ef3", "a334bd087e7a808567daeeae419a80466a377ef3",
"manual" "manual"

View file

@ -0,0 +1,3 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<ol><li>Should have "1." as bullet point.</ol>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<meta charset="UTF-8">
<title>CSS Test: invalid counter-style symbols</title>
<link rel="author" title="Anthony Ramine" href="mailto:n.oxyde@gmail.com">
<link rel="help" href="https://drafts.csswg.org/css-counter-styles-3/#typedef-symbol">
<link rel="match" href="broken-symbols-ref.htm">
<style type="text/css">
@counter-style a {
system: alphabetic;
symbols: ⓐ inherit;
}
</style>
<ol style="list-style-type: a"><li>Should have "1." as bullet point.</ol>