Clean up filter animations

This commit is contained in:
Anthony Ramine 2017-08-21 11:10:44 +02:00
parent baf3597477
commit 54dc3e1670
2 changed files with 86 additions and 101 deletions

View file

@ -2959,37 +2959,28 @@ impl<OpacityType> ToAnimatedZero for SVGOpacity<OpacityType>
%> %>
/// https://drafts.fxtf.org/filters/#animation-of-filters /// https://drafts.fxtf.org/filters/#animation-of-filters
fn add_weighted_filter_function_impl(from: &AnimatedFilter, impl Animatable for AnimatedFilter {
to: &AnimatedFilter, fn add_weighted(
&self,
other: &Self,
self_portion: f64, self_portion: f64,
other_portion: f64) other_portion: f64,
-> Result<AnimatedFilter, ()> { ) -> Result<Self, ()> {
match (from, to) { match (self, other) {
% for func in [ 'Blur', 'HueRotate' ]: % for func in ['Blur', 'Grayscale', 'HueRotate', 'Invert', 'Sepia']:
(&Filter::${func}(from_value), &Filter::${func}(to_value)) => { (&Filter::${func}(ref this), &Filter::${func}(ref other)) => {
Ok(Filter::${func}(from_value.add_weighted( Ok(Filter::${func}(this.add_weighted(
&to_value, other,
self_portion, self_portion,
other_portion, other_portion,
)?)) )?))
}, },
% endfor % endfor
% for func in [ 'Grayscale', 'Invert', 'Sepia' ]:
(&Filter::${func}(from_value), &Filter::${func}(to_value)) => {
Ok(Filter::${func}(add_weighted_with_initial_val(
&from_value,
&to_value,
self_portion,
other_portion,
&NonNegative::<CSSFloat>(0.0),
)?))
},
% endfor
% for func in ['Brightness', 'Contrast', 'Opacity', 'Saturate']: % for func in ['Brightness', 'Contrast', 'Opacity', 'Saturate']:
(&Filter::${func}(from_value), &Filter::${func}(to_value)) => { (&Filter::${func}(ref this), &Filter::${func}(ref other)) => {
Ok(Filter::${func}(add_weighted_with_initial_val( Ok(Filter::${func}(add_weighted_with_initial_val(
&from_value, this,
&to_value, other,
self_portion, self_portion,
other_portion, other_portion,
&NonNegative::<CSSFloat>(1.0), &NonNegative::<CSSFloat>(1.0),
@ -2997,87 +2988,78 @@ fn add_weighted_filter_function_impl(from: &AnimatedFilter,
}, },
% endfor % endfor
% if product == "gecko": % if product == "gecko":
(&Filter::DropShadow(ref from_value), &Filter::DropShadow(ref to_value)) => { (&Filter::DropShadow(ref this), &Filter::DropShadow(ref other)) => {
Ok(Filter::DropShadow(from_value.add_weighted( Ok(Filter::DropShadow(this.add_weighted(
&to_value, other,
self_portion, self_portion,
other_portion, other_portion,
)?)) )?))
}, },
(&Filter::Url(_), &Filter::Url(_)) => {
Err(())
},
% endif % endif
_ => { _ => Err(()),
// If specified the different filter functions, }
// we will need to interpolate as discreate.
Err(())
},
} }
} }
/// https://drafts.fxtf.org/filters/#animation-of-filters
fn add_weighted_filter_function(from: Option<<&AnimatedFilter>, impl ToAnimatedZero for AnimatedFilter {
to: Option<<&AnimatedFilter>, fn to_animated_zero(&self) -> Result<Self, ()> {
self_portion: f64, match *self {
other_portion: f64) -> Result<AnimatedFilter, ()> { % for func in ['Blur', 'Grayscale', 'HueRotate', 'Invert', 'Sepia']:
match (from, to) { Filter::${func}(ref this) => Ok(Filter::${func}(this.to_animated_zero()?)),
(Some(f), Some(t)) => { % endfor
add_weighted_filter_function_impl(f, t, self_portion, other_portion) % for func in ['Brightness', 'Contrast', 'Opacity', 'Saturate']:
}, Filter::${func}(_) => Ok(Filter::${func}(NonNegative(1.))),
(Some(f), None) => { % endfor
add_weighted_filter_function_impl(f, f, self_portion, 0.0) % if product == "gecko":
}, Filter::DropShadow(ref this) => Ok(Filter::DropShadow(this.to_animated_zero()?)),
(None, Some(t)) => { % endif
add_weighted_filter_function_impl(t, t, other_portion, 0.0) _ => Err(()),
}, }
_ => { Err(()) }
} }
} }
fn compute_filter_square_distance(from: &AnimatedFilter, to: &AnimatedFilter) -> Result<SquaredDistance, ()> {
match (from, to) { // FIXME(nox): This should be derived.
impl ComputeSquaredDistance for AnimatedFilter {
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self, other) {
% for func in FILTER_FUNCTIONS: % for func in FILTER_FUNCTIONS:
(&Filter::${func}(f), (&Filter::${func}(ref this), &Filter::${func}(ref other)) => {
&Filter::${func}(t)) => { this.compute_squared_distance(other)
Ok(try!(f.compute_squared_distance(&t)))
}, },
% endfor % endfor
% if product == "gecko": % if product == "gecko":
(&Filter::DropShadow(ref f), &Filter::DropShadow(ref t)) => { (&Filter::DropShadow(ref this), &Filter::DropShadow(ref other)) => {
Ok(try!(f.compute_squared_distance(&t))) this.compute_squared_distance(other)
}, },
% endif % endif
_ => { _ => Err(()),
Err(())
} }
} }
} }
impl Animatable for AnimatedFilterList { impl Animatable for AnimatedFilterList {
#[inline] #[inline]
fn add_weighted(&self, other: &Self, fn add_weighted(
self_portion: f64, other_portion: f64) -> Result<Self, ()> { &self,
let mut filters = vec![]; other: &Self,
let mut from_iter = self.0.iter(); self_portion: f64,
let mut to_iter = other.0.iter(); other_portion: f64,
) -> Result<Self, ()> {
let mut from = from_iter.next(); Ok(AnimatedFilterList(self.0.iter().zip_longest(other.0.iter()).map(|it| {
let mut to = to_iter.next(); match it {
while from.is_some() || to.is_some() { EitherOrBoth::Both(this, other) => {
filters.push(try!(add_weighted_filter_function(from, this.add_weighted(other, self_portion, other_portion)
to, },
self_portion, EitherOrBoth::Left(this) => {
other_portion))); this.add_weighted(&this.to_animated_zero()?, self_portion, other_portion)
if from.is_some() { },
from = from_iter.next(); EitherOrBoth::Right(other) => {
other.to_animated_zero()?.add_weighted(other, self_portion, other_portion)
},
} }
if to.is_some() { }).collect::<Result<Vec<_>, _>>()?))
to = to_iter.next();
}
}
Ok(AnimatedFilterList(filters))
} }
fn add(&self, other: &Self) -> Result<Self, ()> { fn add(&self, other: &Self) -> Result<Self, ()> {
@ -3090,12 +3072,11 @@ impl ComputeSquaredDistance for AnimatedFilterList {
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
self.0.iter().zip_longest(other.0.iter()).map(|it| { self.0.iter().zip_longest(other.0.iter()).map(|it| {
match it { match it {
EitherOrBoth::Both(from, to) => { EitherOrBoth::Both(this, other) => {
compute_filter_square_distance(&from, &to) this.compute_squared_distance(other)
}, },
EitherOrBoth::Left(list) | EitherOrBoth::Right(list) => { EitherOrBoth::Left(list) | EitherOrBoth::Right(list) => {
let none = add_weighted_filter_function(Some(list), Some(list), 0.0, 0.0)?; list.to_animated_zero()?.compute_squared_distance(list)
compute_filter_square_distance(&none, &list)
}, },
} }
}).sum() }).sum()

View file

@ -245,7 +245,11 @@ impl ToAnimatedZero for SimpleShadow {
#[inline] #[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(SimpleShadow { Ok(SimpleShadow {
color: Some(RGBA::transparent()), color: if let Some(color) = self.color.as_ref() {
Some(color.to_animated_zero()?)
} else {
None
},
horizontal: self.horizontal.to_animated_zero()?, horizontal: self.horizontal.to_animated_zero()?,
vertical: self.vertical.to_animated_zero()?, vertical: self.vertical.to_animated_zero()?,
blur: self.blur.to_animated_zero()?, blur: self.blur.to_animated_zero()?,