servo: Merge #20236 - Introduce #[css(skip_if)] (from emilio:to-css-skip-if); r=nox

This is most of #20224 but without the actual counter() fix since it's waiting on a WPT update.

Source-Repo: https://github.com/servo/servo
Source-Revision: 8133f788cfbde23cc54032a3327303b42257b91d

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : f352834ab745131666c9baee1dcae46b2577ba19
This commit is contained in:
Emilio Cobos Álvarez 2018-03-08 09:16:55 -05:00
Родитель 8a51d5aa81
Коммит 0155352329
4 изменённых файлов: 50 добавлений и 68 удалений

Просмотреть файл

@ -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",

Просмотреть файл

@ -80,12 +80,13 @@ pub struct TransformOrigin<H, V, Depth> {
/// A generic timing function.
///
/// <https://drafts.csswg.org/css-timing-1/#single-timing-function-production>
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
pub enum TimingFunction<Integer, Number> {
/// `linear | ease | ease-in | ease-out | ease-in-out`
Keyword(TimingKeyword),
/// `cubic-bezier(<number>, <number>, <number>, <number>)`
#[allow(missing_docs)]
#[css(comma, function)]
CubicBezier {
x1: Number,
y1: Number,
@ -93,8 +94,10 @@ pub enum TimingFunction<Integer, Number> {
y2: Number,
},
/// `step-start | step-end | steps(<integer>, [ start | end ]?)`
Steps(Integer, StepPosition),
#[css(comma, function)]
Steps(Integer, #[css(skip_if = "is_end")] StepPosition),
/// `frames(<integer>)`
#[css(comma, function)]
Frames(Integer),
}
@ -119,6 +122,11 @@ pub enum StepPosition {
End,
}
#[inline]
fn is_end(position: &StepPosition) -> bool {
*position == StepPosition::End
}
impl<H, V, D> TransformOrigin<H, V, D> {
/// Returns a new transform origin.
pub fn new(horizontal: H, vertical: V, depth: D) -> Self {
@ -138,51 +146,6 @@ impl<Integer, Number> TimingFunction<Integer, Number> {
}
}
impl<Integer, Number> ToCss for TimingFunction<Integer, Number>
where
Integer: ToCss,
Number: ToCss,
{
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> 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)`.

Просмотреть файл

@ -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<Path>,
}

Просмотреть файл

@ -34,6 +34,9 @@ use std::fmt::{self, Write};
/// dimension token, like: <member><identifier>;
/// * 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 {