--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -113,16 +113,20 @@
% if delegate_animate:
use properties::animated_properties::Animatable;
impl Animatable for 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(T)
}
+ 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)
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -603,16 +603,40 @@ impl Animatable for AnimationValue {
% endfor
_ => {
panic!("Expected weighted addition of computed values of the same \
property, got: {:?}, {:?}", self, other);
}
}
}
+ fn add(&self, other: &Self) -> Result<Self, ()> {
+ match (self, other) {
+ % for prop in data.longhands:
+ % if prop.animatable:
+ % if prop.animation_value_type == "discrete":
+ (&AnimationValue::${prop.camel_case}(_),
+ &AnimationValue::${prop.camel_case}(_)) => {
+ Err(())
+ }
+ % else:
+ (&AnimationValue::${prop.camel_case}(ref from),
+ &AnimationValue::${prop.camel_case}(ref to)) => {
+ from.add(to).map(AnimationValue::${prop.camel_case})
+ }
+ % endif
+ % endif
+ % endfor
+ _ => {
+ panic!("Expected weighted addition of computed values of the same \
+ property, got: {:?}, {:?}", self, other);
+ }
+ }
+ }
+
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)
@@ -643,16 +667,23 @@ 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, ()> {
self.add_weighted(other, 1.0 - progress, progress)
}
+ /// Returns the [sum][animation-addition] of this value and |other|.
+ ///
+ /// [animation-addition]: https://w3c.github.io/web-animations/#animation-addition
+ fn add(&self, other: &Self) -> Result<Self, ()> {
+ self.add_weighted(other, 1.0, 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)
@@ -786,26 +817,22 @@ impl Animatable for Angle {
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-visibility
impl Animatable for Visibility {
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
match (*self, *other) {
- (Visibility::visible, _) | (_, Visibility::visible) => {
- Ok(if self_portion >= 0.0 && self_portion <= 1.0 &&
- other_portion >= 0.0 && other_portion <= 1.0 {
- Visibility::visible
- } else if self_portion > other_portion {
- *self
- } else {
- *other
- })
- }
+ (Visibility::visible, _) => {
+ Ok(if self_portion > 0.0 { *self } else { *other })
+ },
+ (_, Visibility::visible) => {
+ Ok(if other_portion > 0.0 { *other } else { *self })
+ },
_ => Err(()),
}
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
if *self == *other {
Ok(0.0)
@@ -1493,16 +1520,31 @@ impl Animatable for ClipRect {
}
(None, None) => unreachable!(),
};
result.push(shadow);
}
Ok(${item}List(result))
}
+
+ fn add(&self, other: &Self) -> Result<Self, ()> {
+ let len = self.0.len() + other.0.len();
+
+ let mut result = if len > 1 {
+ SmallVec::from_vec(Vec::with_capacity(len))
+ } else {
+ SmallVec::new()
+ };
+
+ result.extend(self.0.iter().cloned());
+ result.extend(other.0.iter().cloned());
+
+ Ok(${item}List(result))
+ }
}
</%def>
${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.
@@ -2434,16 +2476,33 @@ impl Animatable for TransformList {
_ => {
// http://dev.w3.org/csswg/css-transforms/#none-none-animation
TransformList(None)
}
};
Ok(result)
}
+
+ fn add(&self, other: &Self) -> Result<Self, ()> {
+ match (&self.0, &other.0) {
+ (&Some(ref from_list), &Some(ref to_list)) => {
+ Ok(TransformList(Some([&from_list[..], &to_list[..]].concat())))
+ }
+ (&Some(_), &None) => {
+ Ok(self.clone())
+ }
+ (&None, &Some(_)) => {
+ Ok(other.clone())
+ }
+ _ => {
+ Ok(TransformList(None))
+ }
+ }
+ }
}
impl<T, U> Animatable for Either<T, U>
where T: Animatable + Copy, U: Animatable + Copy,
{
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
match (*self, *other) {