Implement #[compute(clone)] for #[derive(ToComputedValue)]

This commit is contained in:
Anthony Ramine 2017-08-26 12:56:50 +02:00
parent efc852f6e3
commit 735e093de7
6 changed files with 37 additions and 95 deletions

View file

@ -18,8 +18,7 @@ use values::generics::image::{CompatMode, ColorStop as GenericColorStop, EndingS
use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
use values::generics::image::{Image as GenericImage, GradientKind as GenericGradientKind};
use values::generics::image::{LineDirection as GenericLineDirection, MozImageRect as GenericMozImageRect};
use values::specified::image::{Gradient as SpecifiedGradient, LineDirection as SpecifiedLineDirection};
use values::specified::image::{GradientKind as SpecifiedGradientKind};
use values::specified::image::LineDirection as SpecifiedLineDirection;
use values::specified::position::{X, Y};
/// A computed image layer.
@ -181,25 +180,3 @@ impl ToComputedValue for SpecifiedLineDirection {
}
}
}
impl ToComputedValue for SpecifiedGradient {
type ComputedValue = Gradient;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
Self::ComputedValue {
kind: self.kind.to_computed_value(context),
items: self.items.to_computed_value(context),
repeating: self.repeating,
compat_mode: self.compat_mode
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Self {
kind: SpecifiedGradientKind::from_computed_value(&computed.kind),
items: ToComputedValue::from_computed_value(&computed.items),
repeating: computed.repeating,
compat_mode: computed.compat_mode
}
}
}

View file

