aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/properties/helpers.mako.rs19
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs1218
-rw-r--r--components/style/properties/longhand/background.mako.rs8
-rw-r--r--components/style/properties/longhand/box.mako.rs6
-rw-r--r--components/style/properties/longhand/font.mako.rs6
-rw-r--r--components/style/properties/longhand/inherited_table.mako.rs6
-rw-r--r--components/style/properties/longhand/inherited_text.mako.rs10
-rw-r--r--components/style/properties/longhand/svg.mako.rs26
-rw-r--r--components/style/values/mod.rs11
-rw-r--r--ports/geckolib/glue.rs2
-rw-r--r--tests/unit/style/animated_properties.rs2
11 files changed, 556 insertions, 758 deletions
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index 9f89abda857..6adce11d9c1 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -111,15 +111,12 @@
pub struct T(pub SmallVec<[single_value::T; 1]>);
% if delegate_animate:
- use properties::animated_properties::Interpolate;
- impl Interpolate for T {
+ use properties::animated_properties::Animatable;
+ impl Animatable for T {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
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)
@@ -974,10 +971,10 @@
%>
</%def>
-/// Macro for defining Interpolate trait for tuple struct which has Option<T>,
+/// Macro for defining Animatable trait for tuple struct which has Option<T>,
/// e.g. struct T(pub Option<Au>).
-<%def name="impl_interpolate_for_option_tuple(value_for_none)">
- impl Interpolate for T {
+<%def name="impl_animatable_for_option_tuple(value_for_none)">
+ impl Animatable for T {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (self, other) {
@@ -995,13 +992,7 @@
},
}
}
- }
-</%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) {
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index 8767f78102f..fcc963d2d2a 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -581,7 +581,7 @@ impl AnimationValue {
}
}
-impl Interpolate for AnimationValue {
+impl Animatable for AnimationValue {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (self, other) {
% for prop in data.longhands:
@@ -607,23 +607,57 @@ impl Interpolate for AnimationValue {
}
}
}
+
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ 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
+ % endfor
+ _ => {
+ panic!("Expected compute_distance of computed values of the same \
+ property, got: {:?}, {:?}", self, other);
+ }
+ }
+ }
}
-/// A trait used to implement [interpolation][interpolated-types].
-///
-/// [interpolated-types]: https://drafts.csswg.org/css-transitions/#interpolated-types
-pub trait Interpolate: Sized {
- /// Interpolate a value with another for a given property.
+/// A trait used to implement various procedures used during animation.
+pub trait Animatable: Sized {
+ /// [Interpolates][interpolation] a value with another for a given property.
+ ///
+ /// [interpolation]: https://w3c.github.io/web-animations/#animation-interpolation
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()>;
+
+ /// 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
-pub trait RepeatableListInterpolate: Interpolate {}
+pub trait RepeatableListAnimatable: Animatable {}
-impl RepeatableListInterpolate for Either<f32, LengthOrPercentage> {}
+impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
-impl<T: RepeatableListInterpolate> Interpolate for SmallVec<[T; 1]> {
+impl<T: RepeatableListAnimatable> Animatable for SmallVec<[T; 1]> {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
use num_integer::lcm;
let len = lcm(self.len(), other.len());
@@ -631,18 +665,37 @@ impl<T: RepeatableListInterpolate> Interpolate for SmallVec<[T; 1]> {
me.interpolate(you, progress)
}).collect()
}
+
+ #[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, ()> {
+ 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)
+ }).collect::<Result<Vec<_>, _>>().map(|d| d.iter().sum())
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-number
-impl Interpolate for Au {
+impl Animatable for Au {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Au((self.0 as f64 + (other.0 as f64 - self.0 as f64) * progress).round() as i32))
}
+
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ self.0.compute_distance(&other.0)
+ }
}
-impl <T> Interpolate for Option<T>
- where T: Interpolate,
+impl <T> Animatable for Option<T>
+ where T: Animatable,
{
#[inline]
fn interpolate(&self, other: &Option<T>, progress: f64) -> Result<Option<T>, ()> {
@@ -653,36 +706,71 @@ impl <T> Interpolate 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)
+ },
+ _ => 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(()),
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-number
-impl Interpolate for f32 {
+impl Animatable for f32 {
#[inline]
fn interpolate(&self, other: &f32, progress: f64) -> Result<Self, ()> {
Ok(((*self as f64) + ((*other as f64) - (*self as f64)) * progress) 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
-impl Interpolate for f64 {
+impl Animatable for f64 {
#[inline]
fn interpolate(&self, other: &f64, progress: f64) -> Result<Self, ()> {
Ok(*self + (*other - *self) * progress)
}
+
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ Ok((*self - *other).abs())
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-integer
-impl Interpolate for i32 {
+impl Animatable for i32 {
#[inline]
fn interpolate(&self, other: &i32, progress: f64) -> Result<Self, ()> {
let a = *self as f64;
let b = *other as f64;
Ok((a + (b - a) * progress).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
-impl Interpolate for Angle {
+impl Animatable for Angle {
#[inline]
fn interpolate(&self, other: &Angle, progress: f64) -> Result<Self, ()> {
self.radians().interpolate(&other.radians(), progress).map(Angle::from_radians)
@@ -690,7 +778,7 @@ impl Interpolate for Angle {
}
/// https://drafts.csswg.org/css-transitions/#animtype-visibility
-impl Interpolate for Visibility {
+impl Animatable for Visibility {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -706,9 +794,18 @@ impl Interpolate for Visibility {
_ => Err(()),
}
}
+
+ #[inline]
+ fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+ if *self == *other {
+ Ok(0.0)
+ } else {
+ Ok(1.0)
+ }
+ }
}
-impl<T: Interpolate + Copy> Interpolate for Size2D<T> {
+impl<T: Animatable + Copy> Animatable for Size2D<T> {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
let width = try!(self.width.interpolate(&other.width, progress));
@@ -718,7 +815,7 @@ impl<T: Interpolate + Copy> Interpolate for Size2D<T> {
}
}
-impl<T: Interpolate + Copy> Interpolate for Point2D<T> {
+impl<T: Animatable + Copy> Animatable for Point2D<T> {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
let x = try!(self.x.interpolate(&other.x, progress));
@@ -728,15 +825,26 @@ impl<T: Interpolate + Copy> Interpolate for Point2D<T> {
}
}
-impl Interpolate for BorderRadiusSize {
+impl Animatable for BorderRadiusSize {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
self.0.interpolate(&other.0, progress).map(generics::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)))
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-length
-impl Interpolate for VerticalAlign {
+impl Animatable for VerticalAlign {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -749,17 +857,38 @@ impl Interpolate for VerticalAlign {
_ => Err(()),
}
}
+
+ #[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 Interpolate for BackgroundSizeList {
+impl Animatable for BackgroundSizeList {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
self.0.interpolate(&other.0, progress).map(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)
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-color
-impl Interpolate for RGBA {
+impl Animatable for RGBA {
#[inline]
fn interpolate(&self, other: &RGBA, progress: f64) -> Result<Self, ()> {
fn clamp(val: f32) -> f32 {
@@ -783,10 +912,41 @@ impl Interpolate for RGBA {
Ok(RGBA::from_floats(red, green, blue, alpha))
}
}
+
+ /// https://www.w3.org/TR/smil-animation/#animateColorElement says we should use Euclidean
+ /// RGB-cube distance.
+ #[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)
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-color
-impl Interpolate for CSSParserColor {
+impl Animatable for CSSParserColor {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -796,17 +956,32 @@ impl Interpolate for CSSParserColor {
_ => Err(()),
}
}
+
+ #[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),
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
-impl Interpolate for CalcLengthOrPercentage {
+impl Animatable for CalcLengthOrPercentage {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
fn interpolate_half<T>(this: Option<T>,
other: Option<T>,
progress: f64)
-> Result<Option<T>, ()>
- where T: Default + Interpolate,
+ where T: Default + Animatable,
{
match (this, other) {
(None, None) => Ok(None),
@@ -823,10 +998,22 @@ impl Interpolate for CalcLengthOrPercentage {
percentage: try!(interpolate_half(self.percentage, other.percentage, progress)),
})
}
+
+ #[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)
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
-impl Interpolate for LengthOrPercentage {
+impl Animatable for LengthOrPercentage {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -846,10 +1033,52 @@ impl Interpolate 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)
+ }
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
-impl Interpolate for LengthOrPercentageOrAuto {
+impl Animatable for LengthOrPercentageOrAuto {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -874,10 +1103,57 @@ impl Interpolate 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)
+ }
+ }
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
-impl Interpolate for LengthOrPercentageOrNone {
+impl Animatable for LengthOrPercentageOrNone {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -895,10 +1171,25 @@ impl Interpolate for LengthOrPercentageOrNone {
_ => Err(())
}
}
+
+ #[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(())
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
-impl Interpolate for MinLength {
+impl Animatable for MinLength {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -909,10 +1200,21 @@ impl Interpolate for MinLength {
_ => Err(()),
}
}
+
+ #[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(()),
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
-impl Interpolate for MaxLength {
+impl Animatable for MaxLength {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -923,11 +1225,22 @@ impl Interpolate for MaxLength {
_ => Err(()),
}
}
+
+ #[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(()),
+ }
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-number
/// https://drafts.csswg.org/css-transitions/#animtype-length
-impl Interpolate for LineHeight {
+impl Animatable for LineHeight {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
@@ -945,10 +1258,25 @@ impl Interpolate for LineHeight {
_ => Err(()),
}
}
+
+ #[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(()),
+ }
+ }
}
/// http://dev.w3.org/csswg/css-transitions/#animtype-font-weight
-impl Interpolate for FontWeight {
+impl Animatable for FontWeight {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
let a = (*self as u32) as f64;
@@ -974,10 +1302,17 @@ impl Interpolate for FontWeight {
FontWeight::Weight900
})
}
+
+ #[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)
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
-impl<H: Interpolate, V: Interpolate> Interpolate for generic_position::Position<H, V> {
+impl<H: Animatable, V: Animatable> Animatable for generic_position::Position<H, V> {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(generic_position::Position {
@@ -985,33 +1320,64 @@ impl<H: Interpolate, V: Interpolate> Interpolate for generic_position::Position<
vertical: try!(self.vertical.interpolate(&other.vertical, progress)),
})
}
+
+ #[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<H, V> RepeatableListInterpolate for generic_position::Position<H, V>
- where H: RepeatableListInterpolate, V: RepeatableListInterpolate {}
+impl<H, V> RepeatableListAnimatable for generic_position::Position<H, V>
+ where H: RepeatableListAnimatable, V: RepeatableListAnimatable {}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
-impl Interpolate for HorizontalPosition {
+impl Animatable for HorizontalPosition {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
self.0.interpolate(&other.0, progress).map(generic_position::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 RepeatableListInterpolate for HorizontalPosition {}
+impl RepeatableListAnimatable for HorizontalPosition {}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
-impl Interpolate for VerticalPosition {
+impl Animatable for VerticalPosition {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
self.0.interpolate(&other.0, progress).map(generic_position::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 RepeatableListInterpolate for VerticalPosition {}
+impl RepeatableListAnimatable for VerticalPosition {}
/// https://drafts.csswg.org/css-transitions/#animtype-rect
-impl Interpolate for ClipRect {
+impl Animatable for ClipRect {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(ClipRect {
@@ -1021,10 +1387,24 @@ impl Interpolate for ClipRect {
left: try!(self.left.interpolate(&other.left, time)),
})
}
+
+ #[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))
+ }
}
-<%def name="impl_interpolate_for_shadow(item, transparent_color)">
- impl Interpolate for ${item} {
+<%def name="impl_animatable_for_shadow(item, transparent_color)">
+ impl Animatable for ${item} {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
% if "Box" in item:
@@ -1053,10 +1433,33 @@ impl Interpolate for ClipRect {
% endif
})
}
+
+ #[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 "Box" in item:
+ if self.inset != other.inset {
+ return Err(());
+ }
+ % endif
+ 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)),
+ % if "Box" in item:
+ try!(self.spread_radius.compute_distance(&other.spread_radius)),
+ % endif
+ ];
+ Ok(list.iter().fold(0.0f64, |sum, diff| sum + diff * diff))
+ }
}
/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
- impl Interpolate for ${item}List {
+ impl Animatable for ${item}List {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
// The inset value must change
@@ -1109,8 +1512,8 @@ impl Interpolate for ClipRect {
}
</%def>
-${impl_interpolate_for_shadow('BoxShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
-${impl_interpolate_for_shadow('TextShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
+${impl_animatable_for_shadow('BoxShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
+${impl_animatable_for_shadow('TextShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
/// Check if it's possible to do a direct numerical interpolation
/// between these two transform lists.
@@ -1321,7 +1724,7 @@ pub struct MatrixDecomposed2D {
pub matrix: InnerMatrix2D,
}
-impl Interpolate for InnerMatrix2D {
+impl Animatable for InnerMatrix2D {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(InnerMatrix2D {
m11: try!(self.m11.interpolate(&other.m11, progress)),
@@ -1332,7 +1735,7 @@ impl Interpolate for InnerMatrix2D {
}
}
-impl Interpolate for Translate2D {
+impl Animatable for Translate2D {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Translate2D(
try!(self.0.interpolate(&other.0, progress)),
@@ -1341,7 +1744,7 @@ impl Interpolate for Translate2D {
}
}
-impl Interpolate for Scale2D {
+impl Animatable for Scale2D {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Scale2D(
try!(self.0.interpolate(&other.0, progress)),
@@ -1350,7 +1753,7 @@ impl Interpolate for Scale2D {
}
}
-impl Interpolate for MatrixDecomposed2D {
+impl Animatable for MatrixDecomposed2D {
/// https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-2d-matrix-values
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
// If x-axis of one is flipped, and y-axis of the other,
@@ -1396,7 +1799,7 @@ impl Interpolate for MatrixDecomposed2D {
}
}
-impl Interpolate for ComputedMatrix {
+impl Animatable for ComputedMatrix {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
if self.is_3d() || other.is_3d() {
let decomposed_from = decompose_3d_matrix(*self);
@@ -1730,7 +2133,7 @@ fn cross(row1: [f32; 3], row2: [f32; 3]) -> [f32; 3] {
]
}
-impl Interpolate for Translate3D {
+impl Animatable for Translate3D {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Translate3D(
try!(self.0.interpolate(&other.0, progress)),
@@ -1740,7 +2143,7 @@ impl Interpolate for Translate3D {
}
}
-impl Interpolate for Scale3D {
+impl Animatable for Scale3D {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Scale3D(
try!(self.0.interpolate(&other.0, progress)),
@@ -1750,7 +2153,7 @@ impl Interpolate for Scale3D {
}
}
-impl Interpolate for Skew {
+impl Animatable for Skew {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Skew(
try!(self.0.interpolate(&other.0, progress)),
@@ -1760,7 +2163,7 @@ impl Interpolate for Skew {
}
}
-impl Interpolate for Perspective {
+impl Animatable for Perspective {
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(Perspective(
try!(self.0.interpolate(&other.0, progress)),
@@ -1771,7 +2174,7 @@ impl Interpolate for Perspective {
}
}
-impl Interpolate for MatrixDecomposed3D {
+impl Animatable for MatrixDecomposed3D {
/// https://drafts.csswg.org/css-transforms/#interpolation-of-decomposed-3d-matrix-values
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
let mut interpolated = *self;
@@ -2009,7 +2412,7 @@ impl ComputedMatrix {
}
/// https://drafts.csswg.org/css-transforms/#interpolation-of-transforms
-impl Interpolate for TransformList {
+impl Animatable for TransformList {
#[inline]
fn interpolate(&self, other: &TransformList, progress: f64) -> Result<Self, ()> {
// http://dev.w3.org/csswg/css-transforms/#interpolation-of-transforms
@@ -2038,8 +2441,8 @@ impl Interpolate for TransformList {
}
}
-impl<T, U> Interpolate for Either<T, U>
- where T: Interpolate + Copy, U: Interpolate + Copy,
+impl<T, U> Animatable for Either<T, U>
+ where T: Animatable + Copy, U: Animatable + Copy,
{
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
@@ -2056,6 +2459,32 @@ impl<T, U> Interpolate 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> From<<&'a IntermediateRGBA> for RGBA {
@@ -2105,8 +2534,8 @@ impl IntermediateRGBA {
}
}
-/// Unlike Interpolate for RGBA we don't clamp any component values.
-impl Interpolate for IntermediateRGBA {
+/// Unlike Animatable for RGBA we don't clamp any component values.
+impl Animatable for IntermediateRGBA {
#[inline]
fn interpolate(&self, other: &IntermediateRGBA, progress: f64) -> Result<Self, ()> {
let alpha = try!(self.alpha.interpolate(&other.alpha, progress));
@@ -2127,6 +2556,29 @@ impl Interpolate for IntermediateRGBA {
Ok(IntermediateRGBA::new(red, green, blue, alpha))
}
}
+
+ #[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)
+ }
}
impl<'a> From<<&'a Either<CSSParserColor, Auto>> for Either<IntermediateColor, Auto> {
@@ -2166,652 +2618,38 @@ impl<'a> From<<&'a Either<IntermediateColor, Auto>> for Either<CSSParserColor, A
}
}
-
-/// 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_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
- % 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 SmallVec<[T; 1]> {
- #[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 <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 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)
- }
+#[derive(Copy, Clone, Debug, PartialEq)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[allow(missing_docs)]
+pub enum IntermediateColor {
+ CurrentColor,
+ IntermediateRGBA(IntermediateRGBA),
}
-impl ComputeDistance for IntermediateColor {
- #[inline]
- fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
- self.compute_squared_distance(other).map(|sq| sq.sqrt())
- }
-
+impl Animatable for IntermediateColor {
#[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
+ fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
match (*self, *other) {
(IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(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)
- }
+ this.interpolate(other, progress).map(IntermediateColor::IntermediateRGBA)
}
- }
- }
-}
-
-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 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)
- },
+ // FIXME: Bug 1345709: Implement currentColor animations.
_ => 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)
+ self.compute_squared_distance(other).map(|sq| sq.sqrt())
}
#[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<H, V> ComputeDistance for generic_position::Position<H, V>
- where H: ComputeDistance, V: ComputeDistance
-{
- #[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 IntermediateTextShadow {
- #[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 IntermediateTextShadowList {
- #[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 = IntermediateTextShadow {
- offset_x: Au(0),
- offset_y: Au(0),
- blur_radius: Au(0),
- color: IntermediateColor::IntermediateRGBA(IntermediateRGBA::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 IntermediateBoxShadow {
- #[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 IntermediateBoxShadowList {
- #[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 = IntermediateBoxShadow {
- offset_x: Au(0),
- offset_y: Au(0),
- spread_radius: Au(0),
- blur_radius: Au(0),
- color: IntermediateColor::IntermediateRGBA(IntermediateRGBA::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)) => {
+ (IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(ref other)) => {
this.compute_squared_distance(other)
},
- _ => Err(())
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[allow(missing_docs)]
-pub enum IntermediateColor {
- CurrentColor,
- IntermediateRGBA(IntermediateRGBA),
-}
-
-impl Interpolate for IntermediateColor {
- #[inline]
- fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
- match (*self, *other) {
- (IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(ref other)) => {
- this.interpolate(other, progress).map(IntermediateColor::IntermediateRGBA)
- }
- // FIXME: Bug 1345709: Implement currentColor animations.
- _ => Err(()),
+ _ => Ok(0.0),
}
}
}
@@ -2907,8 +2745,8 @@ impl <'a> From<<&'a IntermediateColor> for CSSParserColor {
}
}
}
- ${impl_interpolate_for_shadow('Intermediate%sShadow' % type,
- 'IntermediateColor::IntermediateRGBA(IntermediateRGBA::transparent())')}
+ ${impl_animatable_for_shadow('Intermediate%sShadow' % type,
+ 'IntermediateColor::IntermediateRGBA(IntermediateRGBA::transparent())')}
</%def>
${impl_intermediate_type_for_shadow('Box')}
diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs
index 3689ea61c02..50e2ce4e9bd 100644
--- a/components/style/properties/longhand/background.mako.rs
+++ b/components/style/properties/longhand/background.mako.rs
@@ -195,7 +195,7 @@ ${helpers.single_keyword("background-origin",
#[allow(missing_docs)]
pub mod computed_value {
use values::computed::LengthOrPercentageOrAuto;
- use properties::animated_properties::{ComputeDistance, Interpolate, RepeatableListInterpolate};
+ use properties::animated_properties::{Animatable, RepeatableListAnimatable};
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -212,9 +212,9 @@ ${helpers.single_keyword("background-origin",
Contain,
}
- impl RepeatableListInterpolate for T {}
+ impl RepeatableListAnimatable for T {}
- impl Interpolate for T {
+ impl Animatable for T {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
use properties::longhands::background_size::single_value::computed_value::ExplicitSize;
match (self, other) {
@@ -227,9 +227,7 @@ ${helpers.single_keyword("background-origin",
_ => Err(()),
}
}
- }
- impl ComputeDistance for T {
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt())
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index ca8549dc10c..b9a451b1571 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -2181,7 +2181,7 @@ ${helpers.single_keyword("transform-style",
use values::specified::{NoCalcLength, LengthOrPercentage, Percentage};
pub mod computed_value {
- use properties::animated_properties::{ComputeDistance, Interpolate};
+ use properties::animated_properties::Animatable;
use values::computed::{Length, LengthOrPercentage};
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -2192,7 +2192,7 @@ ${helpers.single_keyword("transform-style",
pub depth: Length,
}
- impl Interpolate for T {
+ impl Animatable for T {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(T {
@@ -2201,9 +2201,7 @@ ${helpers.single_keyword("transform-style",
depth: try!(self.depth.interpolate(&other.depth, time)),
})
}
- }
- impl ComputeDistance for T {
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt())
diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs
index 603e100a4e2..f83757fb5e8 100644
--- a/components/style/properties/longhand/font.mako.rs
+++ b/components/style/properties/longhand/font.mako.rs
@@ -1022,7 +1022,7 @@ ${helpers.single_keyword_system("font-variant-caps",
}
pub mod computed_value {
- use properties::animated_properties::{ComputeDistance, Interpolate};
+ use properties::animated_properties::Animatable;
use std::fmt;
use style_traits::ToCss;
use values::CSSFloat;
@@ -1054,7 +1054,7 @@ ${helpers.single_keyword_system("font-variant-caps",
}
}
- impl Interpolate for T {
+ impl Animatable for T {
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
match (*self, *other) {
(T::Number(ref number), T::Number(ref other)) =>
@@ -1062,9 +1062,7 @@ ${helpers.single_keyword_system("font-variant-caps",
_ => Err(()),
}
}
- }
- impl ComputeDistance for T {
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (*self, *other) {
diff --git a/components/style/properties/longhand/inherited_table.mako.rs b/components/style/properties/longhand/inherited_table.mako.rs
index 5caaa17195d..aba56b125a2 100644
--- a/components/style/properties/longhand/inherited_table.mako.rs
+++ b/components/style/properties/longhand/inherited_table.mako.rs
@@ -30,7 +30,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
pub mod computed_value {
use app_units::Au;
- use properties::animated_properties::{ComputeDistance, Interpolate};
+ use properties::animated_properties::Animatable;
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -40,7 +40,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
}
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
- impl Interpolate for T {
+ impl Animatable for T {
#[inline]
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
Ok(T {
@@ -48,9 +48,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
vertical: try!(self.vertical.interpolate(&other.vertical, time)),
})
}
- }
- impl ComputeDistance for T {
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt())
diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs
index 644c9979ac1..b2d57a72393 100644
--- a/components/style/properties/longhand/inherited_text.mako.rs
+++ b/components/style/properties/longhand/inherited_text.mako.rs
@@ -441,14 +441,13 @@ ${helpers.single_keyword("text-align-last",
pub mod computed_value {
use app_units::Au;
- use properties::animated_properties::{ComputeDistance, Interpolate};
+ use properties::animated_properties::Animatable;
#[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)')}
+ ${helpers.impl_animatable_for_option_tuple('Au(0)')}
}
impl ToCss for computed_value::T {
@@ -527,14 +526,13 @@ ${helpers.single_keyword("text-align-last",
}
pub mod computed_value {
- use properties::animated_properties::{ComputeDistance, Interpolate};
+ use properties::animated_properties::Animatable;
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()')}
+ ${helpers.impl_animatable_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 500c8cc1460..104929fff77 100644
--- a/components/style/properties/longhand/svg.mako.rs
+++ b/components/style/properties/longhand/svg.mako.rs
@@ -99,24 +99,17 @@ ${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::{ComputeDistance, Interpolate, RepeatableListInterpolate};
+ use properties::animated_properties::{Animatable, RepeatableListAnimatable};
use properties::longhands::mask_position_x::computed_value::T as MaskPositionX;
- impl Interpolate for MaskPositionX {
+ impl Animatable for MaskPositionX {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(MaskPositionX(try!(self.0.interpolate(&other.0, progress))))
}
}
- impl RepeatableListInterpolate for MaskPositionX {}
-
- impl ComputeDistance for MaskPositionX {
- #[inline]
- fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
- Err(())
- }
- }
+ impl RepeatableListAnimatable for MaskPositionX {}
</%helpers:vector_longhand>
<%helpers:vector_longhand name="mask-position-y" products="gecko"
@@ -128,24 +121,17 @@ ${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::{ComputeDistance, Interpolate, RepeatableListInterpolate};
+ use properties::animated_properties::{Animatable, RepeatableListAnimatable};
use properties::longhands::mask_position_y::computed_value::T as MaskPositionY;
- impl Interpolate for MaskPositionY {
+ impl Animatable for MaskPositionY {
#[inline]
fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
Ok(MaskPositionY(try!(self.0.interpolate(&other.0, progress))))
}
}
- impl RepeatableListInterpolate for MaskPositionY {}
-
- impl ComputeDistance for MaskPositionY {
- #[inline]
- fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
- Err(())
- }
- }
+ impl RepeatableListAnimatable for MaskPositionY {}
</%helpers:vector_longhand>
${helpers.single_keyword("mask-clip",
diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs
index 01a774d138e..17db73c4ebc 100644
--- a/components/style/values/mod.rs
+++ b/components/style/values/mod.rs
@@ -11,7 +11,7 @@
use Atom;
pub use cssparser::{RGBA, Token, Parser, serialize_identifier, serialize_string};
use parser::{Parse, ParserContext};
-use properties::animated_properties::{ComputeDistance, Interpolate};
+use properties::animated_properties::Animatable;
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::fmt::{self, Debug};
@@ -127,20 +127,13 @@ macro_rules! define_keyword_type {
}
}
- impl Interpolate for $name {
+ impl Animatable for $name {
#[inline]
fn interpolate(&self, _other: &Self, _progress: f64) -> Result<Self, ()> {
Ok($name)
}
}
- impl ComputeDistance for $name {
- #[inline]
- fn compute_distance(&self, _other: &Self) -> Result<f64, ()> {
- Err(())
- }
- }
-
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, $css)
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index 4601d31f683..3de322d9d98 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -75,7 +75,7 @@ use style::parser::{LengthParsingMode, ParserContext};
use style::properties::{CascadeFlags, ComputedValues, Importance, ParsedDeclaration, StyleBuilder};
use style::properties::{PropertyDeclarationBlock, PropertyId};
use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
-use style::properties::animated_properties::{AnimationValue, ComputeDistance, Interpolate, TransitionProperty};
+use style::properties::animated_properties::{Animatable, AnimationValue, TransitionProperty};
use style::properties::parse_one_declaration;
use style::restyle_hints::{self, RestyleHint};
use style::rule_tree::{StrongRuleNode, StyleSource};
diff --git a/tests/unit/style/animated_properties.rs b/tests/unit/style/animated_properties.rs
index e486f0f1474..853c2c24ae6 100644
--- a/tests/unit/style/animated_properties.rs
+++ b/tests/unit/style/animated_properties.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::{Color, RGBA};
-use style::properties::animated_properties::Interpolate;
+use style::properties::animated_properties::Animatable;
#[test]
fn test_rgba_color_interepolation_preserves_transparent() {