::ComputedValue,
- ::ComputedValue,
- ::ComputedValue>;
-
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- Gradient {
- kind: self.kind.to_computed_value(context),
- items: self.items.iter().map(|s| s.to_computed_value(context)).collect(),
- repeating: self.repeating,
- compat_mode: self.compat_mode,
- }
- }
-
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- Gradient {
- kind: ToComputedValue::from_computed_value(&computed.kind),
- items: computed.items.iter().map(ToComputedValue::from_computed_value).collect(),
- repeating: computed.repeating,
- compat_mode: computed.compat_mode,
- }
- }
-}
-
impl GradientKind {
fn label(&self) -> &str {
match *self {
@@ -322,43 +250,6 @@ impl GradientKind {
}
}
-impl ToComputedValue for GradientKind
- where D: ToComputedValue,
- L: ToComputedValue,
- LoP: ToComputedValue,
- P: ToComputedValue,
-{
- type ComputedValue = GradientKind<::ComputedValue,
- ::ComputedValue,
- ::ComputedValue,
- ::ComputedValue>;
-
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- match *self {
- GradientKind::Linear(ref direction) => {
- GradientKind::Linear(direction.to_computed_value(context))
- },
- GradientKind::Radial(ref shape, ref position) => {
- GradientKind::Radial(shape.to_computed_value(context), position.to_computed_value(context))
- },
- }
- }
-
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- match *computed {
- GradientKind::Linear(ref direction) => {
- GradientKind::Linear(ToComputedValue::from_computed_value(direction))
- },
- GradientKind::Radial(ref shape, ref position) => {
- GradientKind::Radial(
- ToComputedValue::from_computed_value(shape),
- ToComputedValue::from_computed_value(position),
- )
- }
- }
- }
-}
-
/// The direction of a linear gradient.
pub trait LineDirection {
/// Whether this direction points towards, and thus can be omitted.
@@ -397,53 +288,6 @@ impl ToCss for EndingShape
}
}
-impl ToComputedValue for EndingShape
- where L: ToComputedValue, LoP: ToComputedValue,
-{
- type ComputedValue = EndingShape<::ComputedValue,
- ::ComputedValue>;
-
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- match *self {
- EndingShape::Circle(Circle::Radius(ref length)) => {
- EndingShape::Circle(Circle::Radius(length.to_computed_value(context)))
- },
- EndingShape::Circle(Circle::Extent(extent)) => {
- EndingShape::Circle(Circle::Extent(extent))
- },
- EndingShape::Ellipse(Ellipse::Radii(ref x, ref y)) => {
- EndingShape::Ellipse(Ellipse::Radii(
- x.to_computed_value(context),
- y.to_computed_value(context),
- ))
- },
- EndingShape::Ellipse(Ellipse::Extent(extent)) => {
- EndingShape::Ellipse(Ellipse::Extent(extent))
- },
- }
- }
-
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- match *computed {
- EndingShape::Circle(Circle::Radius(ref length)) => {
- EndingShape::Circle(Circle::Radius(ToComputedValue::from_computed_value(length)))
- },
- EndingShape::Circle(Circle::Extent(extent)) => {
- EndingShape::Circle(Circle::Extent(extent))
- },
- EndingShape::Ellipse(Ellipse::Radii(ref x, ref y)) => {
- EndingShape::Ellipse(Ellipse::Radii(
- ToComputedValue::from_computed_value(x),
- ToComputedValue::from_computed_value(y),
- ))
- },
- EndingShape::Ellipse(Ellipse::Extent(extent)) => {
- EndingShape::Ellipse(Ellipse::Extent(extent))
- },
- }
- }
-}
-
impl ToCss for GradientItem
where C: ToCss, L: ToCss,
{
@@ -455,35 +299,6 @@ impl ToCss for GradientItem
}
}
-impl ToComputedValue for GradientItem
- where C: ToComputedValue, L: ToComputedValue,
-{
- type ComputedValue = GradientItem<::ComputedValue,
- ::ComputedValue>;
-
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- match *self {
- GradientItem::ColorStop(ref stop) => {
- GradientItem::ColorStop(stop.to_computed_value(context))
- },
- GradientItem::InterpolationHint(ref hint) => {
- GradientItem::InterpolationHint(hint.to_computed_value(context))
- },
- }
- }
-
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- match *computed {
- GradientItem::ColorStop(ref stop) => {
- GradientItem::ColorStop(ToComputedValue::from_computed_value(stop))
- },
- GradientItem::InterpolationHint(ref hint) => {
- GradientItem::InterpolationHint(ToComputedValue::from_computed_value(hint))
- },
- }
- }
-}
-
impl fmt::Debug for ColorStop
where C: fmt::Debug, L: fmt::Debug,
{
@@ -509,27 +324,6 @@ impl ToCss for ColorStop
}
}
-impl ToComputedValue for ColorStop
- where C: ToComputedValue, L: ToComputedValue,
-{
- type ComputedValue = ColorStop<::ComputedValue,
- ::ComputedValue>;
-
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- ColorStop {
- color: self.color.to_computed_value(context),
- position: self.position.as_ref().map(|p| p.to_computed_value(context)),
- }
- }
-
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- ColorStop {
- color: ToComputedValue::from_computed_value(&computed.color),
- position: computed.position.as_ref().map(ToComputedValue::from_computed_value),
- }
- }
-}
-
impl ToCss for ImageRect
where C: ToCss,
{
@@ -547,29 +341,3 @@ impl ToCss for ImageRect
dest.write_str(")")
}
}
-
-impl ToComputedValue for ImageRect
- where C: ToComputedValue,
-{
- type ComputedValue = ImageRect<::ComputedValue>;
-
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- ImageRect {
- url: self.url.to_computed_value(context),
- top: self.top.to_computed_value(context),
- right: self.right.to_computed_value(context),
- bottom: self.bottom.to_computed_value(context),
- left: self.left.to_computed_value(context),
- }
- }
-
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- ImageRect {
- url: ToComputedValue::from_computed_value(&computed.url),
- top: ToComputedValue::from_computed_value(&computed.top),
- right: ToComputedValue::from_computed_value(&computed.right),
- bottom: ToComputedValue::from_computed_value(&computed.bottom),
- left: ToComputedValue::from_computed_value(&computed.left),
- }
- }
-}
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index 58445ef39df..983246b9885 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -12,7 +12,6 @@ use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use super::CustomIdent;
-use super::computed::{Context, ToComputedValue};
pub use self::basic_shape::serialize_radius_values;
@@ -20,9 +19,9 @@ pub mod basic_shape;
pub mod image;
pub mod position;
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-/// A type for representing CSS `widthh` and `height` values.
+/// A type for representing CSS `width` and `height` values.
pub struct BorderRadiusSize(pub Size2D);
impl HasViewportPercentage for BorderRadiusSize {
@@ -61,24 +60,6 @@ impl ToCss for BorderRadiusSize {
}
}
-impl ToComputedValue for BorderRadiusSize {
- type ComputedValue = BorderRadiusSize;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- let w = self.0.width.to_computed_value(context);
- let h = self.0.height.to_computed_value(context);
- BorderRadiusSize(Size2D::new(w, h))
- }
-
- #[inline]
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- let w = ToComputedValue::from_computed_value(&computed.0.width);
- let h = ToComputedValue::from_computed_value(&computed.0.height);
- BorderRadiusSize(Size2D::new(w, h))
- }
-}
-
/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
///
/// Since wherever is used, 'none' is a valid value as
diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs
index 7e13919d30c..4ce5b63ab30 100644
--- a/components/style/values/generics/position.rs
+++ b/components/style/values/generics/position.rs
@@ -5,9 +5,7 @@
//! Generic types for CSS handling of specified and computed values of
//! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position)
-use values::computed::{Context, ToComputedValue};
-
-#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)]
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position).
pub struct Position {
@@ -26,24 +24,3 @@ impl Position {
}
}
}
-
-impl ToComputedValue for Position {
- type ComputedValue = Position<::ComputedValue,
- ::ComputedValue>;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- Position {
- horizontal: self.horizontal.to_computed_value(context),
- vertical: self.vertical.to_computed_value(context),
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- Self {
- horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
- vertical: ToComputedValue::from_computed_value(&computed.vertical),
- }
- }
-}
diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs
index fd47a962ce9..7f4743dccd7 100644
--- a/components/style_derive/lib.rs
+++ b/components/style_derive/lib.rs
@@ -10,9 +10,16 @@ extern crate synstructure;
use proc_macro::TokenStream;
mod has_viewport_percentage;
+mod to_computed_value;
#[proc_macro_derive(HasViewportPercentage)]
pub fn derive_has_viewport_percentage(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
has_viewport_percentage::derive(input).to_string().parse().unwrap()
}
+
+#[proc_macro_derive(ToComputedValue)]
+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()
+}
diff --git a/components/style_derive/to_computed_value.rs b/components/style_derive/to_computed_value.rs
new file mode 100644
index 00000000000..d7c4801dbf8
--- /dev/null
+++ b/components/style_derive/to_computed_value.rs
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use quote;
+use syn;
+use synstructure;
+
+pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
+ let name = &input.ident;
+ let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+ let mut where_clause = where_clause.clone();
+ for param in &input.generics.ty_params {
+ where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into()), None));
+ }
+
+ let computed_value_type = syn::Path::from(syn::PathSegment {
+ ident: name.clone(),
+ parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
+ lifetimes: input.generics.lifetimes.iter().map(|l| {
+ l.lifetime.clone()
+ }).collect(),
+ types: input.generics.ty_params.iter().map(|ty| {
+ syn::Ty::Path(
+ Some(syn::QSelf {
+ ty: Box::new(syn::Ty::Path(None, ty.ident.clone().into())),
+ position: 3,
+ }),
+ syn::Path {
+ global: true,
+ segments: vec![
+ "values".into(),
+ "computed".into(),
+ "ToComputedValue".into(),
+ "ComputedValue".into(),
+ ],
+ },
+ )
+ }).collect(),
+ .. Default::default()
+ }),
+ });
+
+ let to_body = match_body(&input, |field| {
+ quote!(::values::computed::ToComputedValue::to_computed_value(#field, context))
+ });
+ let from_body = match_body(&input, |field| {
+ quote!(::values::computed::ToComputedValue::from_computed_value(#field))
+ });
+
+ quote! {
+ impl #impl_generics ::values::computed::ToComputedValue for #name #ty_generics #where_clause {
+ type ComputedValue = #computed_value_type;
+
+ #[allow(unused_variables)]
+ #[inline]
+ fn to_computed_value(&self, context: &::values::computed::Context) -> Self::ComputedValue {
+ match *self {
+ #to_body
+ }
+ }
+
+ #[inline]
+ fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+ match *computed {
+ #from_body
+ }
+ }
+ }
+ }
+}
+
+fn match_body(input: &syn::DeriveInput, f: F) -> quote::Tokens
+ where F: Fn(&synstructure::BindingInfo) -> quote::Tokens,
+{
+ let by_ref = synstructure::BindStyle::Ref.into();
+ let by_value = synstructure::BindStyle::Move.into();
+
+ synstructure::each_variant(&input, &by_ref, |fields, variant| {
+ let name = if let syn::Body::Enum(_) = input.body {
+ format!("{}::{}", input.ident, variant.ident).into()
+ } else {
+ variant.ident.clone()
+ };
+ let (computed_value, computed_fields) = synstructure::match_pattern(&name, &variant.data, &by_value);
+ let fields_pairs = fields.iter().zip(computed_fields.iter());
+ let mut computations = quote!();
+ computations.append_all(fields_pairs.map(|(field, computed_field)| {
+ let expr = f(field);
+ quote!(let #computed_field = #expr;)
+ }));
+ Some(quote!(
+ #computations
+ #computed_value
+ ))
+ })
+}
+
+/// `#ty: ::values::computed::ToComputedValue`
+fn where_predicate(ty: syn::Ty, computed_value: Option) -> syn::WherePredicate {
+ syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
+ bound_lifetimes: vec![],
+ bounded_ty: ty,
+ bounds: vec![syn::TyParamBound::Trait(
+ syn::PolyTraitRef {
+ bound_lifetimes: vec![],
+ trait_ref: trait_ref(computed_value),
+ },
+ syn::TraitBoundModifier::None
+ )],
+ })
+}
+
+/// `::values::computed::ToComputedValue`
+fn trait_ref(computed_value: Option) -> syn::Path {
+ syn::Path {
+ global: true,
+ segments: vec![
+ "values".into(),
+ "computed".into(),
+ syn::PathSegment {
+ ident: "ToComputedValue".into(),
+ parameters: syn::PathParameters::AngleBracketed(
+ syn::AngleBracketedParameterData {
+ bindings: trait_bindings(computed_value),
+ .. Default::default()
+ }
+ ),
+ }
+ ],
+ }
+}
+
+/// `ComputedValue = #computed_value,`
+fn trait_bindings(computed_value: Option) -> Vec {
+ computed_value.into_iter().map(|ty| {
+ syn::TypeBinding {
+ ident: "ComputedValue".into(),
+ ty: ty,
+ }
+ }).collect()
+}