mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
servo: Merge #17291 - Function support for #[derive(ToCss)] and an Animatable fix (from servo:derive-all-the-things); r=<try>
Source-Repo: https://github.com/servo/servo Source-Revision: 44eb8c8e4fbafa3dac18ae0464923c63e5fc929d --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : c59b9d3982f06e18bca2c783fab6401d86e2ccbf
This commit is contained in:
parent
153b74fe52
commit
f2775d002e
@ -401,7 +401,7 @@ impl CounterStyleOrNone {
|
||||
use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name;
|
||||
use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols;
|
||||
match self {
|
||||
CounterStyleOrNone::None_ => unsafe {
|
||||
CounterStyleOrNone::None => unsafe {
|
||||
set_name(gecko_value, atom!("none").into_addrefed());
|
||||
},
|
||||
CounterStyleOrNone::Name(name) => unsafe {
|
||||
|
@ -1246,7 +1246,14 @@ impl Animatable for LengthOrPercentageOrNone {
|
||||
(LengthOrPercentageOrNone::None, LengthOrPercentageOrNone::None) => {
|
||||
Ok(LengthOrPercentageOrNone::None)
|
||||
}
|
||||
_ => Err(())
|
||||
(this, other) => {
|
||||
let this = <Option<CalcLengthOrPercentage>>::from(this);
|
||||
let other = <Option<CalcLengthOrPercentage>>::from(other);
|
||||
match this.add_weighted(&other, self_portion, other_portion) {
|
||||
Ok(Some(result)) => Ok(LengthOrPercentageOrNone::Calc(result)),
|
||||
_ => Err(()),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1273,7 +1280,12 @@ impl Animatable for LengthOrPercentageOrNone {
|
||||
LengthOrPercentageOrNone::Percentage(ref other)) => {
|
||||
this.compute_distance(other)
|
||||
},
|
||||
_ => Err(())
|
||||
(this, other) => {
|
||||
// If one of the element is Auto, Option<> will be None, and the returned distance is Err(())
|
||||
let this = <Option<CalcLengthOrPercentage>>::from(this);
|
||||
let other = <Option<CalcLengthOrPercentage>>::from(other);
|
||||
this.compute_distance(&other)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||
pub fn from_gecko_keyword(value: u32) -> Self {
|
||||
use gecko_bindings::structs;
|
||||
SpecifiedValue::CounterStyle(if value == structs::NS_STYLE_LIST_STYLE_NONE {
|
||||
CounterStyleOrNone::None_
|
||||
CounterStyleOrNone::None
|
||||
} else {
|
||||
<%
|
||||
values = """disc circle square decimal lower-roman
|
||||
|
@ -62,7 +62,7 @@
|
||||
list_style_type::SpecifiedValue::none
|
||||
% else:
|
||||
use values::generics::CounterStyleOrNone;
|
||||
list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None_)
|
||||
list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None)
|
||||
% endif
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,25 @@ impl From<LengthOrPercentageOrAuto> for Option<CalcLengthOrPercentage> {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LengthOrPercentageOrNone> for Option<CalcLengthOrPercentage> {
|
||||
fn from(len: LengthOrPercentageOrNone) -> Option<CalcLengthOrPercentage> {
|
||||
match len {
|
||||
LengthOrPercentageOrNone::Percentage(this) => {
|
||||
Some(CalcLengthOrPercentage::new(Au(0), Some(this)))
|
||||
}
|
||||
LengthOrPercentageOrNone::Length(this) => {
|
||||
Some(CalcLengthOrPercentage::new(this, None))
|
||||
}
|
||||
LengthOrPercentageOrNone::Calc(this) => {
|
||||
Some(this)
|
||||
}
|
||||
LengthOrPercentageOrNone::None => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for CalcLengthOrPercentage {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match (self.length, self.percentage) {
|
||||
|
@ -92,7 +92,7 @@ pub struct Ellipse<H, V, LengthOrPercentage> {
|
||||
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
|
||||
pub enum ShapeRadius<LengthOrPercentage> {
|
||||
Length(LengthOrPercentage),
|
||||
ClosestSide,
|
||||
@ -161,17 +161,6 @@ impl<L> Default for ShapeRadius<L> {
|
||||
fn default() -> Self { ShapeRadius::ClosestSide }
|
||||
}
|
||||
|
||||
impl<L: ToCss> ToCss for ShapeRadius<L> {
|
||||
#[inline]
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
ShapeRadius::Length(ref lop) => lop.to_css(dest),
|
||||
ShapeRadius::ClosestSide => dest.write_str("closest-side"),
|
||||
ShapeRadius::FarthestSide => dest.write_str("farthest-side"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: ToCss> ToCss for Polygon<L> {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
dest.write_str("polygon(")?;
|
||||
|
@ -5,15 +5,13 @@
|
||||
//! Generic types for legacy Gecko-only properties that should probably be
|
||||
//! unshipped at some point in the future.
|
||||
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
/// A generic value for scroll snap points.
|
||||
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
|
||||
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
|
||||
pub enum ScrollSnapPoint<LengthOrPercentage> {
|
||||
/// `none`
|
||||
None,
|
||||
/// `repeat(<length-or-percentage>)`
|
||||
#[css(function)]
|
||||
Repeat(LengthOrPercentage)
|
||||
}
|
||||
|
||||
@ -33,22 +31,3 @@ impl<L> ScrollSnapPoint<L> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> ToCss for ScrollSnapPoint<L>
|
||||
where
|
||||
L: ToCss,
|
||||
{
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where
|
||||
W: fmt::Write,
|
||||
{
|
||||
match *self {
|
||||
ScrollSnapPoint::None => dest.write_str("none"),
|
||||
ScrollSnapPoint::Repeat(ref length) => {
|
||||
dest.write_str("repeat(")?;
|
||||
length.to_css(dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,13 +54,14 @@ impl SymbolsType {
|
||||
///
|
||||
/// 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, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
|
||||
pub enum CounterStyleOrNone {
|
||||
/// none
|
||||
None_,
|
||||
/// <counter-style-name>
|
||||
/// `none`
|
||||
None,
|
||||
/// `<counter-style-name>`
|
||||
Name(CustomIdent),
|
||||
/// symbols()
|
||||
/// `symbols()`
|
||||
#[css(function)]
|
||||
Symbols(SymbolsType, Symbols),
|
||||
}
|
||||
|
||||
@ -84,7 +85,7 @@ impl Parse for CounterStyleOrNone {
|
||||
return Ok(CounterStyleOrNone::Name(name));
|
||||
}
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(CounterStyleOrNone::None_);
|
||||
return Ok(CounterStyleOrNone::None);
|
||||
}
|
||||
if input.try(|i| i.expect_function_matching("symbols")).is_ok() {
|
||||
return input.parse_nested_block(|input| {
|
||||
@ -108,23 +109,6 @@ impl Parse for CounterStyleOrNone {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for CounterStyleOrNone {
|
||||
#[inline]
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
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(")")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A settings tag, defined by a four-character tag and a setting value
|
||||
///
|
||||
/// For font-feature-settings, this is a tag and an integer,
|
||||
|
@ -25,7 +25,7 @@ pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream {
|
||||
to_computed_value::derive(input).to_string().parse().unwrap()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ToCss)]
|
||||
#[proc_macro_derive(ToCss, attributes(css))]
|
||||
pub fn derive_to_css(stream: TokenStream) -> TokenStream {
|
||||
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
|
||||
to_css::derive(input).to_string().parse().unwrap()
|
||||
|
@ -16,24 +16,61 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
|
||||
|
||||
let style = synstructure::BindStyle::Ref.into();
|
||||
let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
|
||||
if bindings.is_empty() {
|
||||
let identifier = to_css_identifier(variant.ident.as_ref());
|
||||
return Some(quote! {
|
||||
let mut identifier = to_css_identifier(variant.ident.as_ref());
|
||||
let mut expr = if bindings.is_empty() {
|
||||
quote! {
|
||||
::std::fmt::Write::write_str(dest, #identifier)
|
||||
});
|
||||
}
|
||||
let (first, rest) = bindings.split_first().expect("unit variants are not yet supported");
|
||||
where_clause.predicates.push(where_predicate(first.field.ty.clone()));
|
||||
let mut expr = quote! {
|
||||
::style_traits::ToCss::to_css(#first, dest)
|
||||
};
|
||||
for binding in rest {
|
||||
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
|
||||
expr = quote! {
|
||||
#expr?;
|
||||
::std::fmt::Write::write_str(dest, " ")?;
|
||||
::style_traits::ToCss::to_css(#binding, dest)
|
||||
}
|
||||
} else {
|
||||
let (first, rest) = bindings.split_first().expect("unit variants are not yet supported");
|
||||
where_clause.predicates.push(where_predicate(first.field.ty.clone()));
|
||||
let mut expr = quote! {
|
||||
::style_traits::ToCss::to_css(#first, dest)
|
||||
};
|
||||
for binding in rest {
|
||||
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
|
||||
expr = quote! {
|
||||
#expr?;
|
||||
::std::fmt::Write::write_str(dest, " ")?;
|
||||
::style_traits::ToCss::to_css(#binding, dest)
|
||||
};
|
||||
}
|
||||
expr
|
||||
};
|
||||
let mut css_attrs = variant.attrs.iter().filter(|attr| attr.name() == "css");
|
||||
let is_function = css_attrs.next().map_or(false, |attr| {
|
||||
match attr.value {
|
||||
syn::MetaItem::List(ref ident, ref items) if ident.as_ref() == "css" => {
|
||||
let mut nested = items.iter();
|
||||
let is_function = nested.next().map_or(false, |attr| {
|
||||
match *attr {
|
||||
syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref ident)) => {
|
||||
if ident.as_ref() != "function" {
|
||||
panic!("only `#[css(function)]` is supported for now")
|
||||
}
|
||||
true
|
||||
},
|
||||
_ => panic!("only `#[css(<ident>)]` is supported for now"),
|
||||
}
|
||||
});
|
||||
if nested.next().is_some() {
|
||||
panic!("only `#[css()]` or `#[css(<ident>)]` is supported for now")
|
||||
}
|
||||
is_function
|
||||
},
|
||||
_ => panic!("only `#[css(...)]` is supported for now"),
|
||||
}
|
||||
});
|
||||
if css_attrs.next().is_some() {
|
||||
panic!("only a single `#[css(...)]` attribute is supported for now");
|
||||
}
|
||||
if is_function {
|
||||
identifier.push_str("(");
|
||||
expr = quote! {
|
||||
::std::fmt::Write::write_str(dest, #identifier)?;
|
||||
#expr?;
|
||||
::std::fmt::Write::write_str(dest, ")")
|
||||
}
|
||||
}
|
||||
Some(expr)
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user