@ -349,8 +349,8 @@ no_viewport_percentage!(RepeatCount);
///
/// It can also hold `repeat()` function parameters, which expands into the respective
/// values in its computed form.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, ToComputedValue)]
pub struct TrackRepeat<L> {
/// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`)
pub count: RepeatCount,
@ -359,6 +359,7 @@ pub struct TrackRepeat<L> {
/// If there's no `<line-names>`, then it's represented by an empty vector.
/// For N `<track-size>` values, there will be N+1 `<line-names>`, and so this vector's
/// length is always one value more than that of the `<track-size>`.
#[compute(clone)]
pub line_names: Box<[Box<[CustomIdent]>]>,
/// `<track-size>` values.
pub track_sizes: Vec<TrackSize<L>>,
@ -446,31 +447,6 @@ impl<L: Clone> TrackRepeat<L> {
}
}
}
impl<L: ToComputedValue> ToComputedValue for TrackRepeat<L> {
type ComputedValue = TrackRepeat<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
TrackRepeat {
count: self.count,
track_sizes: self.track_sizes.iter()
.map(|val| val.to_computed_value(context))
.collect(),
line_names: self.line_names.clone(),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
TrackRepeat {
count: computed.count,
track_sizes: computed.track_sizes.iter()
.map(ToComputedValue::from_computed_value)
.collect(),
line_names: computed.line_names.clone(),
}
}
}
/// The type of a `<track-list>` as determined during parsing.
///
@ -500,8 +476,8 @@ impl ComputedValueAsSpecified for TrackListType {}
/// A grid `<track-list>` type.
///
/// https://drafts.csswg.org/css-grid/#typedef-track-list
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, ToComputedValue)]
pub struct TrackList<T> {
/// The type of this `<track-list>` (auto, explicit or general).
///
@ -515,6 +491,7 @@ pub struct TrackList<T> {
/// If there's no `<line-names>`, then it's represented by an empty vector.
/// For N values, there will be N+1 `<line-names>`, and so this vector's
/// length is always one value more than that of the `<track-size>`.
#[compute(clone)]
pub line_names: Box<[Box<[CustomIdent]>]>,
/// `<auto-repeat>` value. There can only be one `<auto-repeat>` in a TrackList.
pub auto_repeat: Option<TrackRepeat<T>>,

View file

@ -35,16 +35,18 @@ pub enum Image<Gradient, MozImageRect, ImageUrl> {
/// A CSS gradient.
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
pub struct Gradient<LineDirection, Length, LengthOrPercentage, Position, Color, Angle> {
/// Gradients can be linear or radial.
pub kind: GradientKind<LineDirection, Length, LengthOrPercentage, Position, Angle>,
/// The color stops and interpolation hints.
pub items: Vec<GradientItem<Color, LengthOrPercentage>>,
/// True if this is a repeating gradient.
#[compute(clone)]
pub repeating: bool,
/// Compatibility mode.
#[compute(clone)]
pub compat_mode: CompatMode,
}

View file

@ -11,7 +11,6 @@ use std::ascii::AsciiExt;
use std::mem;
use style_traits::{HasViewportPercentage, ParseError, StyleParseError};
use values::{CSSFloat, CustomIdent};
use values::computed::{self, Context, ToComputedValue};
use values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType};
use values::specified::LengthOrPercentage;
@ -286,42 +285,6 @@ impl HasViewportPercentage for TrackList<LengthOrPercentage> {
}
}
impl ToComputedValue for TrackList<LengthOrPercentage> {
type ComputedValue = TrackList<computed::LengthOrPercentage>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
let mut values = Vec::with_capacity(self.values.len() + 1);
for value in self.values.iter().map(|val| val.to_computed_value(context)) {
values.push(value);
}
TrackList {
list_type: self.list_type.to_computed_value(context),
values: values,
line_names: self.line_names.clone(),
auto_repeat: self.auto_repeat.clone().map(|repeat| repeat.to_computed_value(context)),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
let mut values = Vec::with_capacity(computed.values.len() + 1);
for value in computed.values.iter().map(ToComputedValue::from_computed_value) {
values.push(value);
}
TrackList {
list_type: computed.list_type,
values: values,
line_names: computed.line_names.clone(),
auto_repeat: computed.auto_repeat.clone().map(|ref repeat| TrackRepeat::from_computed_value(repeat)),
}
}
}
impl Parse for GridTemplateComponent<LengthOrPercentage> {
// FIXME: Derive Parse (probably with None_)
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {

View file

@ -49,7 +49,7 @@ pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream {
to_animated_zero::derive(input).to_string().parse().unwrap()
}
#[proc_macro_derive(ToComputedValue)]
#[proc_macro_derive(ToComputedValue, attributes(compute))]
pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
to_computed_value::derive(input).to_string().parse().unwrap()

View file

@ -14,14 +14,31 @@ pub fn derive(input: DeriveInput) -> Tokens {
cg::fmap_trait_parts(&input, trait_path, "ComputedValue");
let to_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
where_clause.add_trait_bound(&binding.field.ty);
quote! {
::values::computed::ToComputedValue::to_computed_value(#binding, context)
let attrs = cg::parse_field_attrs::<ComputedValueAttrs>(&binding.field);
if attrs.clone {
if cg::is_parameterized(&binding.field.ty, where_clause.params, None) {
where_clause.inner.predicates.push(cg::where_predicate(
binding.field.ty.clone(),
&["std", "clone", "Clone"],
None,
));
}
quote! { ::std::clone::Clone::clone(#binding) }
} else {
where_clause.add_trait_bound(&binding.field.ty);
quote! {
::values::computed::ToComputedValue::to_computed_value(#binding, context)
}
}
});
let from_body = cg::fmap_match(&input, BindStyle::Ref, |binding| {
quote! {
::values::computed::ToComputedValue::from_computed_value(#binding)
let attrs = cg::parse_field_attrs::<ComputedValueAttrs>(&binding.field);
if attrs.clone {
quote! { ::std::clone::Clone::clone(#binding) }
} else {
quote! {
::values::computed::ToComputedValue::from_computed_value(#binding)
}
}
});
@ -46,3 +63,9 @@ pub fn derive(input: DeriveInput) -> Tokens {
}
}
}
#[darling(attributes(compute), default)]
#[derive(Default, FromField)]
struct ComputedValueAttrs {
clone: bool,
}