aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/gecko_bindings/bindings.rs7
-rw-r--r--components/style/properties/helpers.mako.rs51
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs619
-rw-r--r--components/style/properties/longhand/background.mako.rs20
-rw-r--r--components/style/properties/longhand/box.mako.rs17
-rw-r--r--components/style/properties/longhand/font.mako.rs13
-rw-r--r--components/style/properties/longhand/inherited_text.mako.rs6
-rw-r--r--components/style/properties/longhand/svg.mako.rs18
-rw-r--r--ports/geckolib/glue.rs11
9 files changed, 750 insertions, 12 deletions
diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs
index 2ea1f286db5..603efb2b100 100644
--- a/components/style/gecko_bindings/bindings.rs
+++ b/components/style/gecko_bindings/bindings.rs
@@ -1754,6 +1754,13 @@ extern "C" {
-> bool;
}
extern "C" {
+ pub fn Servo_AnimationValues_ComputeDistance(from:
+ RawServoAnimationValueBorrowed,
+ to:
+ RawServoAnimationValueBorrowed)
+ -> f64;
+}
+extern "C" {
pub fn Servo_AnimationValue_Serialize(value:
RawServoAnimationValueBorrowed,
property: nsCSSPropertyID,
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index a6cb68f160f..115ed297c57 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -95,6 +95,19 @@
self.0.interpolate(&other.0, progress).map(T)
}
}
+
+ use properties::animated_properties::ComputeDistance;
+ impl ComputeDistance for 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)
+ }
+ }
% endif
}
@@ -785,3 +798,41 @@
}
}
</%def>
+
+/// Macro for defining ComputeDistance trait for tuple struct which has Option<T>,
+/// e.g. struct T(pub Option<Au>).
+<%def name="impl_compute_distance_for_option_tuple(value_for_none)">
+ impl ComputeDistance for T {
+ #[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>
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index ee90f5283b7..fe8b4a47b75 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -10,7 +10,7 @@ use euclid::{Point2D, Size2D};
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
use properties::{CSSWideKeyword, PropertyDeclaration};
use properties::longhands;
-use properties::longhands::background_size::computed_value::T as BackgroundSize;
+use properties::longhands::background_size::computed_value::T as BackgroundSizeList;
use properties::longhands::font_weight::computed_value::T as FontWeight;
use properties::longhands::line_height::computed_value::T as LineHeight;
use properties::longhands::text_shadow::computed_value::T as TextShadowList;
@@ -696,14 +696,14 @@ impl Interpolate for VerticalAlign {
}
}
}
-impl Interpolate for BackgroundSize {
+
+impl Interpolate for BackgroundSizeList {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
- self.0.interpolate(&other.0, progress).map(BackgroundSize)
+ self.0.interpolate(&other.0, progress).map(BackgroundSizeList)
}
}
-
/// https://drafts.csswg.org/css-transitions/#animtype-color
impl Interpolate for RGBA {
#[inline]
@@ -2032,3 +2032,614 @@ impl<T, U> Interpolate for Either<T, U>
}
}
}
+
+
+/// We support ComputeDistance for an API in gecko to test the transition per property.
+impl ComputeDistance for AnimationValue {
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ match (self, other) {
+ % for prop in data.longhands:
+ % if prop.animatable:
+ % if prop.animation_type == "normal":
+ (&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
+ % endfor
+ _ => {
+ panic!("Expected compute_distance of computed values of the same \
+ property, got: {:?}, {:?}", self, other);
+ }
+ }
+ }
+}
+
+/// A trait used to implement [compute_distance].
+/// In order to compute the Euclidean distance of a list, we need to compute squared distance
+/// for each element, so the vector can sum it and then get its squared root as the distance.
+pub trait ComputeDistance: Sized {
+ /// Compute distance between a value and another for a given property.
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()>;
+
+ /// Compute squared distance between a value and another for a given property.
+ /// This is used for list or if there are many components in a property value.
+ fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
+ self.compute_distance(other).map(|d| d * d)
+ }
+}
+
+impl<T: ComputeDistance> ComputeDistance for Vec<T> {
+ #[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 self.len() != other.len() {
+ return Err(());
+ }
+
+ let mut squared_dist = 0.0f64;
+ for (this, other) in self.iter().zip(other) {
+ let diff = try!(this.compute_squared_distance(other));
+ squared_dist += diff;
+ }
+ Ok(squared_dist)
+ }
+}
+
+impl ComputeDistance for Au {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ self.0.compute_distance(&other.0)
+ }
+}
+
+impl ComputeDistance for Auto {
+ #[inline]
+ fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
+ Err(())
+ }
+}
+
+impl ComputeDistance for Normal {
+ #[inline]
+ fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
+ Err(())
+ }
+}
+
+impl <T> ComputeDistance for Option<T>
+ where T: ComputeDistance,
+{
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ match (self, other) {
+ (&Some(ref this), &Some(ref other)) => {
+ this.compute_distance(other)
+ },
+ _ => 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)
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl ComputeDistance for f32 {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ Ok((*self - *other).abs() as f64)
+ }
+}
+
+impl ComputeDistance for f64 {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ Ok((*self - *other).abs())
+ }
+}
+
+impl ComputeDistance for i32 {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ Ok((*self - *other).abs() as f64)
+ }
+}
+
+impl ComputeDistance for Visibility {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ if *self == *other {
+ Ok(0.0)
+ } else {
+ Ok(1.0)
+ }
+ }
+}
+
+/// https://www.w3.org/TR/smil-animation/#animateColorElement says we should use Euclidean RGB-cube distance.
+impl ComputeDistance for RGBA {
+ #[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 clamp(val: f32) -> f32 {
+ val.max(0.).min(1.)
+ }
+
+ let start_a = clamp(self.alpha_f32());
+ let end_a = clamp(other.alpha_f32());
+ let start = [ start_a,
+ self.red_f32() * start_a,
+ self.green_f32() * start_a,
+ self.blue_f32() * start_a ];
+ let end = [ end_a,
+ other.red_f32() * end_a,
+ other.green_f32() * end_a,
+ other.blue_f32() * end_a ];
+ let diff = start.iter().zip(&end)
+ .fold(0.0f64, |n, (&a, &b)| {
+ let diff = (a - b) as f64;
+ n + diff * diff
+ });
+ Ok(diff)
+ }
+}
+
+impl ComputeDistance for CSSParserColor {
+ #[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, ()> {
+ match (*self, *other) {
+ (CSSParserColor::RGBA(ref this), CSSParserColor::RGBA(ref other)) => {
+ this.compute_squared_distance(other)
+ },
+ _ => Ok(0.0),
+ }
+ }
+}
+
+impl ComputeDistance for CalcLengthOrPercentage {
+ #[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.length().0 - other.length().0) as f64;
+ let percentage_diff = (self.percentage() - other.percentage()) as f64;
+ Ok(length_diff * length_diff + percentage_diff * percentage_diff)
+ }
+}
+
+impl ComputeDistance 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 - other) as f64;
+ Ok(diff * diff)
+ },
+ (this, other) => {
+ let this: CalcLengthOrPercentage = From::from(this);
+ let other: CalcLengthOrPercentage = From::from(other);
+ let length_diff = (this.length().0 - other.length().0) as f64;
+ let percentage_diff = (this.percentage() - other.percentage()) as f64;
+ Ok(length_diff * length_diff + percentage_diff * percentage_diff)
+ }
+ }
+ }
+}
+
+impl ComputeDistance 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 - other) as f64;
+ Ok(diff * diff)
+ },
+ (this, other) => {
+ let this: Option<CalcLengthOrPercentage> = From::from(this);
+ let other: Option<CalcLengthOrPercentage> = From::from(other);
+ if this.is_none() || other.is_none() {
+ Err(())
+ } else {
+ let length_diff = (this.unwrap().length().0 - other.unwrap().length().0) as f64;
+ let percentage_diff = (this.unwrap().percentage() - other.unwrap().percentage()) as f64;
+ Ok(length_diff * length_diff + percentage_diff * percentage_diff)
+ }
+ }
+ }
+ }
+}
+
+impl ComputeDistance 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)
+ },
+ _ => Err(())
+ }
+ }
+}
+
+impl ComputeDistance for LengthOrNone {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ match (*self, *other) {
+ (Either::First(ref length), Either::First(ref other)) => {
+ length.compute_distance(other)
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl ComputeDistance for MinLength {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ match (*self, *other) {
+ (MinLength::LengthOrPercentage(ref this),
+ MinLength::LengthOrPercentage(ref other)) => {
+ this.compute_distance(other)
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl ComputeDistance for MaxLength {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ match (*self, *other) {
+ (MaxLength::LengthOrPercentage(ref this),
+ MaxLength::LengthOrPercentage(ref other)) => {
+ this.compute_distance(other)
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl ComputeDistance 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)
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl ComputeDistance for BorderRadiusSize {
+ #[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(try!(self.0.width.compute_squared_distance(&other.0.width)) +
+ try!(self.0.height.compute_squared_distance(&other.0.height)))
+ }
+}
+
+impl ComputeDistance for BackgroundSizeList {
+ #[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 ComputeDistance for LineHeight {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ match (*self, *other) {
+ (LineHeight::Length(ref this),
+ LineHeight::Length(ref other)) => {
+ this.compute_distance(other)
+ },
+ (LineHeight::Number(ref this),
+ LineHeight::Number(ref other)) => {
+ this.compute_distance(other)
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl ComputeDistance for FontWeight {
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ let a = (*self as u32) as f64;
+ let b = (*other as u32) as f64;
+ a.compute_distance(&b)
+ }
+}
+
+impl ComputeDistance for Position {
+ #[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(try!(self.horizontal.compute_squared_distance(&other.horizontal)) +
+ try!(self.vertical.compute_squared_distance(&other.vertical)))
+ }
+}
+
+impl ComputeDistance for HorizontalPosition {
+ #[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 ComputeDistance for VerticalPosition {
+ #[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 ComputeDistance for ClipRect {
+ #[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 = [ try!(self.top.compute_distance(&other.top)),
+ try!(self.right.compute_distance(&other.right)),
+ try!(self.bottom.compute_distance(&other.bottom)),
+ try!(self.left.compute_distance(&other.left)) ];
+ Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
+ }
+}
+
+impl ComputeDistance for TextShadow {
+ #[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 = [ try!(self.offset_x.compute_distance(&other.offset_x)),
+ try!(self.offset_y.compute_distance(&other.offset_y)),
+ try!(self.blur_radius.compute_distance(&other.blur_radius)),
+ try!(self.color.compute_distance(&other.color)) ];
+ Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
+ }
+}
+
+impl ComputeDistance for TextShadowList {
+ #[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 zero = TextShadow {
+ offset_x: Au(0),
+ offset_y: Au(0),
+ blur_radius: Au(0),
+ color: CSSParserColor::RGBA(RGBA::transparent()),
+ };
+
+ let max_len = cmp::max(self.0.len(), other.0.len());
+ let mut diff_squared = 0.0f64;
+ for i in 0..max_len {
+ diff_squared += match (self.0.get(i), other.0.get(i)) {
+ (Some(shadow), Some(other)) => {
+ try!(shadow.compute_squared_distance(other))
+ },
+ (Some(shadow), None) |
+ (None, Some(shadow)) => {
+ try!(shadow.compute_squared_distance(&zero))
+ },
+ (None, None) => unreachable!(),
+ };
+ }
+ Ok(diff_squared)
+ }
+}
+
+impl ComputeDistance 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, ()> {
+ if self.inset != other.inset {
+ return Err(());
+ }
+ let list = [ try!(self.offset_x.compute_distance(&other.offset_x)),
+ try!(self.offset_y.compute_distance(&other.offset_y)),
+ try!(self.color.compute_distance(&other.color)),
+ try!(self.spread_radius.compute_distance(&other.spread_radius)),
+ try!(self.blur_radius.compute_distance(&other.blur_radius)) ];
+ Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
+ }
+}
+
+impl ComputeDistance for BoxShadowList {
+ #[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, ()> {
+ // The inset value must change
+ let mut zero = BoxShadow {
+ offset_x: Au(0),
+ offset_y: Au(0),
+ spread_radius: Au(0),
+ blur_radius: Au(0),
+ color: CSSParserColor::RGBA(RGBA::transparent()),
+ inset: false,
+ };
+
+ let max_len = cmp::max(self.0.len(), other.0.len());
+ let mut diff_squared = 0.0f64;
+ for i in 0..max_len {
+ diff_squared += match (self.0.get(i), other.0.get(i)) {
+ (Some(shadow), Some(other)) => {
+ try!(shadow.compute_squared_distance(other))
+ },
+ (Some(shadow), None) |
+ (None, Some(shadow)) => {
+ zero.inset = shadow.inset;
+ try!(shadow.compute_squared_distance(&zero))
+ }
+ (None, None) => unreachable!(),
+ };
+ }
+ Ok(diff_squared)
+ }
+}
+
+impl ComputeDistance for TransformList {
+ #[inline]
+ fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
+ Err(())
+ }
+}
+
+impl<T, U> ComputeDistance for Either<T, U>
+ where T: ComputeDistance, U: ComputeDistance
+{
+ #[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(())
+ }
+ }
+}
diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs
index 994f70a0a25..2c085cfe9b9 100644
--- a/components/style/properties/longhand/background.mako.rs
+++ b/components/style/properties/longhand/background.mako.rs
@@ -334,7 +334,7 @@ ${helpers.single_keyword("background-origin",
#[allow(missing_docs)]
pub mod computed_value {
use values::computed::LengthOrPercentageOrAuto;
- use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
+ use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -367,6 +367,24 @@ ${helpers.single_keyword("background-origin",
}
}
}
+
+ impl ComputeDistance for T {
+ #[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) {
+ (&T::Explicit(ref me), &T::Explicit(ref other)) => {
+ Ok(try!(me.width.compute_squared_distance(&other.width)) +
+ try!(me.height.compute_squared_distance(&other.height)))
+ },
+ _ => Err(())
+ }
+ }
+ }
}
impl ToCss for computed_value::T {
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index 9f539243fd2..4e6c958f7e5 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -2197,7 +2197,7 @@ ${helpers.single_keyword("transform-style",
use values::specified::{NoCalcLength, LengthOrPercentage, Percentage};
pub mod computed_value {
- use properties::animated_properties::Interpolate;
+ use properties::animated_properties::{ComputeDistance, Interpolate};
use values::computed::{Length, LengthOrPercentage};
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -2209,6 +2209,7 @@ ${helpers.single_keyword("transform-style",
}
impl Interpolate for T {
+ #[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(T {
horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
@@ -2217,6 +2218,20 @@ ${helpers.single_keyword("transform-style",
})
}
}
+
+ impl ComputeDistance for T {
+ #[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(try!(self.horizontal.compute_squared_distance(&other.horizontal)) +
+ try!(self.vertical.compute_squared_distance(&other.vertical)) +
+ try!(self.depth.compute_squared_distance(&other.depth)))
+ }
+ }
}
impl HasViewportPercentage for SpecifiedValue {
diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs
index e9ad7208c76..edb99e39caf 100644
--- a/components/style/properties/longhand/font.mako.rs
+++ b/components/style/properties/longhand/font.mako.rs
@@ -818,7 +818,7 @@ ${helpers.single_keyword("font-variant-caps",
}
pub mod computed_value {
- use properties::animated_properties::Interpolate;
+ use properties::animated_properties::{ComputeDistance, Interpolate};
use std::fmt;
use style_traits::ToCss;
use values::CSSFloat;
@@ -850,6 +850,17 @@ ${helpers.single_keyword("font-variant-caps",
}
}
}
+
+ impl ComputeDistance 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),
+ _ => Err(()),
+ }
+ }
+ }
}
#[inline]
diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs
index bddc1ea10c7..0b1cf0a0229 100644
--- a/components/style/properties/longhand/inherited_text.mako.rs
+++ b/components/style/properties/longhand/inherited_text.mako.rs
@@ -439,13 +439,14 @@ ${helpers.single_keyword("text-align-last",
pub mod computed_value {
use app_units::Au;
- use properties::animated_properties::Interpolate;
+ use properties::animated_properties::{ComputeDistance, Interpolate};
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub Option<Au>);
${helpers.impl_interpolate_for_option_tuple('Au(0)')}
+ ${helpers.impl_compute_distance_for_option_tuple('Au(0)')}
}
impl ToCss for computed_value::T {
@@ -523,13 +524,14 @@ ${helpers.single_keyword("text-align-last",
}
pub mod computed_value {
- use properties::animated_properties::Interpolate;
+ use properties::animated_properties::{ComputeDistance, Interpolate};
use values::computed::LengthOrPercentage;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub Option<LengthOrPercentage>);
${helpers.impl_interpolate_for_option_tuple('LengthOrPercentage::zero()')}
+ ${helpers.impl_compute_distance_for_option_tuple('LengthOrPercentage::zero()')}
}
impl ToCss for computed_value::T {
diff --git a/components/style/properties/longhand/svg.mako.rs b/components/style/properties/longhand/svg.mako.rs
index dea04984cf1..ddcf86c35f6 100644
--- a/components/style/properties/longhand/svg.mako.rs
+++ b/components/style/properties/longhand/svg.mako.rs
@@ -121,7 +121,7 @@ ${helpers.single_keyword("mask-mode",
pub use properties::longhands::background_position_x::single_value::parse;
pub use properties::longhands::background_position_x::single_value::SpecifiedValue;
pub use properties::longhands::background_position_x::single_value::computed_value;
- use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
+ use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
use properties::longhands::mask_position_x::computed_value::T as MaskPositionX;
impl Interpolate for MaskPositionX {
@@ -132,6 +132,13 @@ ${helpers.single_keyword("mask-mode",
}
impl RepeatableListInterpolate for MaskPositionX {}
+
+ impl ComputeDistance for MaskPositionX {
+ #[inline]
+ fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
+ Err(())
+ }
+ }
</%helpers:vector_longhand>
<%helpers:vector_longhand name="mask-position-y" products="gecko" animation_type="normal" extra_prefixes="webkit"
@@ -142,7 +149,7 @@ ${helpers.single_keyword("mask-mode",
pub use properties::longhands::background_position_y::single_value::parse;
pub use properties::longhands::background_position_y::single_value::SpecifiedValue;
pub use properties::longhands::background_position_y::single_value::computed_value;
- use properties::animated_properties::{Interpolate, RepeatableListInterpolate};
+ use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
use properties::longhands::mask_position_y::computed_value::T as MaskPositionY;
impl Interpolate for MaskPositionY {
@@ -153,6 +160,13 @@ ${helpers.single_keyword("mask-mode",
}
impl RepeatableListInterpolate for MaskPositionY {}
+
+ impl ComputeDistance for MaskPositionY {
+ #[inline]
+ fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
+ Err(())
+ }
+ }
</%helpers:vector_longhand>
${helpers.single_keyword("mask-clip",
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index 81c956c3187..426802e615b 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -74,7 +74,7 @@ use style::parser::{LengthParsingMode, ParserContext};
use style::properties::{CascadeFlags, ComputedValues, Importance, ParsedDeclaration};
use style::properties::{PropertyDeclarationBlock, PropertyId};
use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
-use style::properties::animated_properties::{AnimationValue, Interpolate, TransitionProperty};
+use style::properties::animated_properties::{AnimationValue, ComputeDistance, Interpolate, TransitionProperty};
use style::properties::parse_one_declaration;
use style::restyle_hints::{self, RestyleHint};
use style::rule_tree::StyleSource;
@@ -266,6 +266,15 @@ pub extern "C" fn Servo_AnimationValues_IsInterpolable(from: RawServoAnimationVa
}
#[no_mangle]
+pub extern "C" fn Servo_AnimationValues_ComputeDistance(from: RawServoAnimationValueBorrowed,
+ to: RawServoAnimationValueBorrowed)
+ -> 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)
+}
+
+#[no_mangle]
pub extern "C" fn Servo_AnimationValueMap_Push(value_map: RawServoAnimationValueMapBorrowed,
property: nsCSSPropertyID,
value: RawServoAnimationValueBorrowed)