diff --git a/servo/components/style/properties/longhand/list.mako.rs b/servo/components/style/properties/longhand/list.mako.rs index 12a73d0466eb..c478dc6f98c7 100644 --- a/servo/components/style/properties/longhand/list.mako.rs +++ b/servo/components/style/properties/longhand/list.mako.rs @@ -15,31 +15,29 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu // decimal-leading-zero, armenian, upper-armenian, lower-armenian, georgian, lower-roman, // upper-roman // -// TODO(bholley): Missing quite a few gecko properties here as well. -// -// In gecko, {upper,lower}-{roman,alpha} are implemented as @counter-styles in the -// UA, however they can also be set from pres attrs. When @counter-style is supported -// we may need to look into this and handle these differently. -// // [1]: http://dev.w3.org/csswg/css-counter-styles/ % if product == "servo": - ${helpers.single_keyword("list-style-type", """ - disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha + ${helpers.single_keyword( + "list-style-type", + """disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha arabic-indic bengali cambodian cjk-decimal devanagari gujarati gurmukhi kannada khmer lao malayalam mongolian myanmar oriya persian telugu thai tibetan cjk-earthly-branch cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana katakana-iroha""", animation_value_type="discrete", spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type", - servo_restyle_damage="rebuild_and_reflow")} + servo_restyle_damage="rebuild_and_reflow", + )} % else: - ${helpers.predefined_type("list-style-type", - "ListStyleType", - "computed::ListStyleType::disc()", - initial_specified_value="specified::ListStyleType::disc()", - animation_value_type="discrete", - boxed=True, - spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type", - servo_restyle_damage="rebuild_and_reflow")} + ${helpers.predefined_type( + "list-style-type", + "ListStyleType", + "computed::ListStyleType::disc()", + initial_specified_value="specified::ListStyleType::disc()", + animation_value_type="discrete", + boxed=True, + spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type", + servo_restyle_damage="rebuild_and_reflow", + )} % endif ${helpers.predefined_type("list-style-image", diff --git a/servo/components/style/values/generics/transform.rs b/servo/components/style/values/generics/transform.rs index 504198ab89c6..7584e5cdf489 100644 --- a/servo/components/style/values/generics/transform.rs +++ b/servo/components/style/values/generics/transform.rs @@ -80,12 +80,13 @@ pub struct TransformOrigin { /// A generic timing function. /// /// -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] pub enum TimingFunction { /// `linear | ease | ease-in | ease-out | ease-in-out` Keyword(TimingKeyword), /// `cubic-bezier(, , , )` #[allow(missing_docs)] + #[css(comma, function)] CubicBezier { x1: Number, y1: Number, @@ -93,8 +94,10 @@ pub enum TimingFunction { y2: Number, }, /// `step-start | step-end | steps(, [ start | end ]?)` - Steps(Integer, StepPosition), + #[css(comma, function)] + Steps(Integer, #[css(skip_if = "is_end")] StepPosition), /// `frames()` + #[css(comma, function)] Frames(Integer), } @@ -119,6 +122,11 @@ pub enum StepPosition { End, } +#[inline] +fn is_end(position: &StepPosition) -> bool { + *position == StepPosition::End +} + impl TransformOrigin { /// Returns a new transform origin. pub fn new(horizontal: H, vertical: V, depth: D) -> Self { @@ -138,51 +146,6 @@ impl TimingFunction { } } -impl ToCss for TimingFunction -where - Integer: ToCss, - Number: ToCss, -{ - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - match *self { - TimingFunction::Keyword(keyword) => keyword.to_css(dest), - TimingFunction::CubicBezier { - ref x1, - ref y1, - ref x2, - ref y2, - } => { - dest.write_str("cubic-bezier(")?; - x1.to_css(dest)?; - dest.write_str(", ")?; - y1.to_css(dest)?; - dest.write_str(", ")?; - x2.to_css(dest)?; - dest.write_str(", ")?; - y2.to_css(dest)?; - dest.write_str(")") - }, - TimingFunction::Steps(ref intervals, position) => { - dest.write_str("steps(")?; - intervals.to_css(dest)?; - if position != StepPosition::End { - dest.write_str(", ")?; - position.to_css(dest)?; - } - dest.write_str(")") - }, - TimingFunction::Frames(ref frames) => { - dest.write_str("frames(")?; - frames.to_css(dest)?; - dest.write_str(")") - }, - } - } -} - impl TimingKeyword { /// Returns the keyword as a quadruplet of Bezier point coordinates /// `(x1, y1, x2, y2)`. diff --git a/servo/components/style_derive/to_css.rs b/servo/components/style_derive/to_css.rs index a0197dedc86c..f94da49cfaa6 100644 --- a/servo/components/style_derive/to_css.rs +++ b/servo/components/style_derive/to_css.rs @@ -5,7 +5,7 @@ use cg::{self, WhereClause}; use darling::util::Override; use quote::{ToTokens, Tokens}; -use syn::{self, Data}; +use syn::{self, Data, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; pub fn derive(input: syn::DeriveInput) -> Tokens { @@ -79,7 +79,6 @@ fn derive_variant_arm( let mut expr = if let Some(keyword) = variant_attrs.keyword { assert!(bindings.is_empty()); - let keyword = keyword.to_string(); quote! { ::std::fmt::Write::write_str(dest, #keyword) } @@ -129,7 +128,15 @@ fn derive_variant_fields_expr( if !attrs.ignore_bound { where_clause.add_trait_bound(&first.ast().ty); } - return quote! { ::style_traits::ToCss::to_css(#first, dest) }; + let mut expr = quote! { ::style_traits::ToCss::to_css(#first, dest) }; + if let Some(condition) = attrs.skip_if { + expr = quote! { + if !#condition(#first) { + #expr + } + } + } + return expr; } let mut expr = derive_single_field_expr(first, attrs, where_clause); @@ -149,7 +156,7 @@ fn derive_single_field_expr( attrs: CssFieldAttrs, where_clause: &mut WhereClause, ) -> Tokens { - if attrs.iterable { + let mut expr = if attrs.iterable { if let Some(if_empty) = attrs.if_empty { return quote! { { @@ -174,7 +181,17 @@ fn derive_single_field_expr( where_clause.add_trait_bound(&field.ast().ty); } quote! { writer.item(#field)?; } + }; + + if let Some(condition) = attrs.skip_if { + expr = quote! { + if !#condition(#field) { + #expr + } + } } + + expr } #[darling(attributes(css), default)] @@ -204,4 +221,5 @@ struct CssFieldAttrs { ignore_bound: bool, iterable: bool, skip: bool, + skip_if: Option, } diff --git a/servo/components/style_traits/values.rs b/servo/components/style_traits/values.rs index aad75d51b8a7..d6bd05b7b40e 100644 --- a/servo/components/style_traits/values.rs +++ b/servo/components/style_traits/values.rs @@ -34,6 +34,9 @@ use std::fmt::{self, Write}; /// dimension token, like: ; /// * if `#[css(skip)]` is found on a field, the `ToCss` call for that field /// is skipped; +/// * if `#[css(skip_if = "function")]` is found on a field, the `ToCss` call +/// for that field is skipped if `function` returns true. This function is +/// provided the field as an argument; /// * finally, one can put `#[css(derive_debug)]` on the whole type, to /// implement `Debug` by a single call to `ToCss::to_css`. pub trait ToCss {