From cb2e04acf6ee3646ef56bb67c17b779428ad6e61 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 20 May 2017 22:00:05 +0200 Subject: [PATCH 1/3] Remove style::values::HasViewportPercentage reexport --- components/style/cascade_info.rs | 2 +- components/style/custom_properties.rs | 4 ++-- components/style/properties/helpers.mako.rs | 2 +- components/style/properties/longhand/effects.mako.rs | 4 ++-- components/style/properties/longhand/font.mako.rs | 4 ++-- components/style/properties/properties.mako.rs | 4 ++-- components/style/values/generics/basic_shape.rs | 3 +-- components/style/values/generics/image.rs | 3 +-- components/style/values/generics/mod.rs | 3 +-- components/style/values/mod.rs | 1 - components/style/values/specified/calc.rs | 4 ++-- components/style/values/specified/grid.rs | 4 ++-- components/style/values/specified/length.rs | 4 ++-- components/style/values/specified/position.rs | 3 +-- tests/unit/style/parsing/value.rs | 2 +- tests/unit/style/properties/viewport.rs | 2 +- 16 files changed, 22 insertions(+), 27 deletions(-) diff --git a/components/style/cascade_info.rs b/components/style/cascade_info.rs index 5c7565909db..2fdd047dadf 100644 --- a/components/style/cascade_info.rs +++ b/components/style/cascade_info.rs @@ -8,7 +8,7 @@ use dom::TNode; use properties::{DeclaredValue, PropertyDeclaration}; -use values::HasViewportPercentage; +use style_traits::HasViewportPercentage; /// A structure to collect information about the cascade. /// diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 071efade790..15435e4743d 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -14,7 +14,7 @@ use std::ascii::AsciiExt; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::fmt; -use style_traits::ToCss; +use style_traits::{HasViewportPercentage, ToCss}; use stylearc::Arc; /// A custom property name is just an `Atom`. @@ -49,7 +49,7 @@ pub struct SpecifiedValue { references: HashSet, } -impl ::values::HasViewportPercentage for SpecifiedValue { +impl HasViewportPercentage for SpecifiedValue { fn has_viewport_percentage(&self) -> bool { panic!("has_viewport_percentage called before resolving!"); } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index d57f54c24bc..20da42ab58c 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -82,7 +82,7 @@ use smallvec::SmallVec; use std::fmt; #[allow(unused_imports)] - use values::HasViewportPercentage; + use style_traits::HasViewportPercentage; use style_traits::ToCss; pub mod single_value { diff --git a/components/style/properties/longhand/effects.mako.rs b/components/style/properties/longhand/effects.mako.rs index 730142b76a7..0374ae0dafb 100644 --- a/components/style/properties/longhand/effects.mako.rs +++ b/components/style/properties/longhand/effects.mako.rs @@ -87,8 +87,8 @@ ${helpers.predefined_type("clip", spec="https://drafts.fxtf.org/filters/#propdef-filter"> //pub use self::computed_value::T as SpecifiedValue; use std::fmt; - use style_traits::ToCss; - use values::{CSSFloat, HasViewportPercentage}; + use style_traits::{HasViewportPercentage, ToCss}; + use values::CSSFloat; use values::specified::{Angle, Length}; #[cfg(feature = "gecko")] use values::specified::Shadow; diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 191dca52574..29bd2478524 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -550,8 +550,8 @@ ${helpers.single_keyword_system("font-variant-caps", use properties::longhands::system_font::SystemFont; use properties::style_structs::Font; use std::fmt; - use style_traits::ToCss; - use values::{FONT_MEDIUM_PX, HasViewportPercentage}; + use style_traits::{HasViewportPercentage, ToCss}; + use values::FONT_MEDIUM_PX; use values::specified::{AllowQuirks, FontRelativeLength, LengthOrPercentage}; use values::specified::{NoCalcLength, Percentage}; use values::specified::length::FontBaseSize; diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 47022d30a6a..158bdbf6e78 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -34,10 +34,10 @@ use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext}; use properties::animated_properties::TransitionProperty; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; use shared_lock::StylesheetGuards; -use style_traits::ToCss; +use style_traits::{HasViewportPercentage, ToCss}; use stylesheets::{CssRuleType, Origin, UrlExtraData}; #[cfg(feature = "servo")] use values::Either; -use values::{HasViewportPercentage, computed}; +use values::computed; use cascade_info::CascadeInfo; use rule_tree::StrongRuleNode; use style_adjuster::StyleAdjuster; diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index d961141dbc9..f75c038b59a 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -11,8 +11,7 @@ use parser::{Parse, ParserContext}; use properties::shorthands::serialize_four_sides; use std::ascii::AsciiExt; use std::fmt; -use style_traits::ToCss; -use values::HasViewportPercentage; +use style_traits::{HasViewportPercentage, ToCss}; use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::generics::BorderRadiusSize; use values::specified::url::SpecifiedUrl; diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index 2b42314eb00..034bc0c2859 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -9,8 +9,7 @@ use Atom; use cssparser::serialize_identifier; use std::fmt; -use style_traits::ToCss; -use values::HasViewportPercentage; +use style_traits::{HasViewportPercentage, ToCss}; use values::computed::{Context, ToComputedValue}; use values::specified::url::SpecifiedUrl; diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 9ad4668f4da..58445ef39df 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -10,9 +10,8 @@ use cssparser::Parser; use euclid::size::Size2D; use parser::{Parse, ParserContext}; use std::fmt; -use style_traits::ToCss; +use style_traits::{HasViewportPercentage, ToCss}; use super::CustomIdent; -use super::HasViewportPercentage; use super::computed::{Context, ToComputedValue}; pub use self::basic_shape::serialize_radius_values; diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 6a6469a1742..bbb6603bb90 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -16,7 +16,6 @@ use std::borrow::Cow; use std::fmt::{self, Debug}; use std::hash; use style_traits::ToCss; -pub use style_traits::HasViewportPercentage; pub mod computed; pub mod generics; diff --git a/components/style/values/specified/calc.rs b/components/style/values/specified/calc.rs index 4db36e998c2..dc6f5cf2f81 100644 --- a/components/style/values/specified/calc.rs +++ b/components/style/values/specified/calc.rs @@ -11,9 +11,9 @@ use cssparser::{Parser, Token}; use parser::ParserContext; use std::ascii::AsciiExt; use std::fmt; -use style_traits::ToCss; +use style_traits::{HasViewportPercentage, ToCss}; use style_traits::values::specified::AllowedLengthType; -use values::{CSSInteger, CSSFloat, HasViewportPercentage}; +use values::{CSSInteger, CSSFloat}; use values::specified::{Angle, Time}; use values::specified::length::{FontRelativeLength, NoCalcLength, ViewportPercentageLength}; diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index a4a8b930ef8..0633a0b0e80 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -8,8 +8,8 @@ use cssparser::{Parser, Token, serialize_identifier}; use parser::{Parse, ParserContext}; use std::{fmt, mem, usize}; use std::ascii::AsciiExt; -use style_traits::ToCss; -use values::{CSSFloat, CustomIdent, Either, HasViewportPercentage}; +use style_traits::{HasViewportPercentage, ToCss}; +use values::{CSSFloat, CustomIdent, Either}; use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue}; use values::specified::{Integer, LengthOrPercentage}; diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 331901bf8c6..830b433b80c 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -14,11 +14,11 @@ use parser::{Parse, ParserContext}; use std::{cmp, fmt, mem}; use std::ascii::AsciiExt; use std::ops::Mul; -use style_traits::ToCss; +use style_traits::{HasViewportPercentage, ToCss}; use style_traits::values::specified::{AllowedLengthType, AllowedNumericType}; use stylesheets::CssRuleType; use super::{AllowQuirks, Number, ToComputedValue}; -use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, HasViewportPercentage, None_, Normal}; +use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, None_, Normal}; use values::ExtremumLength; use values::computed::{ComputedValueAsSpecified, Context}; use values::specified::calc::CalcNode; diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index a4b4953c372..085fea59300 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -10,8 +10,7 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use std::fmt; -use style_traits::ToCss; -use values::HasViewportPercentage; +use style_traits::{HasViewportPercentage, ToCss}; use values::computed::{CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage}; use values::computed::{Context, ToComputedValue}; use values::generics::position::Position as GenericPosition; diff --git a/tests/unit/style/parsing/value.rs b/tests/unit/style/parsing/value.rs index 3a1f69746e4..5808f875747 100644 --- a/tests/unit/style/parsing/value.rs +++ b/tests/unit/style/parsing/value.rs @@ -8,8 +8,8 @@ use media_queries::CSSErrorReporterTest; use style::context::QuirksMode; use style::parser::{PARSING_MODE_ALLOW_ALL_NUMERIC_VALUES, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; -use style::values::HasViewportPercentage; use style::values::specified::{AbsoluteLength, NoCalcLength, Number, ViewportPercentageLength}; +use style_traits::HasViewportPercentage; #[test] fn length_has_viewport_percentage() { diff --git a/tests/unit/style/properties/viewport.rs b/tests/unit/style/properties/viewport.rs index 4444e19e023..ce4f879224e 100644 --- a/tests/unit/style/properties/viewport.rs +++ b/tests/unit/style/properties/viewport.rs @@ -5,8 +5,8 @@ use app_units::Au; use style::properties::PropertyDeclaration; use style::properties::longhands::border_top_width; -use style::values::HasViewportPercentage; use style::values::specified::{AbsoluteLength, Length, NoCalcLength, ViewportPercentageLength}; +use style_traits::HasViewportPercentage; #[test] fn has_viewport_percentage_for_specified_value() { From a99e73ba6bc1c35f34564adf42a8a4af156b04e3 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 20 May 2017 22:00:36 +0200 Subject: [PATCH 2/3] Silence a warning in servo_geometry --- components/geometry/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/components/geometry/lib.rs b/components/geometry/lib.rs index 453cf0997c5..8b98301dde7 100644 --- a/components/geometry/lib.rs +++ b/components/geometry/lib.rs @@ -10,7 +10,6 @@ use app_units::{Au, MAX_AU, MIN_AU}; use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; -use std::i32; // Units for use with euclid::length and euclid::scale_factor. From 07c0456cfd5a2be826d49be3accffe12ac692971 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 21 May 2017 01:04:00 +0200 Subject: [PATCH 3/3] Derive ToComputedValue For now, only impls for types like in style::values::generics can be derived. This also needed a few ToComputedValueAsSpecified impls that I would like to replace by some #[to_computed_value(clone)] attribute, but I think it is ok to keep it like this for now. --- components/style/values/computed/mod.rs | 77 ++++++ .../style/values/generics/basic_shape.rs | 139 +--------- components/style/values/generics/image.rs | 256 +----------------- components/style/values/generics/mod.rs | 23 +- components/style/values/generics/position.rs | 25 +- components/style_derive/lib.rs | 7 + components/style_derive/to_computed_value.rs | 142 ++++++++++ 7 files changed, 247 insertions(+), 422 deletions(-) create mode 100644 components/style_derive/to_computed_value.rs diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 8c537eb3694..94042158c48 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -4,6 +4,7 @@ //! Computed values. +use Atom; use context::QuirksMode; use euclid::size::Size2D; use font_metrics::FontMetricsProvider; @@ -154,6 +155,79 @@ pub trait ToComputedValue { fn from_computed_value(computed: &Self::ComputedValue) -> Self; } +impl ToComputedValue for (A, B) + where A: ToComputedValue, B: ToComputedValue, +{ + type ComputedValue = ( + ::ComputedValue, + ::ComputedValue, + ); + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + (self.0.to_computed_value(context), self.1.to_computed_value(context)) + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + (A::from_computed_value(&computed.0), B::from_computed_value(&computed.1)) + } +} + +impl ToComputedValue for Option + where T: ToComputedValue +{ + type ComputedValue = Option<::ComputedValue>; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + self.as_ref().map(|item| item.to_computed_value(context)) + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + computed.as_ref().map(T::from_computed_value) + } +} + +impl ToComputedValue for Size2D + where T: ToComputedValue +{ + type ComputedValue = Size2D<::ComputedValue>; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + Size2D::new( + self.width.to_computed_value(context), + self.height.to_computed_value(context), + ) + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + Size2D::new( + T::from_computed_value(&computed.width), + T::from_computed_value(&computed.height), + ) + } +} + +impl ToComputedValue for Vec + where T: ToComputedValue +{ + type ComputedValue = Vec<::ComputedValue>; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + self.iter().map(|item| item.to_computed_value(context)).collect() + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + computed.iter().map(T::from_computed_value).collect() + } +} + /// A marker trait to represent that the specified value is also the computed /// value. pub trait ComputedValueAsSpecified {} @@ -174,6 +248,9 @@ impl ToComputedValue for T } } +impl ComputedValueAsSpecified for Atom {} +impl ComputedValueAsSpecified for bool {} + /// A computed `` value. #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd)] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index f75c038b59a..31f434414f5 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -12,14 +12,14 @@ use properties::shorthands::serialize_four_sides; use std::ascii::AsciiExt; use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; -use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; +use values::computed::ComputedValueAsSpecified; use values::generics::BorderRadiusSize; use values::specified::url::SpecifiedUrl; /// A generic type used for `border-radius`, `outline-radius` and `inset()` values. /// /// https://drafts.csswg.org/css-backgrounds-3/#border-radius -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct BorderRadius { /// The top left radius. @@ -59,32 +59,8 @@ impl ToCss for BorderRadius { } } -impl ToComputedValue for BorderRadius { - type ComputedValue = BorderRadius; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - BorderRadius { - top_left: self.top_left.to_computed_value(cx), - top_right: self.top_right.to_computed_value(cx), - bottom_right: self.bottom_right.to_computed_value(cx), - bottom_left: self.bottom_left.to_computed_value(cx), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - BorderRadius { - top_left: ToComputedValue::from_computed_value(&computed.top_left), - top_right: ToComputedValue::from_computed_value(&computed.top_right), - bottom_right: ToComputedValue::from_computed_value(&computed.bottom_right), - bottom_left: ToComputedValue::from_computed_value(&computed.bottom_left), - } - } -} - /// https://drafts.csswg.org/css-shapes/#typedef-shape-radius -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] pub enum ShapeRadius { @@ -109,28 +85,6 @@ impl ToCss for ShapeRadius { } } -impl ToComputedValue for ShapeRadius { - type ComputedValue = ShapeRadius; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - match *self { - ShapeRadius::Length(ref lop) => ShapeRadius::Length(lop.to_computed_value(cx)), - ShapeRadius::ClosestSide => ShapeRadius::ClosestSide, - ShapeRadius::FarthestSide => ShapeRadius::FarthestSide, - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - ShapeRadius::Length(ref lop) => ShapeRadius::Length(ToComputedValue::from_computed_value(lop)), - ShapeRadius::ClosestSide => ShapeRadius::ClosestSide, - ShapeRadius::FarthestSide => ShapeRadius::FarthestSide, - } - } -} - // https://drafts.csswg.org/css-shapes/#typedef-fill-rule // NOTE: Basic shapes spec says that these are the only two values, however // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty @@ -147,7 +101,7 @@ impl Default for FillRule { fn default() -> Self { FillRule::NonZero } } -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// A generic type for representing the `polygon()` function /// @@ -211,32 +165,7 @@ impl ToCss for Polygon { } } -impl ToComputedValue for Polygon { - type ComputedValue = Polygon; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - Polygon { - fill: self.fill.to_computed_value(cx), - coordinates: self.coordinates.iter().map(|c| { - (c.0.to_computed_value(cx), c.1.to_computed_value(cx)) - }).collect(), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - Polygon { - fill: ToComputedValue::from_computed_value(&computed.fill), - coordinates: computed.coordinates.iter().map(|c| { - (ToComputedValue::from_computed_value(&c.0), - ToComputedValue::from_computed_value(&c.1)) - }).collect(), - } - } -} - -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// https://drafts.csswg.org/css-shapes/#funcdef-inset #[allow(missing_docs)] @@ -268,37 +197,11 @@ impl ToCss for InsetRect { } } -impl ToComputedValue for InsetRect { - type ComputedValue = InsetRect; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - InsetRect { - top: self.top.to_computed_value(cx), - right: self.right.to_computed_value(cx), - bottom: self.bottom.to_computed_value(cx), - left: self.left.to_computed_value(cx), - round: self.round.as_ref().map(|r| r.to_computed_value(cx)), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - InsetRect { - 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), - round: computed.round.as_ref().map(|r| ToComputedValue::from_computed_value(r)), - } - } -} - /// A shape source, for some reference box /// /// `clip-path` uses ShapeSource, /// `shape-outside` uses ShapeSource -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] pub enum ShapeSource { @@ -364,33 +267,3 @@ impl Parse for ShapeSource { ref_box.map(|v| ShapeSource::Box(v)).ok_or(()) } } - -impl ToComputedValue for ShapeSource { - type ComputedValue = ShapeSource; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - match *self { - ShapeSource::Url(ref url) => ShapeSource::Url(url.to_computed_value(cx)), - ShapeSource::Shape(ref shape, ref ref_box) => { - ShapeSource::Shape(shape.to_computed_value(cx), - ref_box.as_ref().map(|ref val| val.to_computed_value(cx))) - }, - ShapeSource::Box(ref ref_box) => ShapeSource::Box(ref_box.to_computed_value(cx)), - ShapeSource::None => ShapeSource::None, - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - ShapeSource::Url(ref url) => ShapeSource::Url(SpecifiedUrl::from_computed_value(url)), - ShapeSource::Shape(ref shape, ref ref_box) => { - ShapeSource::Shape(ToComputedValue::from_computed_value(shape), - ref_box.as_ref().map(|val| ToComputedValue::from_computed_value(val))) - }, - ShapeSource::Box(ref ref_box) => ShapeSource::Box(ToComputedValue::from_computed_value(ref_box)), - ShapeSource::None => ShapeSource::None, - } - } -} diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index 034bc0c2859..9aa49428dce 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -10,13 +10,13 @@ use Atom; use cssparser::serialize_identifier; use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; -use values::computed::{Context, ToComputedValue}; +use values::computed::ComputedValueAsSpecified; use values::specified::url::SpecifiedUrl; /// An [image]. /// /// [image]: https://drafts.csswg.org/css-images/#image-values -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum Image { /// A `` image. @@ -31,7 +31,7 @@ pub enum Image { /// A CSS gradient. /// https://drafts.csswg.org/css-images/#gradients -#[derive(Clone, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct Gradient { /// Gradients can be linear or radial. @@ -44,7 +44,7 @@ pub struct Gradient pub compat_mode: CompatMode, } -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// Whether we used the modern notation or the compatibility `-webkit` prefix. pub enum CompatMode { @@ -55,7 +55,7 @@ pub enum CompatMode { } /// A gradient kind. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum GradientKind { /// A linear gradient. @@ -65,7 +65,7 @@ pub enum GradientKind { } /// A radial gradient's ending shape. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum EndingShape { /// A circular gradient. @@ -75,7 +75,7 @@ pub enum EndingShape { } /// A circle shape. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum Circle { /// A circle radius. @@ -85,7 +85,7 @@ pub enum Circle { } /// An ellipse shape. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum Ellipse { /// An ellipse pair of radii. @@ -104,10 +104,11 @@ define_css_keyword_enum!(ShapeExtent: "cover" => Cover ); no_viewport_percentage!(ShapeExtent); +impl ComputedValueAsSpecified for ShapeExtent {} /// A gradient item. /// https://drafts.csswg.org/css-images-4/#color-stop-syntax -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum GradientItem { /// A color stop. @@ -118,7 +119,7 @@ pub enum GradientItem { /// A color stop. /// https://drafts.csswg.org/css-images/#typedef-color-stop-list -#[derive(Clone, Copy, HasViewportPercentage, PartialEq)] +#[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct ColorStop { /// The color of this stop. @@ -130,7 +131,7 @@ pub struct ColorStop { /// Values for `moz-image-rect`. /// /// `-moz-image-rect(, top, right, bottom, left);` -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] pub struct ImageRect { @@ -186,47 +187,6 @@ impl HasViewportPercentage for Image } } -impl ToComputedValue for Image - where G: ToComputedValue, R: ToComputedValue, -{ - type ComputedValue = Image<::ComputedValue, - ::ComputedValue>; - - fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - match *self { - Image::Url(ref url) => { - Image::Url(url.clone()) - }, - Image::Gradient(ref gradient) => { - Image::Gradient(gradient.to_computed_value(context)) - }, - Image::Rect(ref rect) => { - Image::Rect(rect.to_computed_value(context)) - }, - Image::Element(ref selector) => { - Image::Element(selector.clone()) - } - } - } - - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - Image::Url(ref url) => { - Image::Url(url.clone()) - }, - Image::Gradient(ref gradient) => { - Image::Gradient(ToComputedValue::from_computed_value(gradient)) - }, - Image::Rect(ref rect) => { - Image::Rect(ToComputedValue::from_computed_value(rect)) - }, - Image::Element(ref selector) => { - Image::Element(selector.clone()) - }, - } - } -} - impl ToCss for Gradient where D: LineDirection, L: ToCss, LoP: ToCss, P: ToCss, C: ToCss, { @@ -281,38 +241,6 @@ impl ToCss for Gradient } } -impl ToComputedValue for Gradient - where D: ToComputedValue, - L: ToComputedValue, - LoP: ToComputedValue, - P: ToComputedValue, - C: ToComputedValue, -{ - type ComputedValue = Gradient<::ComputedValue, - ::ComputedValue, - ::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() +}