aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/macros.rs2
-rw-r--r--components/style/properties/helpers.mako.rs72
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs525
-rw-r--r--components/style/properties/longhand/font.mako.rs12
-rw-r--r--components/style/properties/longhand/inherited_table.mako.rs13
-rw-r--r--components/style/values/animated/effects.rs33
-rw-r--r--components/style/values/computed/background.rs21
-rw-r--r--components/style/values/computed/length.rs96
-rw-r--r--components/style/values/computed/mod.rs16
-rw-r--r--components/style/values/computed/text.rs16
-rw-r--r--components/style/values/computed/transform.rs14
-rw-r--r--components/style/values/distance.rs124
-rw-r--r--components/style/values/generics/background.rs2
-rw-r--r--components/style/values/generics/basic_shape.rs139
-rw-r--r--components/style/values/generics/border.rs29
-rw-r--r--components/style/values/generics/effects.rs2
-rw-r--r--components/style/values/generics/mod.rs10
-rw-r--r--components/style/values/generics/position.rs4
-rw-r--r--components/style/values/generics/rect.rs2
-rw-r--r--components/style/values/generics/svg.rs7
-rw-r--r--components/style/values/generics/text.rs14
-rw-r--r--components/style/values/generics/transform.rs2
-rw-r--r--components/style/values/mod.rs4
-rw-r--r--components/style_derive/compute_squared_distance.rs117
-rw-r--r--components/style_derive/lib.rs7
-rw-r--r--ports/geckolib/glue.rs3
26 files changed, 545 insertions, 741 deletions
diff --git a/components/style/macros.rs b/components/style/macros.rs
index d72ecc73c06..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 {
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index 82eeb653e16..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<single_value::T>,
@@ -142,16 +145,6 @@
fn add(&self, other: &Self) -> Result<Self, ()> {
self.0.add(&other.0).map(T)
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.0.compute_distance(&other.0)
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- self.0.compute_squared_distance(&other.0)
- }
}
impl ToAnimatedZero for T {
@@ -956,63 +949,6 @@
%>
</%def>
-/// Macro for defining Animatable trait for tuple struct which has Option<T>,
-/// e.g. struct T(pub Option<Au>).
-<%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<Self, ()> {
- 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<f64, ()> {
- 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<f64, ()> {
- 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)
- },
- }
- }
- }
-</%def>
-
// 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)">
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, ()> {
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<f64, ()> { 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<f64, ()> {
- 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<f64, ()> {
+impl ComputeSquaredDistance for AnimationValue {
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
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<T> ComputeSquaredDistance for $ty
+ where
+ T: ComputeSquaredDistance + RepeatableListAnimatable,
+ {
#[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- // 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<SquaredDistance, ()> {
+ 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<Self, ()> {
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<f64, ()> {
- self.0.compute_distance(&other.0)
- }
}
impl <T> Animatable for Option<T>
@@ -852,28 +840,6 @@ impl <T> Animatable for Option<T>
_ => Err(()),
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
- 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<Self, ()> {
Ok((*self as f64 * self_portion + *other as f64 * other_portion) as f32)
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<Self, ()> {
Ok(*self * self_portion + *other * other_portion)
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<Self, ()> {
Ok((*self as f64 * self_portion + *other as f64 * other_portion).round() as i32)
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
- // 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<Self, ()> {
Ok(Percentage((self.0 as f64 * self_portion + other.0 as f64 * other_portion) as f32))
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
- if *self == *other {
- Ok(0.0)
- } else {
- Ok(1.0)
- }
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ Ok(SquaredDistance::Value(if *self == *other { 0. } else { 1. }))
}
}
@@ -1003,16 +940,6 @@ impl<T: Animatable + Copy> Animatable for Size2D<T> {
Ok(Size2D::new(width, height))
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.compute_squared_distance(other)?.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.width.compute_squared_distance(&other.width)? + self.height.compute_squared_distance(&other.height)?)
- }
}
impl<T: Animatable + Copy> Animatable for Point2D<T> {
@@ -1044,15 +971,20 @@ impl Animatable for VerticalAlign {
_ => Err(()),
}
}
+}
+impl ComputeSquaredDistance for VerticalAlign {
#[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (*self, *other) {
- (VerticalAlign::LengthOrPercentage(ref this),
- VerticalAlign::LengthOrPercentage(ref other)) => {
- this.compute_distance(other)
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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<f64, ()> {
- self.compute_squared_distance(other).map(|sq| sq.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
- 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<f64, ()> {
- 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<f64, ()> {
- 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<CalcLengthOrPercentage> = From::from(this);
- let other: Option<CalcLengthOrPercentage> = From::from(other);
- this.compute_distance(&other)
- }
- }
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<CalcLengthOrPercentage> = From::from(this);
- let other: Option<CalcLengthOrPercentage> = 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<f64, ()> {
- 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 = <Option<CalcLengthOrPercentage>>::from(this);
- let other = <Option<CalcLengthOrPercentage>>::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<f64, ()> {
- 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<f64, ()> {
- 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<f64, ()> {
- 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<f64, ()> {
- let from = f64::from(*self);
- let to = f64::from(*other);
- from.compute_distance(&to)
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ f64::from(*self).compute_squared_distance(&(*other).into())
}
}
@@ -1500,17 +1282,6 @@ impl<H: Animatable, V: Animatable> Animatable for generic_position::Position<H,
vertical: self.vertical.add_weighted(&other.vertical, self_portion, other_portion)?,
})
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.horizontal.compute_squared_distance(&other.horizontal)? +
- self.vertical.compute_squared_distance(&other.vertical)?)
- }
}
impl<H, V> ToAnimatedZero for generic_position::Position<H, V>
@@ -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<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<SquaredDistance, ()> {
+ // FIXME: This should be implemented.
+ Err(())
+ }
+}
+
impl ToAnimatedZero for TransformList {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
@@ -2666,32 +2429,6 @@ impl<T, U> Animatable for Either<T, U>
}
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
- 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<A, B> ToAnimatedZero for Either<A, B>
@@ -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<f64, ()> {
- self.compute_squared_distance(other).map(|sq| sq.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<SquaredDistance, ()> {
+ 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<f64, ()> {
- self.compute_squared_distance(other).map(|sq| sq.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
// 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<f64, ()> {
- self.compute_squared_distance(other).map(|sq| sq.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.kind.compute_squared_distance(&other.kind)? +
- self.fallback.compute_squared_distance(&other.fallback)?)
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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<f64, ()> {
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
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<LengthType> Animatable for SVGLength<LengthType>
}
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (self, other) {
- (&SVGLength::Length(ref this), &SVGLength::Length(ref other)) => {
- this.compute_distance(other)
- }
- _ => Err(())
- }
- }
}
impl<LengthType> ToAnimatedZero for SVGLength<LengthType> where LengthType : ToAnimatedZero {
@@ -3097,16 +2817,6 @@ impl<LengthType> Animatable for SVGStrokeDashArray<LengthType>
}
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (self, other) {
- (&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => {
- this.compute_distance(other)
- }
- _ => Err(())
- }
- }
}
impl<LengthType> ToAnimatedZero for SVGStrokeDashArray<LengthType>
@@ -3138,16 +2848,6 @@ impl<OpacityType> Animatable for SVGOpacity<OpacityType>
}
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (self, other) {
- (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => {
- this.compute_distance(other)
- }
- _ => Err(())
- }
- }
}
impl<OpacityType> ToAnimatedZero for SVGOpacity<OpacityType>
@@ -3246,9 +2946,7 @@ fn add_weighted_filter_function(from: Option<<&AnimatedFilter>,
}
}
-fn compute_filter_square_distance(from: &AnimatedFilter,
- to: &AnimatedFilter)
- -> Result<f64, ()> {
+fn compute_filter_square_distance(from: &AnimatedFilter, to: &AnimatedFilter) -> Result<SquaredDistance, ()> {
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<Self, ()> {
Ok(AnimatedFilterList(self.0.iter().chain(other.0.iter()).cloned().collect()))
}
+}
+impl ComputeSquaredDistance for AnimatedFilterList {
#[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
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<T> Animatable for NonNegative<T>
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(NonNegative::<T>)
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.0.compute_distance(&other.0)
- }
}
impl<T> ToAnimatedZero for NonNegative<T>
@@ -3405,11 +3093,6 @@ impl<T> Animatable for GreaterThanOrEqualToOne<T>
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(GreaterThanOrEqualToOne::<T>)
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.0.compute_distance(&other.0)
- }
}
impl<T> ToAnimatedZero for GreaterThanOrEqualToOne<T>
diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs
index 96ba9199bf2..0ebcf2db9a7 100644
--- a/components/style/properties/longhand/font.mako.rs
+++ b/components/style/properties/longhand/font.mako.rs
@@ -485,7 +485,7 @@ ${helpers.single_keyword_system("font-variant-caps",
///
/// 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);
@@ -1118,6 +1118,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 +1146,13 @@ ${helpers.single_keyword_system("font-variant-caps",
_ => Err(()),
}
}
+ }
+ impl ComputeSquaredDistance for T {
#[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (*self, *other) {
- (T::Number(ref number), T::Number(ref other)) =>
- number.compute_distance(other),
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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..1d646cc9410 100644
--- a/components/style/properties/longhand/inherited_table.mako.rs
+++ b/components/style/properties/longhand/inherited_table.mako.rs
@@ -31,7 +31,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
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,
@@ -49,17 +49,6 @@ ${helpers.single_keyword("caption-side", "top bottom",
self_portion, other_portion)?,
})
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.horizontal.compute_squared_distance(&other.horizontal)? +
- self.vertical.compute_squared_distance(&other.vertical)?)
- }
}
impl ToAnimatedZero for T {
diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs
index 9bd3456d028..37cf926a1d7 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<S> ComputeSquaredDistance for ShadowList<S> {
+ #[inline]
+ fn compute_squared_distance(&self, _other: &Self) -> Result<SquaredDistance, ()> {
+ // FIXME: This should be implemented.
+ Err(())
+ }
+}
+
impl<S> ToAnimatedZero for ShadowList<S> {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
@@ -140,14 +149,11 @@ impl Animatable for BoxShadow {
inset: self.inset,
})
}
+}
+impl ComputeSquaredDistance for BoxShadow {
#[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
if self.inset != other.inset {
return Err(());
}
@@ -219,21 +225,6 @@ impl Animatable for SimpleShadow {
blur: blur,
})
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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 {
diff --git a/components/style/values/computed/background.rs b/components/style/values/computed/background.rs
index d2781ac1891..a2111a046e4 100644
--- a/components/style/values/computed/background.rs
+++ b/components/style/values/computed/background.rs
@@ -30,27 +30,6 @@ impl Animatable for BackgroundSize {
_ => Err(()),
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sd| sd.sqrt())
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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 {
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<Percentage>,
}
+impl ComputeSquaredDistance for CalcLengthOrPercentage {
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ // 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<SquaredDistance, ()> {
+ 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<Au> 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<SquaredDistance, ()> {
+ 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) => {
+ <Option<CalcLengthOrPercentage>>::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<SquaredDistance, ()> {
+ 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) => {
+ <Option<CalcLengthOrPercentage>>::compute_squared_distance(&(*this).into(), &(*other).into())
+ }
+ }
+ }
+}
+
impl LengthOrPercentageOrNone {
/// Returns the used value.
pub fn to_used_value(&self, containing_length: Au) -> Option<Au> {
@@ -607,6 +671,22 @@ pub enum MozLength {
ExtremumLength(ExtremumLength),
}
+impl ComputeSquaredDistance for MozLength {
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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<SquaredDistance, ()> {
+ 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..b963d37fab6 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<SquaredDistance, ()> {
+ // 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 {
@@ -533,9 +543,9 @@ pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
/// NonNegativeLengthOrPercentage | NonNegativeNumber
pub type NonNegativeLengthOrPercentageOrNumber = Either<NonNegativeNumber, NonNegativeLengthOrPercentage>;
-#[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<Au>,
@@ -649,7 +659,7 @@ impl From<Au> for NonNegativeAu {
}
/// A computed `<percentage>` 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);
diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs
index 7376616ba5e..fd39b4dd647 100644
--- a/components/style/values/computed/text.rs
+++ b/components/style/values/computed/text.rs
@@ -45,22 +45,6 @@ impl Animatable for LineHeight {
_ => Err(()),
}
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (*self, *other) {
- (GenericLineHeight::Length(ref this), GenericLineHeight::Length(ref other)) => {
- this.compute_distance(other)
- },
- (GenericLineHeight::Number(ref this), GenericLineHeight::Number(ref other)) => {
- this.compute_distance(other)
- },
- (GenericLineHeight::Normal, GenericLineHeight::Normal) => Ok(0.),
- #[cfg(feature = "gecko")]
- (GenericLineHeight::MozBlockHeight, GenericLineHeight::MozBlockHeight) => Ok(0.),
- _ => Err(()),
- }
- }
}
impl ToAnimatedZero for LineHeight {
diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs
index 5bf953d46be..70c543b9a7f 100644
--- a/components/style/values/computed/transform.rs
+++ b/components/style/values/computed/transform.rs
@@ -37,20 +37,6 @@ impl Animatable for TransformOrigin {
self.depth.add_weighted(&other.depth, self_portion, other_portion)?,
))
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(f64::sqrt)
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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 {
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<SquaredDistance, ()>;
+}
+
+/// 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<SquaredDistance, ()> {
+ Ok(SquaredDistance::Sqrt(((*self as f64) - (*other as f64)).abs()))
+ }
+}
+
+impl ComputeSquaredDistance for i32 {
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ Ok(SquaredDistance::Sqrt((*self - *other).abs() as f64))
+ }
+}
+
+impl ComputeSquaredDistance for f32 {
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ Ok(SquaredDistance::Sqrt((*self - *other).abs() as f64))
+ }
+}
+
+impl ComputeSquaredDistance for f64 {
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ Ok(SquaredDistance::Sqrt((*self - *other).abs()))
+ }
+}
+
+impl ComputeSquaredDistance for Au {
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ self.0.compute_squared_distance(&other.0)
+ }
+}
+
+impl<T> ComputeSquaredDistance for Option<T>
+ where T: ComputeSquaredDistance
+{
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ match (self.as_ref(), other.as_ref()) {
+ (Some(this), Some(other)) => this.compute_squared_distance(other),
+ (None, None) => Ok(SquaredDistance::Value(0.)),
+ _ => Err(()),
+ }
+ }
+}
+
+impl<T> ComputeSquaredDistance for Size2D<T>
+ where T: ComputeSquaredDistance
+{
+ #[inline]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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<SquaredDistance> 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<I>(mut iter: I) -> Self
+ where
+ I: Iterator<Item = Self>,
+ {
+ 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/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<LengthOrPercentageOrAuto> {
/// `<width> <height>`
diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs
index f218fd41ba8..cad038df0f1 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;
@@ -54,7 +55,7 @@ pub enum ShapeSource<BasicShape, ReferenceBox, Url> {
#[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<H, V, LengthOrPercentage> {
Inset(InsetRect<LengthOrPercentage>),
Circle(Circle<H, V, LengthOrPercentage>),
@@ -65,7 +66,7 @@ pub enum BasicShape<H, V, LengthOrPercentage> {
/// 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<LengthOrPercentage> {
pub rect: Rect<LengthOrPercentage>,
pub round: Option<BorderRadius<LengthOrPercentage>>,
@@ -74,7 +75,7 @@ pub struct InsetRect<LengthOrPercentage> {
/// 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<H, V, LengthOrPercentage> {
pub position: Position<H, V>,
pub radius: ShapeRadius<LengthOrPercentage>,
@@ -83,7 +84,7 @@ pub struct Circle<H, V, LengthOrPercentage> {
/// 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<H, V, LengthOrPercentage> {
pub position: Position<H, V>,
pub semiaxis_x: ShapeRadius<LengthOrPercentage>,
@@ -93,7 +94,7 @@ pub struct Ellipse<H, V, LengthOrPercentage> {
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
pub enum ShapeRadius<LengthOrPercentage> {
Length(LengthOrPercentage),
ClosestSide,
@@ -144,20 +145,16 @@ where
_ => Err(()),
}
}
+}
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
+// FIXME(nox): Implement ComputeSquaredDistance for T types and stop
+// using PartialEq here, this will let us derive this impl.
+impl<B, T, U> ComputeSquaredDistance for ShapeSource<B, T, U>
+where
+ B: ComputeSquaredDistance,
+ T: PartialEq,
+{
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self, other) {
(
&ShapeSource::Shape(ref this, ref this_box),
@@ -209,42 +206,6 @@ where
_ => Err(()),
}
}
-
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<f64, ()> {
- 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<L> Animatable for InsetRect<L>
@@ -261,17 +222,6 @@ where
let round = self.round.add_weighted(&other.round, self_portion, other_portion)?;
Ok(InsetRect { rect, round })
}
-
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.compute_squared_distance(other)?.sqrt())
- }
-
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(
- self.rect.compute_squared_distance(&other.rect)? +
- self.round.compute_squared_distance(&other.round)?,
- )
- }
}
impl<L> ToCss for InsetRect<L>
@@ -304,17 +254,6 @@ where
let radius = self.radius.add_weighted(&other.radius, self_portion, other_portion)?;
Ok(Circle { position, radius })
}
-
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.compute_squared_distance(other)?.sqrt())
- }
-
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(
- self.position.compute_squared_distance(&other.position)? +
- self.radius.compute_squared_distance(&other.radius)?,
- )
- }
}
impl<H, V, L> Animatable for Ellipse<H, V, L>
@@ -334,18 +273,6 @@ 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<f64, ()> {
- Ok(self.compute_squared_distance(other)?.sqrt())
- }
-
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<L> Animatable for ShapeRadius<L>
@@ -365,24 +292,6 @@ where
_ => Err(()),
}
}
-
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- match (self, other) {
- (&ShapeRadius::Length(ref this), &ShapeRadius::Length(ref other)) => {
- this.compute_distance(other)
- },
- _ => Err(()),
- }
- }
-
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- match (self, other) {
- (&ShapeRadius::Length(ref this), &ShapeRadius::Length(ref other)) => {
- this.compute_squared_distance(other)
- },
- _ => Err(()),
- }
- }
}
impl<L> Default for ShapeRadius<L> {
@@ -413,12 +322,13 @@ where
}).collect::<Result<Vec<_>, _>>()?;
Ok(Polygon { fill: self.fill, coordinates })
}
+}
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- Ok(self.compute_squared_distance(other)?.sqrt())
- }
-
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
+impl<L> ComputeSquaredDistance for Polygon<L>
+where
+ L: ComputeSquaredDistance,
+{
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
if self.fill != other.fill {
return Err(());
}
@@ -426,9 +336,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..78faf1de050 100644
--- a/components/style/values/generics/border.rs
+++ b/components/style/values/generics/border.rs
@@ -36,7 +36,7 @@ pub struct BorderImageSlice<NumberOrPercentage> {
///
/// 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<LengthOrPercentage> {
/// The top left radius.
pub top_left: BorderCornerRadius<LengthOrPercentage>,
@@ -48,9 +48,9 @@ pub struct BorderRadius<LengthOrPercentage> {
pub bottom_left: BorderCornerRadius<LengthOrPercentage>,
}
-#[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<L>(pub Size2D<L>);
impl<N> From<N> for BorderImageSlice<N>
@@ -129,19 +129,6 @@ 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<f64, ()> {
- Ok(self.compute_squared_distance(other)?.sqrt())
- }
-
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- 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<L> ToCss for BorderRadius<L>
@@ -189,16 +176,6 @@ where
) -> Result<Self, ()> {
Ok(BorderCornerRadius(self.0.add_weighted(&other.0, self_portion, other_portion)?))
}
-
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.0.compute_distance(&other.0)
- }
-
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
- self.0.compute_squared_distance(&other.0)
- }
}
impl<L> ToCss for BorderCornerRadius<L>
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<Angle, Factor, Length, DropShadow> {
/// 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, SizeLength, ShapeLength> {
/// Color.
pub color: Color,
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index 075ce2c4715..b097b0f85de 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -267,11 +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<T>(pub T);
/// 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<T>(pub T);
diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs
index 4ce5b63ab30..503cb9a1563 100644
--- a/components/style/values/generics/position.rs
+++ b/components/style/values/generics/position.rs
@@ -5,9 +5,9 @@
//! Generic types for CSS handling of specified and computed values of
//! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position)
-#[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<H, V> {
/// The horizontal component of position.
pub horizontal: H,
diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs
index 3dc9e095890..89ce196267a 100644
--- a/components/style/values/generics/rect.rs
+++ b/components/style/values/generics/rect.rs
@@ -12,7 +12,7 @@ use style_traits::{ToCss, ParseError};
/// 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<T>(pub T, pub T, pub T, pub T);
diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs
index 05e0e66248f..60f76950aee 100644
--- a/components/style/values/generics/svg.rs
+++ b/components/style/values/generics/svg.rs
@@ -97,7 +97,8 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP
/// An SVG length value supports `context-value` in addition to length.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, HasViewportPercentage, ToAnimatedValue, ToComputedValue, ToCss)]
+#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
+#[derive(HasViewportPercentage, ToAnimatedValue, ToComputedValue, ToCss)]
pub enum SVGLength<LengthType> {
/// `<length> | <percentage> | <number>`
Length(LengthType),
@@ -107,7 +108,7 @@ pub enum SVGLength<LengthType> {
/// 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<LengthType> {
/// `[ <length> | <percentage> | <number> ]#`
Values(Vec<LengthType>),
@@ -141,7 +142,7 @@ impl<LengthType> ToCss for SVGStrokeDashArray<LengthType> 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<OpacityType> {
/// `<opacity-value>`
Opacity(OpacityType),
diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs
index 94be4a6db8c..a3879602bdc 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<Value> Animatable for Spacing<Value>
let other = other.value().unwrap_or(&zero);
this.add_weighted(other, self_portion, other_portion).map(Spacing::Value)
}
+}
+impl<V> ComputeSquaredDistance for Spacing<V>
+where
+ V: ComputeSquaredDistance + From<Au>,
+{
#[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- let zero = Value::from(Au(0));
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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)
}
}
@@ -104,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<Number, LengthOrPercentage> {
/// `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<T, U = T> {
/// 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<H, V, Depth> {
/// The horizontal origin.
pub horizontal: H,
diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs
index 616aa5cb485..f03ab188a7a 100644
--- a/components/style/values/mod.rs
+++ b/components/style/values/mod.rs
@@ -19,6 +19,7 @@ use style_traits::{ToCss, ParseError, StyleParseError};
pub mod animated;
pub mod computed;
+pub mod distance;
pub mod generics;
pub mod specified;
@@ -51,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<A, B> {
/// The first value.
First(A),
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();
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index b8ab946de88..cdf76aa1407 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -131,6 +131,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;
@@ -380,7 +381,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]