From b14e68f91536c717c6b6bfa105df597bef04c3e7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 12 Aug 2017 13:26:04 +0200 Subject: [PATCH 1/3] Remove impl_animatable_for_option_tuple --- components/style/properties/helpers.mako.rs | 57 --------------------- 1 file changed, 57 deletions(-) diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 82eeb653e16..540007298d5 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -956,63 +956,6 @@ %> -/// Macro for defining Animatable trait for tuple struct which has Option, -/// e.g. struct T(pub Option). -<%def name="impl_animatable_for_option_tuple(value_for_none)"> - impl Animatable for T { - #[inline] - fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) - -> Result { - match (self, other) { - (&T(Some(ref this)), &T(Some(ref other))) => { - Ok(T(this.add_weighted(other, self_portion, other_portion).ok())) - }, - (&T(Some(ref this)), &T(None)) => { - Ok(T(this.add_weighted(&${value_for_none}, self_portion, other_portion).ok())) - }, - (&T(None), &T(Some(ref other))) => { - Ok(T(${value_for_none}.add_weighted(other, self_portion, other_portion).ok())) - }, - (&T(None), &T(None)) => { - Ok(T(None)) - }, - } - } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&T(Some(ref this)), &T(Some(ref other))) => { - this.compute_distance(other) - }, - (&T(Some(ref value)), &T(None)) | - (&T(None), &T(Some(ref value)))=> { - value.compute_distance(&${value_for_none}) - }, - (&T(None), &T(None)) => { - Ok(0.0) - }, - } - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&T(Some(ref this)), &T(Some(ref other))) => { - this.compute_squared_distance(other) - }, - (&T(Some(ref value)), &T(None)) | - (&T(None), &T(Some(ref value))) => { - value.compute_squared_distance(&${value_for_none}) - }, - (&T(None), &T(None)) => { - Ok(0.0) - }, - } - } - } - - // Define property that supports prefixed intrinsic size keyword values for gecko. // E.g. -moz-max-content, -moz-min-content, etc. <%def name="gecko_size_type(name, length_type, initial_value, logical, **kwargs)"> From 51b740033baaeb5fd4ce7ae1ad0b8dad3b3b7d9e Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 12 Aug 2017 17:36:52 +0200 Subject: [PATCH 2/3] Introduce ComputeSquaredDistance This allows us to merge the former Animatable methods compute_distance and compute_squared_distance, reducing code size. --- components/style/macros.rs | 10 + components/style/properties/helpers.mako.rs | 10 +- .../helpers/animated_properties.mako.rs | 525 ++++-------------- .../style/properties/longhand/font.mako.rs | 19 +- .../longhand/inherited_table.mako.rs | 16 +- components/style/values/animated/effects.rs | 27 +- .../style/values/computed/background.rs | 10 +- components/style/values/computed/length.rs | 96 ++++ components/style/values/computed/mod.rs | 29 + components/style/values/computed/text.rs | 23 +- components/style/values/computed/transform.rs | 10 +- components/style/values/distance.rs | 124 +++++ .../style/values/generics/basic_shape.rs | 121 ++-- components/style/values/generics/border.rs | 24 +- components/style/values/generics/mod.rs | 21 + components/style/values/generics/position.rs | 16 + components/style/values/generics/rect.rs | 16 + components/style/values/generics/svg.rs | 59 ++ components/style/values/generics/text.rs | 12 +- components/style/values/mod.rs | 21 + ports/geckolib/glue.rs | 3 +- 21 files changed, 641 insertions(+), 551 deletions(-) create mode 100644 components/style/values/distance.rs diff --git a/components/style/macros.rs b/components/style/macros.rs index d72ecc73c06..3251b7e2d37 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -117,5 +117,15 @@ macro_rules! define_keyword_type { #[inline] fn to_animated_zero(&self) -> Result { Ok($name) } } + + impl $crate::values::distance::ComputeSquaredDistance for $name { + #[inline] + fn compute_squared_distance( + &self, + _other: &Self + ) -> Result<$crate::values::distance::SquaredDistance, ()> { + Ok($crate::values::distance::SquaredDistance::Value(0.)) + } + } }; } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 540007298d5..d428cc20cdb 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -132,6 +132,7 @@ % if need_animatable or animation_value_type == "ComputedValue": use properties::animated_properties::Animatable; use values::animated::ToAnimatedZero; + use values::distance::{ComputeSquaredDistance, SquaredDistance}; impl Animatable for T { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) @@ -142,14 +143,11 @@ fn add(&self, other: &Self) -> Result { self.0.add(&other.0).map(T) } + } + impl ComputeSquaredDistance for T { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.0.compute_distance(&other.0) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { self.0.compute_squared_distance(&other.0) } } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 1b4755b4bb7..4b423751d6b 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -49,6 +49,7 @@ use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToC use values::computed::{NonNegativeAu, NonNegativeNumber, PositiveIntegerOrAuto}; use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal}; use values::computed::length::NonNegativeLengthOrPercentage; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::{GreaterThanOrEqualToOne, NonNegative}; use values::generics::effects::Filter; use values::generics::position as generic_position; @@ -83,16 +84,6 @@ pub trait Animatable: Sized { fn accumulate(&self, other: &Self, count: u64) -> Result { self.add_weighted(other, count as f64, 1.0) } - - /// Compute distance between a value and another for a given property. - fn compute_distance(&self, _other: &Self) -> Result { Err(()) } - - /// In order to compute the Euclidean distance of a list or property value with multiple - /// components, we need to compute squared distance for each element, so the vector can sum it - /// and then get its squared root as the distance. - fn compute_squared_distance(&self, other: &Self) -> Result { - self.compute_distance(other).map(|d| d * d) - } } /// https://drafts.csswg.org/css-transitions/#animtype-repeatable-list @@ -741,28 +732,31 @@ impl Animatable for AnimationValue { } } } +} - fn compute_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for AnimationValue { + fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { % for prop in data.longhands: - % if prop.animatable: - % if prop.animation_value_type != "discrete": - (&AnimationValue::${prop.camel_case}(ref from), - &AnimationValue::${prop.camel_case}(ref to)) => { - from.compute_distance(to) - }, - % else: - (&AnimationValue::${prop.camel_case}(ref _from), - &AnimationValue::${prop.camel_case}(ref _to)) => { - Err(()) - }, - % endif - % endif + % if prop.animatable: + % if prop.animation_value_type != "discrete": + (&AnimationValue::${prop.camel_case}(ref this), &AnimationValue::${prop.camel_case}(ref other)) => { + this.compute_squared_distance(other) + }, + % else: + (&AnimationValue::${prop.camel_case}(_), &AnimationValue::${prop.camel_case}(_)) => { + Err(()) + }, + % endif + % endif % endfor _ => { - panic!("Expected compute_distance of computed values of the same \ - property, got: {:?}, {:?}", self, other); - } + panic!( + "computed values should be of the same property, got: {:?}, {:?}", + self, + other + ); + }, } } } @@ -802,22 +796,21 @@ macro_rules! repeated_vec_impl { me.add_weighted(you, self_portion, other_portion) }).collect() } + } + impl ComputeSquaredDistance for $ty + where + T: ComputeSquaredDistance + RepeatableListAnimatable, + { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - // If the length of either list is zero, the least common multiple is undefined. - if cmp::min(self.len(), other.len()) < 1 { + fn compute_squared_distance(&self, other: &Self) -> Result { + if self.is_empty() || other.is_empty() { return Err(()); } use num_integer::lcm; let len = lcm(self.len(), other.len()); - self.iter().cycle().zip(other.iter().cycle()).take(len).map(|(me, you)| { - me.compute_squared_distance(you) + self.iter().cycle().zip(other.iter().cycle()).take(len).map(|(this, other)| { + this.compute_squared_distance(other) }).sum() } })* @@ -832,11 +825,6 @@ impl Animatable for Au { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { Ok(Au((self.0 as f64 * self_portion + other.0 as f64 * other_portion).round() as i32)) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.0.compute_distance(&other.0) - } } impl Animatable for Option @@ -852,28 +840,6 @@ impl Animatable for Option _ => Err(()), } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&Some(ref this), &Some(ref other)) => { - this.compute_distance(other) - }, - (&None, &None) => Ok(0.0), - _ => Err(()), - } - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&Some(ref this), &Some(ref other)) => { - this.compute_squared_distance(other) - }, - (&None, &None) => Ok(0.0), - _ => Err(()), - } - } } /// https://drafts.csswg.org/css-transitions/#animtype-number @@ -882,11 +848,6 @@ impl Animatable for f32 { fn add_weighted(&self, other: &f32, self_portion: f64, other_portion: f64) -> Result { Ok((*self as f64 * self_portion + *other as f64 * other_portion) as f32) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - Ok((*self - *other).abs() as f64) - } } /// https://drafts.csswg.org/css-transitions/#animtype-number @@ -895,11 +856,6 @@ impl Animatable for f64 { fn add_weighted(&self, other: &f64, self_portion: f64, other_portion: f64) -> Result { Ok(*self * self_portion + *other * other_portion) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - Ok((*self - *other).abs()) - } } /// https://drafts.csswg.org/css-transitions/#animtype-integer @@ -908,11 +864,6 @@ impl Animatable for i32 { fn add_weighted(&self, other: &i32, self_portion: f64, other_portion: f64) -> Result { Ok((*self as f64 * self_portion + *other as f64 * other_portion).round() as i32) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - Ok((*self - *other).abs() as f64) - } } /// https://drafts.csswg.org/css-transitions/#animtype-number @@ -934,13 +885,6 @@ impl Animatable for Angle { } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - // Use the formula for calculating the distance between angles defined in SVG: - // https://www.w3.org/TR/SVG/animate.html#complexDistances - Ok((self.radians64() - other.radians64()).abs()) - } } /// https://drafts.csswg.org/css-transitions/#animtype-percentage @@ -949,11 +893,6 @@ impl Animatable for Percentage { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { Ok(Percentage((self.0 as f64 * self_portion + other.0 as f64 * other_portion) as f32)) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - Ok((self.0 as f64 - other.0 as f64).abs()) - } } impl ToAnimatedZero for Percentage { @@ -977,14 +916,12 @@ impl Animatable for Visibility { _ => Err(()), } } +} +impl ComputeSquaredDistance for Visibility { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - if *self == *other { - Ok(0.0) - } else { - Ok(1.0) - } + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok(SquaredDistance::Value(if *self == *other { 0. } else { 1. })) } } @@ -1003,16 +940,6 @@ impl Animatable for Size2D { Ok(Size2D::new(width, height)) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - Ok(self.compute_squared_distance(other)?.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok(self.width.compute_squared_distance(&other.width)? + self.height.compute_squared_distance(&other.height)?) - } } impl Animatable for Point2D { @@ -1044,15 +971,20 @@ impl Animatable for VerticalAlign { _ => Err(()), } } +} +impl ComputeSquaredDistance for VerticalAlign { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (VerticalAlign::LengthOrPercentage(ref this), - VerticalAlign::LengthOrPercentage(ref other)) => { - this.compute_distance(other) + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&VerticalAlign::LengthOrPercentage(ref this), &VerticalAlign::LengthOrPercentage(ref other)) => { + this.compute_squared_distance(other) + }, + _ => { + // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` + // if `self` and `other` are the same keyword value? + Err(()) }, - _ => Err(()), } } } @@ -1087,18 +1019,6 @@ impl Animatable for CalcLengthOrPercentage { let percentage = add_weighted_half(self.percentage, other.percentage, self_portion, other_portion)?; Ok(CalcLengthOrPercentage::with_clamping_mode(length, percentage, self.clamping_mode)) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sq| sq.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - let length_diff = (self.unclamped_length().0 - other.unclamped_length().0) as f64; - let percentage_diff = (self.percentage() - other.percentage()) as f64; - Ok(length_diff * length_diff + percentage_diff * percentage_diff) - } } /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc @@ -1131,48 +1051,6 @@ impl Animatable for LengthOrPercentage { } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (LengthOrPercentage::Length(ref this), - LengthOrPercentage::Length(ref other)) => { - this.compute_distance(other) - }, - (LengthOrPercentage::Percentage(ref this), - LengthOrPercentage::Percentage(ref other)) => { - this.compute_distance(other) - }, - (this, other) => { - let this: CalcLengthOrPercentage = From::from(this); - let other: CalcLengthOrPercentage = From::from(other); - this.compute_distance(&other) - } - } - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (LengthOrPercentage::Length(ref this), - LengthOrPercentage::Length(ref other)) => { - let diff = (this.0 - other.0) as f64; - Ok(diff * diff) - }, - (LengthOrPercentage::Percentage(ref this), - LengthOrPercentage::Percentage(ref other)) => { - let diff = this.0 as f64 - other.0 as f64; - Ok(diff * diff) - }, - (this, other) => { - let this: CalcLengthOrPercentage = From::from(this); - let other: CalcLengthOrPercentage = From::from(other); - let length_diff = (this.unclamped_length().0 - other.unclamped_length().0) as f64; - let percentage_diff = (this.percentage() - other.percentage()) as f64; - Ok(length_diff * length_diff + percentage_diff * percentage_diff) - } - } - } } impl ToAnimatedZero for LengthOrPercentage { @@ -1210,53 +1088,6 @@ impl Animatable for LengthOrPercentageOrAuto { } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (LengthOrPercentageOrAuto::Length(ref this), - LengthOrPercentageOrAuto::Length(ref other)) => { - this.compute_distance(other) - }, - (LengthOrPercentageOrAuto::Percentage(ref this), - LengthOrPercentageOrAuto::Percentage(ref other)) => { - this.compute_distance(other) - }, - (this, other) => { - // If one of the element is Auto, Option<> will be None, and the returned distance is Err(()) - let this: Option = From::from(this); - let other: Option = From::from(other); - this.compute_distance(&other) - } - } - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (LengthOrPercentageOrAuto::Length(ref this), - LengthOrPercentageOrAuto::Length(ref other)) => { - let diff = (this.0 - other.0) as f64; - Ok(diff * diff) - }, - (LengthOrPercentageOrAuto::Percentage(ref this), - LengthOrPercentageOrAuto::Percentage(ref other)) => { - let diff = this.0 as f64 - other.0 as f64; - Ok(diff * diff) - }, - (this, other) => { - let this: Option = From::from(this); - let other: Option = From::from(other); - if let (Some(this), Some(other)) = (this, other) { - let length_diff = (this.unclamped_length().0 - other.unclamped_length().0) as f64; - let percentage_diff = (this.percentage() - other.percentage()) as f64; - Ok(length_diff * length_diff + percentage_diff * percentage_diff) - } else { - Err(()) - } - } - } - } } impl ToAnimatedZero for LengthOrPercentageOrAuto { @@ -1301,26 +1132,6 @@ impl Animatable for LengthOrPercentageOrNone { }, } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (LengthOrPercentageOrNone::Length(ref this), - LengthOrPercentageOrNone::Length(ref other)) => { - this.compute_distance(other) - }, - (LengthOrPercentageOrNone::Percentage(ref this), - LengthOrPercentageOrNone::Percentage(ref other)) => { - this.compute_distance(other) - }, - (this, other) => { - // If one of the element is Auto, Option<> will be None, and the returned distance is Err(()) - let this = >::from(this); - let other = >::from(other); - this.compute_distance(&other) - }, - } - } } impl ToAnimatedZero for LengthOrPercentageOrNone { @@ -1350,17 +1161,6 @@ impl Animatable for MozLength { _ => Err(()), } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (MozLength::LengthOrPercentageOrAuto(ref this), - MozLength::LengthOrPercentageOrAuto(ref other)) => { - this.compute_distance(other) - }, - _ => Err(()), - } - } } impl ToAnimatedZero for MozLength { @@ -1388,17 +1188,6 @@ impl Animatable for MaxLength { _ => Err(()), } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (MaxLength::LengthOrPercentageOrNone(ref this), - MaxLength::LengthOrPercentageOrNone(ref other)) => { - this.compute_distance(other) - }, - _ => Err(()), - } - } } impl ToAnimatedZero for MaxLength { @@ -1417,13 +1206,6 @@ impl Animatable for FontWeight { let weight = (weight.max(100.).min(900.) / 100.).round() * 100.; Ok(FontWeight(weight as u16)) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - let a = self.0 as f64; - let b = other.0 as f64; - a.compute_distance(&b) - } } impl ToAnimatedZero for FontWeight { @@ -1447,12 +1229,12 @@ impl Animatable for FontStretch { Ok(result.into()) } +} +impl ComputeSquaredDistance for FontStretch { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - let from = f64::from(*self); - let to = f64::from(*other); - from.compute_distance(&to) + fn compute_squared_distance(&self, other: &Self) -> Result { + f64::from(*self).compute_squared_distance(&(*other).into()) } } @@ -1500,17 +1282,6 @@ impl Animatable for generic_position::Position Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok(self.horizontal.compute_squared_distance(&other.horizontal)? + - self.vertical.compute_squared_distance(&other.vertical)?) - } } impl ToAnimatedZero for generic_position::Position @@ -1542,22 +1313,6 @@ impl Animatable for ClipRect { left: self.left.add_weighted(&other.left, self_portion, other_portion)?, }) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - let list = [ - self.top.compute_distance(&other.top)?, - self.right.compute_distance(&other.right)?, - self.bottom.compute_distance(&other.bottom)?, - self.left.compute_distance(&other.left)? - ]; - Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff)) - } } impl ToAnimatedZero for ClipRect { @@ -2641,6 +2396,14 @@ impl Animatable for TransformList { } } +impl ComputeSquaredDistance for TransformList { + #[inline] + fn compute_squared_distance(&self, _other: &Self) -> Result { + // FIXME: This should be implemented. + Err(()) + } +} + impl ToAnimatedZero for TransformList { #[inline] fn to_animated_zero(&self) -> Result { @@ -2666,32 +2429,6 @@ impl Animatable for Either } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&Either::First(ref this), &Either::First(ref other)) => { - this.compute_distance(other) - }, - (&Either::Second(ref this), &Either::Second(ref other)) => { - this.compute_distance(other) - }, - _ => Err(()) - } - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&Either::First(ref this), &Either::First(ref other)) => { - this.compute_squared_distance(other) - }, - (&Either::Second(ref this), &Either::Second(ref other)) => { - this.compute_squared_distance(other) - }, - _ => Err(()) - } - } } impl ToAnimatedZero for Either @@ -2789,28 +2526,14 @@ impl Animatable for IntermediateRGBA { Ok(IntermediateRGBA::new(red, green, blue, alpha)) } } +} +impl ComputeSquaredDistance for IntermediateRGBA { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sq| sq.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - let start = [ self.alpha, - self.red * self.alpha, - self.green * self.alpha, - self.blue * self.alpha ]; - let end = [ other.alpha, - other.red * other.alpha, - other.green * other.alpha, - other.blue * other.alpha ]; - let diff = start.iter().zip(&end) - .fold(0.0f64, |n, (&a, &b)| { - let diff = (a - b) as f64; - n + diff * diff - }); - Ok(diff) + fn compute_squared_distance(&self, other: &Self) -> Result { + let start = [ self.alpha, self.red * self.alpha, self.green * self.alpha, self.blue * self.alpha ]; + let end = [ other.alpha, other.red * other.alpha, other.green * other.alpha, other.blue * other.alpha ]; + start.iter().zip(&end).map(|(this, other)| this.compute_squared_distance(other)).sum() } } @@ -2930,31 +2653,35 @@ impl Animatable for IntermediateColor { }) } } +} +impl ComputeSquaredDistance for IntermediateColor { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sq| sq.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { // All comments in add_weighted also applies here. if self.foreground_ratio == other.foreground_ratio { if self.is_currentcolor() { - Ok(0.) + Ok(SquaredDistance::Value(0.)) } else { self.color.compute_squared_distance(&other.color) } } else if self.is_currentcolor() && other.is_numeric() { - Ok(IntermediateRGBA::transparent().compute_squared_distance(&other.color)? + 1.) + Ok( + IntermediateRGBA::transparent().compute_squared_distance(&other.color)? + + SquaredDistance::Value(1.), + ) } else if self.is_numeric() && other.is_currentcolor() { - Ok(self.color.compute_squared_distance(&IntermediateRGBA::transparent())? + 1.) + Ok( + self.color.compute_squared_distance(&IntermediateRGBA::transparent())? + + SquaredDistance::Value(1.), + ) } else { let self_color = self.effective_intermediate_rgba(); let other_color = other.effective_intermediate_rgba(); - let dist = self_color.compute_squared_distance(&other_color)?; - let ratio_diff = (self.foreground_ratio - other.foreground_ratio) as f64; - Ok(dist + ratio_diff * ratio_diff) + Ok( + self_color.compute_squared_distance(&other_color)? + + self.foreground_ratio.compute_squared_distance(&other.foreground_ratio)?, + ) } } } @@ -2978,16 +2705,15 @@ impl Animatable for IntermediateSVGPaint { fallback: self.fallback.add_weighted(&other.fallback, self_portion, other_portion)?, }) } +} +impl ComputeSquaredDistance for IntermediateSVGPaint { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sq| sq.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok(self.kind.compute_squared_distance(&other.kind)? + - self.fallback.compute_squared_distance(&other.fallback)?) + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok( + self.kind.compute_squared_distance(&other.kind)? + + self.fallback.compute_squared_distance(&other.fallback)?, + ) } } @@ -3016,16 +2742,20 @@ impl Animatable for IntermediateSVGPaintKind { _ => Err(()) } } +} +impl ComputeSquaredDistance for IntermediateSVGPaintKind { #[inline] - fn compute_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { - (&SVGPaintKind::Color(ref self_color), &SVGPaintKind::Color(ref other_color)) => { - self_color.compute_distance(other_color) + (&SVGPaintKind::Color(ref this), &SVGPaintKind::Color(ref other)) => { + this.compute_squared_distance(other) } (&SVGPaintKind::None, &SVGPaintKind::None) | (&SVGPaintKind::ContextFill, &SVGPaintKind::ContextFill) | - (&SVGPaintKind::ContextStroke, &SVGPaintKind::ContextStroke)=> Ok(0.0), + (&SVGPaintKind::ContextStroke, &SVGPaintKind::ContextStroke) => { + Ok(SquaredDistance::Value(0.)) + }, _ => Err(()) } } @@ -3060,16 +2790,6 @@ impl Animatable for SVGLength } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&SVGLength::Length(ref this), &SVGLength::Length(ref other)) => { - this.compute_distance(other) - } - _ => Err(()) - } - } } impl ToAnimatedZero for SVGLength where LengthType : ToAnimatedZero { @@ -3097,16 +2817,6 @@ impl Animatable for SVGStrokeDashArray } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => { - this.compute_distance(other) - } - _ => Err(()) - } - } } impl ToAnimatedZero for SVGStrokeDashArray @@ -3138,16 +2848,6 @@ impl Animatable for SVGOpacity } } } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => { - this.compute_distance(other) - } - _ => Err(()) - } - } } impl ToAnimatedZero for SVGOpacity @@ -3246,9 +2946,7 @@ fn add_weighted_filter_function(from: Option<<&AnimatedFilter>, } } -fn compute_filter_square_distance(from: &AnimatedFilter, - to: &AnimatedFilter) - -> Result { +fn compute_filter_square_distance(from: &AnimatedFilter, to: &AnimatedFilter) -> Result { match (from, to) { % for func in FILTER_FUNCTIONS : (&Filter::${func}(f), @@ -3296,29 +2994,24 @@ impl Animatable for AnimatedFilterList { fn add(&self, other: &Self) -> Result { Ok(AnimatedFilterList(self.0.iter().chain(other.0.iter()).cloned().collect())) } +} +impl ComputeSquaredDistance for AnimatedFilterList { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { use itertools::{EitherOrBoth, Itertools}; - let mut square_distance: f64 = 0.0; - for it in self.0.iter().zip_longest(other.0.iter()) { - square_distance += match it { + self.0.iter().zip_longest(other.0.iter()).map(|it| { + match it { EitherOrBoth::Both(from, to) => { - compute_filter_square_distance(&from, &to)? + compute_filter_square_distance(&from, &to) }, EitherOrBoth::Left(list) | EitherOrBoth::Right(list)=> { let none = add_weighted_filter_function(Some(list), Some(list), 0.0, 0.0)?; - compute_filter_square_distance(&none, &list)? + compute_filter_square_distance(&none, &list) }, - }; - } - Ok(square_distance) + } + }).sum() } } @@ -3382,11 +3075,6 @@ impl Animatable for NonNegative fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { self.0.add_weighted(&other.0, self_portion, other_portion).map(NonNegative::) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.0.compute_distance(&other.0) - } } impl ToAnimatedZero for NonNegative @@ -3405,11 +3093,6 @@ impl Animatable for GreaterThanOrEqualToOne fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { self.0.add_weighted(&other.0, self_portion, other_portion).map(GreaterThanOrEqualToOne::) } - - #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.0.compute_distance(&other.0) - } } impl ToAnimatedZero for GreaterThanOrEqualToOne diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 96ba9199bf2..1eae098655e 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -480,6 +480,8 @@ ${helpers.single_keyword_system("font-variant-caps", } pub mod computed_value { + use values::distance::{ComputeSquaredDistance, SquaredDistance}; + /// As of CSS Fonts Module Level 3, only the following values are /// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 /// @@ -489,6 +491,13 @@ ${helpers.single_keyword_system("font-variant-caps", #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] pub struct T(pub u16); + impl ComputeSquaredDistance for T { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + self.0.compute_squared_distance(&other.0) + } + } + impl T { /// Value for normal pub fn normal() -> Self { @@ -1118,6 +1127,7 @@ ${helpers.single_keyword_system("font-variant-caps", use properties::animated_properties::Animatable; use values::CSSFloat; use values::animated::{ToAnimatedValue, ToAnimatedZero}; + use values::distance::{ComputeSquaredDistance, SquaredDistance}; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Copy, Clone, Debug, PartialEq, ToCss)] @@ -1145,12 +1155,13 @@ ${helpers.single_keyword_system("font-variant-caps", _ => Err(()), } } + } + impl ComputeSquaredDistance for T { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (T::Number(ref number), T::Number(ref other)) => - number.compute_distance(other), + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&T::Number(ref this), &T::Number(ref other)) => this.compute_squared_distance(other), _ => Err(()), } } diff --git a/components/style/properties/longhand/inherited_table.mako.rs b/components/style/properties/longhand/inherited_table.mako.rs index 1be9de01bd2..d6aa1369bb3 100644 --- a/components/style/properties/longhand/inherited_table.mako.rs +++ b/components/style/properties/longhand/inherited_table.mako.rs @@ -28,6 +28,7 @@ ${helpers.single_keyword("caption-side", "top bottom", pub mod computed_value { use properties::animated_properties::Animatable; use values::animated::{ToAnimatedValue, ToAnimatedZero}; + use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::computed::NonNegativeAu; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -49,16 +50,15 @@ ${helpers.single_keyword("caption-side", "top bottom", self_portion, other_portion)?, }) } + } + impl ComputeSquaredDistance for T { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok(self.horizontal.compute_squared_distance(&other.horizontal)? + - self.vertical.compute_squared_distance(&other.vertical)?) + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok( + self.horizontal.compute_squared_distance(&other.horizontal)? + + self.vertical.compute_squared_distance(&other.vertical)?, + ) } } diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index 9bd3456d028..5c4a02b519a 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -14,6 +14,7 @@ use values::Impossible; use values::animated::{ToAnimatedValue, ToAnimatedZero}; use values::computed::{Angle, NonNegativeNumber}; use values::computed::length::{Length, NonNegativeLength}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::Filter as GenericFilter; use values::generics::effects::SimpleShadow as GenericSimpleShadow; @@ -102,6 +103,14 @@ where } } +impl ComputeSquaredDistance for ShadowList { + #[inline] + fn compute_squared_distance(&self, _other: &Self) -> Result { + // FIXME: This should be implemented. + Err(()) + } +} + impl ToAnimatedZero for ShadowList { #[inline] fn to_animated_zero(&self) -> Result { @@ -140,14 +149,11 @@ impl Animatable for BoxShadow { inset: self.inset, }) } +} +impl ComputeSquaredDistance for BoxShadow { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { if self.inset != other.inset { return Err(()); } @@ -219,14 +225,11 @@ impl Animatable for SimpleShadow { blur: blur, }) } +} +impl ComputeSquaredDistance for SimpleShadow { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { Ok( self.color.compute_squared_distance(&other.color)? + self.horizontal.compute_squared_distance(&other.horizontal)? + diff --git a/components/style/values/computed/background.rs b/components/style/values/computed/background.rs index d2781ac1891..9bfb77c1523 100644 --- a/components/style/values/computed/background.rs +++ b/components/style/values/computed/background.rs @@ -8,6 +8,7 @@ use properties::animated_properties::{Animatable, RepeatableListAnimatable}; use properties::longhands::background_size::computed_value::T as BackgroundSizeList; use values::animated::{ToAnimatedValue, ToAnimatedZero}; use values::computed::length::LengthOrPercentageOrAuto; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::background::BackgroundSize as GenericBackgroundSize; /// A computed value for the `background-size` property. @@ -30,14 +31,11 @@ impl Animatable for BackgroundSize { _ => Err(()), } } +} +impl ComputeSquaredDistance for BackgroundSize { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(|sd| sd.sqrt()) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { ( &GenericBackgroundSize::Explicit { width: self_width, height: self_height }, diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index ed4a38255d3..fbe3b56e724 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -12,6 +12,7 @@ use style_traits::values::specified::AllowedLengthType; use super::{Number, ToComputedValue, Context, Percentage}; use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal, specified}; use values::computed::{NonNegativeAu, NonNegativeNumber}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::NonNegative; use values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; use values::specified::length::ViewportPercentageLength; @@ -71,6 +72,18 @@ pub struct CalcLengthOrPercentage { pub percentage: Option, } +impl ComputeSquaredDistance for CalcLengthOrPercentage { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + // FIXME(nox): This looks incorrect to me, to add a distance between lengths + // with a distance between percentages. + Ok( + self.unclamped_length().compute_squared_distance(&other.unclamped_length())? + + self.percentage().compute_squared_distance(&other.percentage())?, + ) + } +} + impl CalcLengthOrPercentage { /// Returns a new `CalcLengthOrPercentage`. #[inline] @@ -257,6 +270,23 @@ pub enum LengthOrPercentage { Calc(CalcLengthOrPercentage), } +impl ComputeSquaredDistance for LengthOrPercentage { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&LengthOrPercentage::Length(ref this), &LengthOrPercentage::Length(ref other)) => { + this.compute_squared_distance(other) + }, + (&LengthOrPercentage::Percentage(ref this), &LengthOrPercentage::Percentage(ref other)) => { + this.compute_squared_distance(other) + }, + (this, other) => { + CalcLengthOrPercentage::compute_squared_distance(&(*this).into(), &(*other).into()) + } + } + } +} + impl From for LengthOrPercentage { #[inline] fn from(length: Au) -> Self { @@ -382,6 +412,23 @@ pub enum LengthOrPercentageOrAuto { Calc(CalcLengthOrPercentage), } +impl ComputeSquaredDistance for LengthOrPercentageOrAuto { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&LengthOrPercentageOrAuto::Length(ref this), &LengthOrPercentageOrAuto::Length(ref other)) => { + this.compute_squared_distance(other) + }, + (&LengthOrPercentageOrAuto::Percentage(ref this), &LengthOrPercentageOrAuto::Percentage(ref other)) => { + this.compute_squared_distance(other) + }, + (this, other) => { + >::compute_squared_distance(&(*this).into(), &(*other).into()) + } + } + } +} + impl LengthOrPercentageOrAuto { /// Returns true if the computed value is absolute 0 or 0%. /// @@ -460,6 +507,23 @@ pub enum LengthOrPercentageOrNone { None, } +impl ComputeSquaredDistance for LengthOrPercentageOrNone { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&LengthOrPercentageOrNone::Length(ref this), &LengthOrPercentageOrNone::Length(ref other)) => { + this.compute_squared_distance(other) + }, + (&LengthOrPercentageOrNone::Percentage(ref this), &LengthOrPercentageOrNone::Percentage(ref other)) => { + this.compute_squared_distance(other) + }, + (this, other) => { + >::compute_squared_distance(&(*this).into(), &(*other).into()) + } + } + } +} + impl LengthOrPercentageOrNone { /// Returns the used value. pub fn to_used_value(&self, containing_length: Au) -> Option { @@ -607,6 +671,22 @@ pub enum MozLength { ExtremumLength(ExtremumLength), } +impl ComputeSquaredDistance for MozLength { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&MozLength::LengthOrPercentageOrAuto(ref this), &MozLength::LengthOrPercentageOrAuto(ref other)) => { + this.compute_squared_distance(other) + }, + _ => { + // FIXME(nox): Should this return `Ok(SquaredDistance::Value(1.))` + // when `self` and `other` are the same extremum value? + Err(()) + }, + } + } +} + impl MozLength { /// Returns the `auto` value. pub fn auto() -> Self { @@ -651,6 +731,22 @@ pub enum MaxLength { ExtremumLength(ExtremumLength), } +impl ComputeSquaredDistance for MaxLength { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&MaxLength::LengthOrPercentageOrNone(ref this), &MaxLength::LengthOrPercentageOrNone(ref other)) => { + this.compute_squared_distance(other) + }, + _ => { + // FIXME(nox): Should this return `Ok(SquaredDistance::Value(1.))` + // when `self` and `other` are the same extremum value? + Err(()) + }, + } + } +} + impl MaxLength { /// Returns the `none` value. pub fn none() -> Self { diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 75b9e3bb354..42f37b4ab22 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -22,6 +22,7 @@ use std::fmt; use std::sync::Arc; use style_traits::ToCss; use super::{CSSFloat, CSSInteger}; +use super::distance::{ComputeSquaredDistance, SquaredDistance}; use super::generics::{GreaterThanOrEqualToOne, NonNegative}; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; @@ -338,6 +339,15 @@ pub enum Angle { Turn(CSSFloat), } +impl ComputeSquaredDistance for Angle { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + // Use the formula for calculating the distance between angles defined in SVG: + // https://www.w3.org/TR/SVG/animate.html#complexDistances + self.radians64().compute_squared_distance(&other.radians64()) + } +} + impl Angle { /// Construct a computed `Angle` value from a radian amount. pub fn from_radians(radians: CSSFloat) -> Self { @@ -544,6 +554,18 @@ pub struct ClipRect { pub left: Option, } +impl ComputeSquaredDistance for ClipRect { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok( + self.top.compute_squared_distance(&other.top)? + + self.right.compute_squared_distance(&other.right)? + + self.bottom.compute_squared_distance(&other.bottom)? + + self.left.compute_squared_distance(&other.left)?, + ) + } +} + impl ToCss for ClipRect { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { dest.write_str("rect(")?; @@ -653,6 +675,13 @@ impl From for NonNegativeAu { #[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] pub struct Percentage(pub CSSFloat); +impl ComputeSquaredDistance for Percentage { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + self.0.compute_squared_distance(&other.0) + } +} + impl Percentage { /// 0% #[inline] diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 7376616ba5e..7db57907391 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -9,6 +9,7 @@ use values::{CSSInteger, CSSFloat}; use values::animated::ToAnimatedZero; use values::computed::{NonNegativeAu, NonNegativeNumber}; use values::computed::length::{Length, LengthOrPercentage}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::text::InitialLetter as GenericInitialLetter; use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::Spacing; @@ -45,19 +46,25 @@ impl Animatable for LineHeight { _ => Err(()), } } +} +impl ComputeSquaredDistance for LineHeight { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - match (*self, *other) { - (GenericLineHeight::Length(ref this), GenericLineHeight::Length(ref other)) => { - this.compute_distance(other) + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&GenericLineHeight::Length(ref this), &GenericLineHeight::Length(ref other)) => { + this.compute_squared_distance(other) }, - (GenericLineHeight::Number(ref this), GenericLineHeight::Number(ref other)) => { - this.compute_distance(other) + (&GenericLineHeight::Number(ref this), &GenericLineHeight::Number(ref other)) => { + this.compute_squared_distance(other) + }, + (&GenericLineHeight::Normal, &GenericLineHeight::Normal) => { + Ok(SquaredDistance::Value(0.)) }, - (GenericLineHeight::Normal, GenericLineHeight::Normal) => Ok(0.), #[cfg(feature = "gecko")] - (GenericLineHeight::MozBlockHeight, GenericLineHeight::MozBlockHeight) => Ok(0.), + (&GenericLineHeight::MozBlockHeight, &GenericLineHeight::MozBlockHeight) => { + Ok(SquaredDistance::Value(0.)) + }, _ => Err(()), } } diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 5bf953d46be..c57bef639df 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -7,6 +7,7 @@ use properties::animated_properties::Animatable; use values::animated::ToAnimatedZero; use values::computed::{Length, LengthOrPercentage, Number, Percentage}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::transform::TimingFunction as GenericTimingFunction; use values::generics::transform::TransformOrigin as GenericTransformOrigin; @@ -37,14 +38,11 @@ impl Animatable for TransformOrigin { self.depth.add_weighted(&other.depth, self_portion, other_portion)?, )) } +} +impl ComputeSquaredDistance for TransformOrigin { #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.compute_squared_distance(other).map(f64::sqrt) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { Ok( self.horizontal.compute_squared_distance(&other.horizontal)? + self.vertical.compute_squared_distance(&other.vertical)? + diff --git a/components/style/values/distance.rs b/components/style/values/distance.rs new file mode 100644 index 00000000000..d4eb91f112f --- /dev/null +++ b/components/style/values/distance.rs @@ -0,0 +1,124 @@ +/* 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/. */ + +//! Machinery to compute distances between animatable values. + +use app_units::Au; +use euclid::Size2D; +use std::iter::Sum; +use std::ops::Add; + +/// A trait to compute squared distances between two animatable values. +pub trait ComputeSquaredDistance { + /// Computes the squared distance between two animatable values. + fn compute_squared_distance(&self, other: &Self) -> Result; +} + +/// A distance between two animatable values. +#[derive(Clone, Copy, Debug)] +pub enum SquaredDistance { + /// Represented as the square root of the squared distance. + Sqrt(f64), + /// Represented as the squared distance itself. + Value(f64), +} + +impl ComputeSquaredDistance for u16 { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok(SquaredDistance::Sqrt(((*self as f64) - (*other as f64)).abs())) + } +} + +impl ComputeSquaredDistance for i32 { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok(SquaredDistance::Sqrt((*self - *other).abs() as f64)) + } +} + +impl ComputeSquaredDistance for f32 { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok(SquaredDistance::Sqrt((*self - *other).abs() as f64)) + } +} + +impl ComputeSquaredDistance for f64 { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok(SquaredDistance::Sqrt((*self - *other).abs())) + } +} + +impl ComputeSquaredDistance for Au { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + self.0.compute_squared_distance(&other.0) + } +} + +impl ComputeSquaredDistance for Option + where T: ComputeSquaredDistance +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self.as_ref(), other.as_ref()) { + (Some(this), Some(other)) => this.compute_squared_distance(other), + (None, None) => Ok(SquaredDistance::Value(0.)), + _ => Err(()), + } + } +} + +impl ComputeSquaredDistance for Size2D + where T: ComputeSquaredDistance +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok(self.width.compute_squared_distance(&other.width)? + self.height.compute_squared_distance(&other.height)?) + } +} + +impl SquaredDistance { + /// Returns the square root of this squared distance. + pub fn sqrt(self) -> f64 { + match self { + SquaredDistance::Sqrt(this) => this, + SquaredDistance::Value(this) => this.sqrt(), + } + } +} + +impl From for f64 { + #[inline] + fn from(distance: SquaredDistance) -> Self { + match distance { + SquaredDistance::Sqrt(this) => this * this, + SquaredDistance::Value(this) => this, + } + } +} + +impl Add for SquaredDistance { + type Output = Self; + + #[inline] + fn add(self, rhs: Self) -> Self { + SquaredDistance::Value(f64::from(self) + f64::from(rhs)) + } +} + +impl Sum for SquaredDistance { + fn sum(mut iter: I) -> Self + where + I: Iterator, + { + let first = match iter.next() { + Some(first) => first, + None => return SquaredDistance::Value(0.), + }; + iter.fold(first, Add::add) + } +} diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index f218fd41ba8..cf1437ce8d0 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -10,6 +10,7 @@ use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; use values::animated::ToAnimatedZero; use values::computed::ComputedValueAsSpecified; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::border::BorderRadius; use values::generics::position::Position; use values::generics::rect::Rect; @@ -144,20 +145,16 @@ where _ => Err(()), } } +} - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - ( - &ShapeSource::Shape(ref this, ref this_box), - &ShapeSource::Shape(ref other, ref other_box), - ) if this_box == other_box => { - this.compute_distance(other) - }, - _ => Err(()), - } - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +// FIXME(nox): Implement ComputeSquaredDistance for T types and stop +// using PartialEq here. +impl ComputeSquaredDistance for ShapeSource +where + B: ComputeSquaredDistance, + T: PartialEq, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { ( &ShapeSource::Shape(ref this, ref this_box), @@ -209,26 +206,15 @@ where _ => Err(()), } } +} - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&BasicShape::Circle(ref this), &BasicShape::Circle(ref other)) => { - this.compute_distance(other) - }, - (&BasicShape::Ellipse(ref this), &BasicShape::Ellipse(ref other)) => { - this.compute_distance(other) - }, - (&BasicShape::Inset(ref this), &BasicShape::Inset(ref other)) => { - this.compute_distance(other) - }, - (&BasicShape::Polygon(ref this), &BasicShape::Polygon(ref other)) => { - this.compute_distance(other) - }, - _ => Err(()), - } - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for BasicShape +where + H: ComputeSquaredDistance, + V: ComputeSquaredDistance, + L: ComputeSquaredDistance + Copy, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { (&BasicShape::Circle(ref this), &BasicShape::Circle(ref other)) => { this.compute_squared_distance(other) @@ -261,12 +247,13 @@ where let round = self.round.add_weighted(&other.round, self_portion, other_portion)?; Ok(InsetRect { rect, round }) } +} - fn compute_distance(&self, other: &Self) -> Result { - Ok(self.compute_squared_distance(other)?.sqrt()) - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for InsetRect +where + L: ComputeSquaredDistance + Copy, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { Ok( self.rect.compute_squared_distance(&other.rect)? + self.round.compute_squared_distance(&other.round)?, @@ -304,12 +291,15 @@ where let radius = self.radius.add_weighted(&other.radius, self_portion, other_portion)?; Ok(Circle { position, radius }) } +} - fn compute_distance(&self, other: &Self) -> Result { - Ok(self.compute_squared_distance(other)?.sqrt()) - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for Circle +where + H: ComputeSquaredDistance, + V: ComputeSquaredDistance, + L: ComputeSquaredDistance, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { Ok( self.position.compute_squared_distance(&other.position)? + self.radius.compute_squared_distance(&other.radius)?, @@ -334,12 +324,15 @@ where let semiaxis_y = self.semiaxis_y.add_weighted(&other.semiaxis_y, self_portion, other_portion)?; Ok(Ellipse { position, semiaxis_x, semiaxis_y }) } +} - fn compute_distance(&self, other: &Self) -> Result { - Ok(self.compute_squared_distance(other)?.sqrt()) - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for Ellipse +where + H: ComputeSquaredDistance, + V: ComputeSquaredDistance, + L: ComputeSquaredDistance, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { Ok( self.position.compute_squared_distance(&other.position)? + self.semiaxis_x.compute_squared_distance(&other.semiaxis_x)? + @@ -365,17 +358,13 @@ where _ => Err(()), } } +} - fn compute_distance(&self, other: &Self) -> Result { - match (self, other) { - (&ShapeRadius::Length(ref this), &ShapeRadius::Length(ref other)) => { - this.compute_distance(other) - }, - _ => Err(()), - } - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for ShapeRadius +where + L: ComputeSquaredDistance, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { match (self, other) { (&ShapeRadius::Length(ref this), &ShapeRadius::Length(ref other)) => { this.compute_squared_distance(other) @@ -413,12 +402,13 @@ where }).collect::, _>>()?; Ok(Polygon { fill: self.fill, coordinates }) } +} - fn compute_distance(&self, other: &Self) -> Result { - Ok(self.compute_squared_distance(other)?.sqrt()) - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for Polygon +where + L: ComputeSquaredDistance, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { if self.fill != other.fill { return Err(()); } @@ -426,9 +416,10 @@ where return Err(()); } self.coordinates.iter().zip(other.coordinates.iter()).map(|(this, other)| { - let x = this.0.compute_squared_distance(&other.0)?; - let y = this.1.compute_squared_distance(&other.1)?; - Ok(x + y) + Ok( + this.0.compute_squared_distance(&other.0)? + + this.1.compute_squared_distance(&other.1)?, + ) }).sum() } } diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index e70504e7e87..9b66ce23dc2 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -8,6 +8,7 @@ use euclid::Size2D; use properties::animated_properties::Animatable; use std::fmt; use style_traits::ToCss; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::rect::Rect; /// A generic value for a single side of a `border-image-width` property. @@ -129,12 +130,13 @@ where let bl = self.bottom_left.add_weighted(&other.bottom_left, self_portion, other_portion)?; Ok(BorderRadius::new(tl, tr, br, bl)) } +} - fn compute_distance(&self, other: &Self) -> Result { - Ok(self.compute_squared_distance(other)?.sqrt()) - } - - fn compute_squared_distance(&self, other: &Self) -> Result { +impl ComputeSquaredDistance for BorderRadius +where + L: ComputeSquaredDistance + Copy, +{ + fn compute_squared_distance(&self, other: &Self) -> Result { Ok( self.top_left.compute_squared_distance(&other.top_left)? + self.top_right.compute_squared_distance(&other.top_right)? + @@ -189,14 +191,14 @@ where ) -> Result { Ok(BorderCornerRadius(self.0.add_weighted(&other.0, self_portion, other_portion)?)) } +} +impl ComputeSquaredDistance for BorderCornerRadius +where + L: ComputeSquaredDistance + Copy, +{ #[inline] - fn compute_distance(&self, other: &Self) -> Result { - self.0.compute_distance(&other.0) - } - - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { + fn compute_squared_distance(&self, other: &Self) -> Result { self.0.compute_squared_distance(&other.0) } } diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 075ce2c4715..689dd95f1d1 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -11,6 +11,7 @@ use parser::{Parse, ParserContext}; use std::fmt; use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss}; use super::CustomIdent; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; pub mod background; pub mod basic_shape; @@ -271,7 +272,27 @@ impl ToCss for FontSettingTagFloat { #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] pub struct NonNegative(pub T); +impl ComputeSquaredDistance for NonNegative +where + T: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + self.0.compute_squared_distance(&other.0) + } +} + /// A wrapper of greater-than-or-equal-to-one values. #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] pub struct GreaterThanOrEqualToOne(pub T); + +impl ComputeSquaredDistance for GreaterThanOrEqualToOne +where + T: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + self.0.compute_squared_distance(&other.0) + } +} diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs index 4ce5b63ab30..0c641a62daa 100644 --- a/components/style/values/generics/position.rs +++ b/components/style/values/generics/position.rs @@ -5,6 +5,8 @@ //! Generic types for CSS handling of specified and computed values of //! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position) +use values::distance::{ComputeSquaredDistance, SquaredDistance}; + #[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). @@ -24,3 +26,17 @@ impl Position { } } } + +impl ComputeSquaredDistance for Position +where + H: ComputeSquaredDistance, + V: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok( + self.horizontal.compute_squared_distance(&other.horizontal)? + + self.vertical.compute_squared_distance(&other.vertical)?, + ) + } +} diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index 3dc9e095890..b948cf88f82 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -9,6 +9,7 @@ use parser::{Parse, ParserContext}; use properties::animated_properties::Animatable; use std::fmt; use style_traits::{ToCss, ParseError}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A CSS value made of four components, where its `ToCss` impl will try to /// serialize as few components as possible, like for example in `border-width`. @@ -70,6 +71,21 @@ where } } +impl ComputeSquaredDistance for Rect +where + L: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + Ok( + self.0.compute_squared_distance(&other.0)? + + self.1.compute_squared_distance(&other.1)? + + self.2.compute_squared_distance(&other.2)? + + self.3.compute_squared_distance(&other.3)?, + ) + } +} + impl From for Rect where T: Clone { diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 05e0e66248f..079bce1f1c1 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -6,8 +6,10 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; +use properties::animated_properties::RepeatableListAnimatable; use std::fmt; use style_traits::{ParseError, StyleParseError, ToCss}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// An SVG paint value /// @@ -105,6 +107,25 @@ pub enum SVGLength { ContextValue, } +impl ComputeSquaredDistance for SVGLength +where + L: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&SVGLength::Length(ref this), &SVGLength::Length(ref other)) => { + this.compute_squared_distance(other) + }, + _ => { + // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` + // if `self` and `other` are the same keyword value? + Err(()) + }, + } + } +} + /// Generic value for stroke-dasharray. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq, HasViewportPercentage, ToAnimatedValue, ToComputedValue)] @@ -115,6 +136,25 @@ pub enum SVGStrokeDashArray { ContextValue, } +impl ComputeSquaredDistance for SVGStrokeDashArray +where + L: ComputeSquaredDistance + RepeatableListAnimatable, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => { + this.compute_squared_distance(other) + }, + _ => { + // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` + // if `self` and `other` are the same keyword value? + Err(()) + }, + } + } +} + impl ToCss for SVGStrokeDashArray where LengthType: ToCss { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match self { @@ -150,3 +190,22 @@ pub enum SVGOpacity { /// `context-stroke-opacity` ContextStrokeOpacity, } + +impl ComputeSquaredDistance for SVGOpacity +where + L: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => { + this.compute_squared_distance(other) + } + _ => { + // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` + // if `self` and `other` are the same keyword value? + Err(()) + }, + } + } +} diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index 94be4a6db8c..3330d0dbceb 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -10,6 +10,7 @@ use parser::ParserContext; use properties::animated_properties::Animatable; use style_traits::ParseError; use values::animated::ToAnimatedZero; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A generic value for the `initial-letter` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -84,13 +85,18 @@ impl Animatable for Spacing let other = other.value().unwrap_or(&zero); this.add_weighted(other, self_portion, other_portion).map(Spacing::Value) } +} +impl ComputeSquaredDistance for Spacing +where + V: ComputeSquaredDistance + From, +{ #[inline] - fn compute_distance(&self, other: &Self) -> Result { - let zero = Value::from(Au(0)); + fn compute_squared_distance(&self, other: &Self) -> Result { + let zero = V::from(Au(0)); let this = self.value().unwrap_or(&zero); let other = other.value().unwrap_or(&zero); - this.compute_distance(other) + this.compute_squared_distance(other) } } diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 616aa5cb485..4a2c20b3b18 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -16,9 +16,11 @@ use std::ascii::AsciiExt; use std::fmt::{self, Debug}; use std::hash; use style_traits::{ToCss, ParseError, StyleParseError}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; pub mod animated; pub mod computed; +pub mod distance; pub mod generics; pub mod specified; @@ -59,6 +61,25 @@ pub enum Either { Second(B), } +impl ComputeSquaredDistance for Either +where + A: ComputeSquaredDistance, + B: ComputeSquaredDistance, +{ + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&Either::First(ref this), &Either::First(ref other)) => { + this.compute_squared_distance(other) + }, + (&Either::Second(ref this), &Either::Second(ref other)) => { + this.compute_squared_distance(other) + }, + _ => Err(()) + } + } +} + impl Debug for Either { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index d20fce6fb13..821c73d6942 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -126,6 +126,7 @@ use style::traversal_flags::{TraversalFlags, self}; use style::values::{CustomIdent, KeyframesName}; use style::values::animated::ToAnimatedZero; use style::values::computed::Context; +use style::values::distance::ComputeSquaredDistance; use style_traits::{PARSING_MODE_DEFAULT, ToCss}; use super::error_reporter::ErrorReporter; use super::stylesheet_loader::StylesheetLoader; @@ -375,7 +376,7 @@ pub extern "C" fn Servo_AnimationValues_ComputeDistance(from: RawServoAnimationV -> f64 { let from_value = AnimationValue::as_arc(&from); let to_value = AnimationValue::as_arc(&to); - from_value.compute_distance(to_value).unwrap_or(0.0) + from_value.compute_squared_distance(to_value).map(|d| d.sqrt()).unwrap_or(0.0) } #[no_mangle] From 277351da3589ba6497635f12dc9793d032e469e1 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 13 Aug 2017 00:50:36 +0200 Subject: [PATCH 3/3] Derive ComputeSquaredDistance --- components/style/macros.rs | 12 +- components/style/properties/helpers.mako.rs | 13 +- .../style/properties/longhand/font.mako.rs | 11 +- .../longhand/inherited_table.mako.rs | 13 +- components/style/values/animated/effects.rs | 12 -- .../style/values/computed/background.rs | 19 --- components/style/values/computed/mod.rs | 25 +--- components/style/values/computed/text.rs | 23 ---- components/style/values/computed/transform.rs | 12 -- .../style/values/generics/background.rs | 2 +- .../style/values/generics/basic_shape.rs | 92 +------------- components/style/values/generics/border.rs | 31 +---- components/style/values/generics/effects.rs | 2 +- components/style/values/generics/mod.rs | 31 +---- components/style/values/generics/position.rs | 20 +-- components/style/values/generics/rect.rs | 18 +-- components/style/values/generics/svg.rs | 66 +--------- components/style/values/generics/text.rs | 2 +- components/style/values/generics/transform.rs | 2 +- components/style/values/mod.rs | 23 +--- .../style_derive/compute_squared_distance.rs | 117 ++++++++++++++++++ components/style_derive/lib.rs | 7 ++ 22 files changed, 162 insertions(+), 391 deletions(-) create mode 100644 components/style_derive/compute_squared_distance.rs diff --git a/components/style/macros.rs b/components/style/macros.rs index 3251b7e2d37..8af642f80da 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -84,7 +84,7 @@ macro_rules! define_keyword_type { ($name: ident, $css: expr) => { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - #[derive(Clone, Copy, PartialEq, ToCss)] + #[derive(Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)] pub struct $name; impl $crate::properties::animated_properties::Animatable for $name { @@ -117,15 +117,5 @@ macro_rules! define_keyword_type { #[inline] fn to_animated_zero(&self) -> Result { Ok($name) } } - - impl $crate::values::distance::ComputeSquaredDistance for $name { - #[inline] - fn compute_squared_distance( - &self, - _other: &Self - ) -> Result<$crate::values::distance::SquaredDistance, ()> { - Ok($crate::values::distance::SquaredDistance::Value(0.)) - } - } }; } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index d428cc20cdb..e82ee073c87 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -119,8 +119,11 @@ use values::computed::ComputedVecIter; /// The computed value, effectively a list of single values. - #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + #[derive(Clone, Debug, PartialEq)] + % if need_animatable or animation_value_type == "ComputedValue": + #[derive(ComputeSquaredDistance)] + % endif pub struct T( % if allow_empty and allow_empty != "NotInitial": pub Vec, @@ -132,7 +135,6 @@ % if need_animatable or animation_value_type == "ComputedValue": use properties::animated_properties::Animatable; use values::animated::ToAnimatedZero; - use values::distance::{ComputeSquaredDistance, SquaredDistance}; impl Animatable for T { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) @@ -145,13 +147,6 @@ } } - impl ComputeSquaredDistance for T { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - self.0.compute_squared_distance(&other.0) - } - } - impl ToAnimatedZero for T { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 1eae098655e..0ebcf2db9a7 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -480,24 +480,15 @@ ${helpers.single_keyword_system("font-variant-caps", } pub mod computed_value { - use values::distance::{ComputeSquaredDistance, SquaredDistance}; - /// As of CSS Fonts Module Level 3, only the following values are /// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 /// /// However, system fonts may provide other values. Pango /// may provide 350, 380, and 1000 (on top of the existing values), for example. - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, ToCss)] + #[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, Eq, Hash, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] pub struct T(pub u16); - impl ComputeSquaredDistance for T { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - self.0.compute_squared_distance(&other.0) - } - } - impl T { /// Value for normal pub fn normal() -> Self { diff --git a/components/style/properties/longhand/inherited_table.mako.rs b/components/style/properties/longhand/inherited_table.mako.rs index d6aa1369bb3..1d646cc9410 100644 --- a/components/style/properties/longhand/inherited_table.mako.rs +++ b/components/style/properties/longhand/inherited_table.mako.rs @@ -28,11 +28,10 @@ ${helpers.single_keyword("caption-side", "top bottom", pub mod computed_value { use properties::animated_properties::Animatable; use values::animated::{ToAnimatedValue, ToAnimatedZero}; - use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::computed::NonNegativeAu; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - #[derive(Clone, Copy, Debug, PartialEq, ToCss)] + #[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToCss)] pub struct T { pub horizontal: NonNegativeAu, pub vertical: NonNegativeAu, @@ -52,16 +51,6 @@ ${helpers.single_keyword("caption-side", "top bottom", } } - impl ComputeSquaredDistance for T { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.horizontal.compute_squared_distance(&other.horizontal)? + - self.vertical.compute_squared_distance(&other.vertical)?, - ) - } - } - impl ToAnimatedZero for T { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index 5c4a02b519a..37cf926a1d7 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -227,18 +227,6 @@ impl Animatable for SimpleShadow { } } -impl ComputeSquaredDistance for SimpleShadow { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.color.compute_squared_distance(&other.color)? + - self.horizontal.compute_squared_distance(&other.horizontal)? + - self.vertical.compute_squared_distance(&other.vertical)? + - self.blur.compute_squared_distance(&other.blur)? - ) - } -} - impl ToAnimatedZero for SimpleShadow { #[inline] fn to_animated_zero(&self) -> Result { diff --git a/components/style/values/computed/background.rs b/components/style/values/computed/background.rs index 9bfb77c1523..a2111a046e4 100644 --- a/components/style/values/computed/background.rs +++ b/components/style/values/computed/background.rs @@ -8,7 +8,6 @@ use properties::animated_properties::{Animatable, RepeatableListAnimatable}; use properties::longhands::background_size::computed_value::T as BackgroundSizeList; use values::animated::{ToAnimatedValue, ToAnimatedZero}; use values::computed::length::LengthOrPercentageOrAuto; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::background::BackgroundSize as GenericBackgroundSize; /// A computed value for the `background-size` property. @@ -33,24 +32,6 @@ impl Animatable for BackgroundSize { } } -impl ComputeSquaredDistance for BackgroundSize { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - ( - &GenericBackgroundSize::Explicit { width: self_width, height: self_height }, - &GenericBackgroundSize::Explicit { width: other_width, height: other_height }, - ) => { - Ok( - self_width.compute_squared_distance(&other_width)? + - self_height.compute_squared_distance(&other_height)? - ) - } - _ => Err(()), - } - } -} - impl ToAnimatedZero for BackgroundSize { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 42f37b4ab22..b963d37fab6 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -543,9 +543,9 @@ pub type LengthOrPercentageOrNumber = Either; /// NonNegativeLengthOrPercentage | NonNegativeNumber pub type NonNegativeLengthOrPercentageOrNumber = Either; -#[derive(Clone, PartialEq, Eq, Copy, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, Eq, PartialEq)] /// A computed cliprect for clip and image-region pub struct ClipRect { pub top: Option, @@ -554,18 +554,6 @@ pub struct ClipRect { pub left: Option, } -impl ComputeSquaredDistance for ClipRect { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.top.compute_squared_distance(&other.top)? + - self.right.compute_squared_distance(&other.right)? + - self.bottom.compute_squared_distance(&other.bottom)? + - self.left.compute_squared_distance(&other.left)?, - ) - } -} - impl ToCss for ClipRect { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { dest.write_str("rect(")?; @@ -671,17 +659,10 @@ impl From for NonNegativeAu { } /// A computed `` value. -#[derive(Clone, Copy, Debug, Default, PartialEq, HasViewportPercentage)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, Default, HasViewportPercentage, PartialEq)] #[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] pub struct Percentage(pub CSSFloat); -impl ComputeSquaredDistance for Percentage { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - self.0.compute_squared_distance(&other.0) - } -} - impl Percentage { /// 0% #[inline] diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 7db57907391..fd39b4dd647 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -9,7 +9,6 @@ use values::{CSSInteger, CSSFloat}; use values::animated::ToAnimatedZero; use values::computed::{NonNegativeAu, NonNegativeNumber}; use values::computed::length::{Length, LengthOrPercentage}; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::text::InitialLetter as GenericInitialLetter; use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::Spacing; @@ -48,28 +47,6 @@ impl Animatable for LineHeight { } } -impl ComputeSquaredDistance for LineHeight { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&GenericLineHeight::Length(ref this), &GenericLineHeight::Length(ref other)) => { - this.compute_squared_distance(other) - }, - (&GenericLineHeight::Number(ref this), &GenericLineHeight::Number(ref other)) => { - this.compute_squared_distance(other) - }, - (&GenericLineHeight::Normal, &GenericLineHeight::Normal) => { - Ok(SquaredDistance::Value(0.)) - }, - #[cfg(feature = "gecko")] - (&GenericLineHeight::MozBlockHeight, &GenericLineHeight::MozBlockHeight) => { - Ok(SquaredDistance::Value(0.)) - }, - _ => Err(()), - } - } -} - impl ToAnimatedZero for LineHeight { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index c57bef639df..70c543b9a7f 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -7,7 +7,6 @@ use properties::animated_properties::Animatable; use values::animated::ToAnimatedZero; use values::computed::{Length, LengthOrPercentage, Number, Percentage}; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::transform::TimingFunction as GenericTimingFunction; use values::generics::transform::TransformOrigin as GenericTransformOrigin; @@ -40,17 +39,6 @@ impl Animatable for TransformOrigin { } } -impl ComputeSquaredDistance for TransformOrigin { - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.horizontal.compute_squared_distance(&other.horizontal)? + - self.vertical.compute_squared_distance(&other.vertical)? + - self.depth.compute_squared_distance(&other.depth)? - ) - } -} - impl ToAnimatedZero for TransformOrigin { #[inline] fn to_animated_zero(&self) -> Result { diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs index aa24454ef6d..8a79691f3b9 100644 --- a/components/style/values/generics/background.rs +++ b/components/style/values/generics/background.rs @@ -5,7 +5,7 @@ //! Generic types for CSS values related to backgrounds. /// A generic value for the `background-size` property. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum BackgroundSize { /// ` ` diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index cf1437ce8d0..cad038df0f1 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -55,7 +55,7 @@ pub enum ShapeSource { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq, ToComputedValue, ToCss)] pub enum BasicShape { Inset(InsetRect), Circle(Circle), @@ -66,7 +66,7 @@ pub enum BasicShape { /// https://drafts.csswg.org/css-shapes/#funcdef-inset #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Debug, PartialEq, ToComputedValue)] +#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq, ToComputedValue)] pub struct InsetRect { pub rect: Rect, pub round: Option>, @@ -75,7 +75,7 @@ pub struct InsetRect { /// https://drafts.csswg.org/css-shapes/#funcdef-circle #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue)] pub struct Circle { pub position: Position, pub radius: ShapeRadius, @@ -84,7 +84,7 @@ pub struct Circle { /// https://drafts.csswg.org/css-shapes/#funcdef-ellipse #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue)] pub struct Ellipse { pub position: Position, pub semiaxis_x: ShapeRadius, @@ -94,7 +94,7 @@ pub struct Ellipse { /// https://drafts.csswg.org/css-shapes/#typedef-shape-radius #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue, ToCss)] pub enum ShapeRadius { Length(LengthOrPercentage), ClosestSide, @@ -148,7 +148,7 @@ where } // FIXME(nox): Implement ComputeSquaredDistance for T types and stop -// using PartialEq here. +// using PartialEq here, this will let us derive this impl. impl ComputeSquaredDistance for ShapeSource where B: ComputeSquaredDistance, @@ -208,31 +208,6 @@ where } } -impl ComputeSquaredDistance for BasicShape -where - H: ComputeSquaredDistance, - V: ComputeSquaredDistance, - L: ComputeSquaredDistance + Copy, -{ - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&BasicShape::Circle(ref this), &BasicShape::Circle(ref other)) => { - this.compute_squared_distance(other) - }, - (&BasicShape::Ellipse(ref this), &BasicShape::Ellipse(ref other)) => { - this.compute_squared_distance(other) - }, - (&BasicShape::Inset(ref this), &BasicShape::Inset(ref other)) => { - this.compute_squared_distance(other) - }, - (&BasicShape::Polygon(ref this), &BasicShape::Polygon(ref other)) => { - this.compute_squared_distance(other) - }, - _ => Err(()), - } - } -} - impl Animatable for InsetRect where L: Animatable + Copy, @@ -249,18 +224,6 @@ where } } -impl ComputeSquaredDistance for InsetRect -where - L: ComputeSquaredDistance + Copy, -{ - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.rect.compute_squared_distance(&other.rect)? + - self.round.compute_squared_distance(&other.round)?, - ) - } -} - impl ToCss for InsetRect where L: ToCss + PartialEq { @@ -293,20 +256,6 @@ where } } -impl ComputeSquaredDistance for Circle -where - H: ComputeSquaredDistance, - V: ComputeSquaredDistance, - L: ComputeSquaredDistance, -{ - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.position.compute_squared_distance(&other.position)? + - self.radius.compute_squared_distance(&other.radius)?, - ) - } -} - impl Animatable for Ellipse where H: Animatable, @@ -326,21 +275,6 @@ where } } -impl ComputeSquaredDistance for Ellipse -where - H: ComputeSquaredDistance, - V: ComputeSquaredDistance, - L: ComputeSquaredDistance, -{ - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.position.compute_squared_distance(&other.position)? + - self.semiaxis_x.compute_squared_distance(&other.semiaxis_x)? + - self.semiaxis_y.compute_squared_distance(&other.semiaxis_y)?, - ) - } -} - impl Animatable for ShapeRadius where L: Animatable, @@ -360,20 +294,6 @@ where } } -impl ComputeSquaredDistance for ShapeRadius -where - L: ComputeSquaredDistance, -{ - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&ShapeRadius::Length(ref this), &ShapeRadius::Length(ref other)) => { - this.compute_squared_distance(other) - }, - _ => Err(()), - } - } -} - impl Default for ShapeRadius { #[inline] fn default() -> Self { ShapeRadius::ClosestSide } diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index 9b66ce23dc2..78faf1de050 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -8,7 +8,6 @@ use euclid::Size2D; use properties::animated_properties::Animatable; use std::fmt; use style_traits::ToCss; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::rect::Rect; /// A generic value for a single side of a `border-image-width` property. @@ -37,7 +36,7 @@ pub struct BorderImageSlice { /// /// https://drafts.csswg.org/css-backgrounds-3/#border-radius #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] pub struct BorderRadius { /// The top left radius. pub top_left: BorderCornerRadius, @@ -49,9 +48,9 @@ pub struct BorderRadius { pub bottom_left: BorderCornerRadius, } -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] /// A generic value for `border-*-radius` longhand properties. +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] pub struct BorderCornerRadius(pub Size2D); impl From for BorderImageSlice @@ -132,20 +131,6 @@ where } } -impl ComputeSquaredDistance for BorderRadius -where - L: ComputeSquaredDistance + Copy, -{ - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.top_left.compute_squared_distance(&other.top_left)? + - self.top_right.compute_squared_distance(&other.top_right)? + - self.bottom_right.compute_squared_distance(&other.bottom_right)? + - self.bottom_left.compute_squared_distance(&other.bottom_left)?, - ) - } -} - impl ToCss for BorderRadius where L: PartialEq + ToCss { @@ -193,16 +178,6 @@ where } } -impl ComputeSquaredDistance for BorderCornerRadius -where - L: ComputeSquaredDistance + Copy, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - self.0.compute_squared_distance(&other.0) - } -} - impl ToCss for BorderCornerRadius where L: ToCss, { diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index 9105123f5ab..cff8d87c078 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -65,7 +65,7 @@ pub enum Filter { /// Contrary to the canonical order from the spec, the color is serialised /// first, like in Gecko and Webkit. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] pub struct SimpleShadow { /// Color. pub color: Color, diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 689dd95f1d1..b097b0f85de 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -11,7 +11,6 @@ use parser::{Parse, ParserContext}; use std::fmt; use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss}; use super::CustomIdent; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; pub mod background; pub mod basic_shape; @@ -268,31 +267,13 @@ impl ToCss for FontSettingTagFloat { } /// A wrapper of Non-negative values. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] +#[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, PartialOrd, ToComputedValue, ToCss)] pub struct NonNegative(pub T); -impl ComputeSquaredDistance for NonNegative -where - T: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - self.0.compute_squared_distance(&other.0) - } -} - /// A wrapper of greater-than-or-equal-to-one values. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] +#[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, PartialOrd, ToComputedValue, ToCss)] pub struct GreaterThanOrEqualToOne(pub T); - -impl ComputeSquaredDistance for GreaterThanOrEqualToOne -where - T: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - self.0.compute_squared_distance(&other.0) - } -} diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs index 0c641a62daa..503cb9a1563 100644 --- a/components/style/values/generics/position.rs +++ b/components/style/values/generics/position.rs @@ -5,11 +5,9 @@ //! Generic types for CSS handling of specified and computed values of //! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position) -use values::distance::{ComputeSquaredDistance, SquaredDistance}; - -#[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). +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] pub struct Position { /// The horizontal component of position. pub horizontal: H, @@ -26,17 +24,3 @@ impl Position { } } } - -impl ComputeSquaredDistance for Position -where - H: ComputeSquaredDistance, - V: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.horizontal.compute_squared_distance(&other.horizontal)? + - self.vertical.compute_squared_distance(&other.vertical)?, - ) - } -} diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index b948cf88f82..89ce196267a 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -9,11 +9,10 @@ use parser::{Parse, ParserContext}; use properties::animated_properties::Animatable; use std::fmt; use style_traits::{ToCss, ParseError}; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A CSS value made of four components, where its `ToCss` impl will try to /// serialize as few components as possible, like for example in `border-width`. -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct Rect(pub T, pub T, pub T, pub T); @@ -71,21 +70,6 @@ where } } -impl ComputeSquaredDistance for Rect -where - L: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - Ok( - self.0.compute_squared_distance(&other.0)? + - self.1.compute_squared_distance(&other.1)? + - self.2.compute_squared_distance(&other.2)? + - self.3.compute_squared_distance(&other.3)?, - ) - } -} - impl From for Rect where T: Clone { diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 079bce1f1c1..60f76950aee 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -6,10 +6,8 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; -use properties::animated_properties::RepeatableListAnimatable; use std::fmt; use style_traits::{ParseError, StyleParseError, ToCss}; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// An SVG paint value /// @@ -99,7 +97,8 @@ impl Parse for SVGPaint { /// ` | | ` Length(LengthType), @@ -107,28 +106,9 @@ pub enum SVGLength { ContextValue, } -impl ComputeSquaredDistance for SVGLength -where - L: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&SVGLength::Length(ref this), &SVGLength::Length(ref other)) => { - this.compute_squared_distance(other) - }, - _ => { - // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` - // if `self` and `other` are the same keyword value? - Err(()) - }, - } - } -} - /// Generic value for stroke-dasharray. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Debug, PartialEq, HasViewportPercentage, ToAnimatedValue, ToComputedValue)] +#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq, HasViewportPercentage, ToAnimatedValue, ToComputedValue)] pub enum SVGStrokeDashArray { /// `[ | | ]#` Values(Vec), @@ -136,25 +116,6 @@ pub enum SVGStrokeDashArray { ContextValue, } -impl ComputeSquaredDistance for SVGStrokeDashArray -where - L: ComputeSquaredDistance + RepeatableListAnimatable, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => { - this.compute_squared_distance(other) - }, - _ => { - // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` - // if `self` and `other` are the same keyword value? - Err(()) - }, - } - } -} - impl ToCss for SVGStrokeDashArray where LengthType: ToCss { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match self { @@ -181,7 +142,7 @@ impl ToCss for SVGStrokeDashArray where LengthType: ToCs /// An SVG opacity value accepts `context-{fill,stroke}-opacity` in /// addition to opacity value. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, HasViewportPercentage, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, HasViewportPercentage, ToComputedValue, ToCss)] pub enum SVGOpacity { /// `` Opacity(OpacityType), @@ -190,22 +151,3 @@ pub enum SVGOpacity { /// `context-stroke-opacity` ContextStrokeOpacity, } - -impl ComputeSquaredDistance for SVGOpacity -where - L: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => { - this.compute_squared_distance(other) - } - _ => { - // FIXME(nox): Should this return `Ok(SquaredDistance::Value(0.))` - // if `self` and `other` are the same keyword value? - Err(()) - }, - } - } -} diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index 3330d0dbceb..a3879602bdc 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -110,7 +110,7 @@ where /// A generic value for the `line-height` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] pub enum LineHeight { /// `normal` Normal, diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index e00104f0c43..32f37caec12 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -24,7 +24,7 @@ pub struct Matrix { /// A generic transform origin. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] pub struct TransformOrigin { /// The horizontal origin. pub horizontal: H, diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 4a2c20b3b18..f03ab188a7a 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -16,7 +16,6 @@ use std::ascii::AsciiExt; use std::fmt::{self, Debug}; use std::hash; use style_traits::{ToCss, ParseError, StyleParseError}; -use values::distance::{ComputeSquaredDistance, SquaredDistance}; pub mod animated; pub mod computed; @@ -53,7 +52,8 @@ impl Parse for Impossible { /// A struct representing one of two kinds of values. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToAnimatedValue, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, HasViewportPercentage, PartialEq)] +#[derive(ToAnimatedValue, ToComputedValue, ToCss)] pub enum Either { /// The first value. First(A), @@ -61,25 +61,6 @@ pub enum Either { Second(B), } -impl ComputeSquaredDistance for Either -where - A: ComputeSquaredDistance, - B: ComputeSquaredDistance, -{ - #[inline] - fn compute_squared_distance(&self, other: &Self) -> Result { - match (self, other) { - (&Either::First(ref this), &Either::First(ref other)) => { - this.compute_squared_distance(other) - }, - (&Either::Second(ref this), &Either::Second(ref other)) => { - this.compute_squared_distance(other) - }, - _ => Err(()) - } - } -} - impl Debug for Either { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/components/style_derive/compute_squared_distance.rs b/components/style_derive/compute_squared_distance.rs new file mode 100644 index 00000000000..46aa376319d --- /dev/null +++ b/components/style_derive/compute_squared_distance.rs @@ -0,0 +1,117 @@ +/* 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 std::borrow::Cow; +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()))) + } + + let variants = variants(&input); + let mut match_body = quote!(); + match_body.append_all(variants.iter().map(|variant| { + let name = match input.body { + syn::Body::Struct(_) => Cow::Borrowed(&input.ident), + syn::Body::Enum(_) => { + Cow::Owned(syn::Ident::from(format!("{}::{}", input.ident, variant.ident))) + }, + }; + let (this_pattern, this_info) = synstructure::match_pattern( + &name, + &variant.data, + &synstructure::BindOpts::with_prefix( + synstructure::BindStyle::Ref, + "this".to_owned(), + ), + ); + let (other_pattern, other_info) = synstructure::match_pattern( + &name, + &variant.data, + &synstructure::BindOpts::with_prefix( + synstructure::BindStyle::Ref, + "other".to_owned(), + ), + ); + let sum = if this_info.is_empty() { + quote! { ::values::distance::SquaredDistance::Value(0.) } + } else { + let mut sum = quote!(); + sum.append_separated(this_info.iter().zip(&other_info).map(|(this, other)| { + where_clause.predicates.push(where_predicate(this.field.ty.clone())); + quote! { + ::values::distance::ComputeSquaredDistance::compute_squared_distance(#this, #other)? + } + }), "+"); + sum + }; + quote! { + (&#this_pattern, &#other_pattern) => { + Ok(#sum) + } + } + })); + + if variants.len() > 1 { + match_body = quote! { #match_body, _ => Err(()), }; + } + + quote! { + impl #impl_generics ::values::distance::ComputeSquaredDistance for #name #ty_generics #where_clause { + #[allow(unused_variables, unused_imports)] + #[inline] + fn compute_squared_distance( + &self, + other: &Self, + ) -> Result<::values::distance::SquaredDistance, ()> { + match (self, other) { + #match_body + } + } + } + } +} + +fn variants(input: &syn::DeriveInput) -> Cow<[syn::Variant]> { + match input.body { + syn::Body::Enum(ref variants) => (&**variants).into(), + syn::Body::Struct(ref data) => { + vec![syn::Variant { + ident: input.ident.clone(), + attrs: input.attrs.clone(), + data: data.clone(), + discriminant: None, + }].into() + }, + } +} + +fn where_predicate(ty: syn::Ty) -> 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: syn::Path { + global: true, + segments: vec![ + "values".into(), + "distance".into(), + "ComputeSquaredDistance".into(), + ], + }, + }, + syn::TraitBoundModifier::None, + )], + }, + ) +} diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs index 683d6c2c563..13a855eb6ba 100644 --- a/components/style_derive/lib.rs +++ b/components/style_derive/lib.rs @@ -9,11 +9,18 @@ extern crate synstructure; use proc_macro::TokenStream; +mod compute_squared_distance; mod has_viewport_percentage; mod to_animated_value; mod to_computed_value; mod to_css; +#[proc_macro_derive(ComputeSquaredDistance)] +pub fn derive_compute_squared_distance(stream: TokenStream) -> TokenStream { + let input = syn::parse_derive_input(&stream.to_string()).unwrap(); + compute_squared_distance::derive(input).to_string().parse().unwrap() +} + #[proc_macro_derive(HasViewportPercentage)] pub fn derive_has_viewport_percentage(stream: TokenStream) -> TokenStream { let input = syn::parse_derive_input(&stream.to_string()).unwrap();