mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 14:25:52 +00:00
servo: Merge #18134 - Introduce values::animated::Animate (from servo:we-are-leaving-babylon); r=emilio
Source-Repo: https://github.com/servo/servo Source-Revision: 8ca9542de6838fc485e9e41013d84b396ff216a9 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 781cac1c82939307d62e6a53903845a7176f63dd
This commit is contained in:
parent
1b3b415680
commit
cc0adff3ff
@ -1410,15 +1410,15 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||
})
|
||||
}
|
||||
|
||||
fn needs_transitions_update_per_property(&self,
|
||||
property: &TransitionProperty,
|
||||
combined_duration: f32,
|
||||
before_change_style: &ComputedValues,
|
||||
after_change_style: &ComputedValues,
|
||||
existing_transitions: &HashMap<TransitionProperty,
|
||||
Arc<AnimationValue>>)
|
||||
-> bool {
|
||||
use properties::animated_properties::Animatable;
|
||||
fn needs_transitions_update_per_property(
|
||||
&self,
|
||||
property: &TransitionProperty,
|
||||
combined_duration: f32,
|
||||
before_change_style: &ComputedValues,
|
||||
after_change_style: &ComputedValues,
|
||||
existing_transitions: &HashMap<TransitionProperty, Arc<AnimationValue>>,
|
||||
) -> bool {
|
||||
use values::animated::{Animate, Procedure};
|
||||
|
||||
// |property| should be an animatable longhand
|
||||
let animatable_longhand = AnimatableLonghand::from_transition_property(property).unwrap();
|
||||
@ -1440,7 +1440,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||
|
||||
combined_duration > 0.0f32 &&
|
||||
from != to &&
|
||||
from.interpolate(&to, 0.5).is_ok()
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).is_ok()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -87,10 +87,13 @@ macro_rules! define_keyword_type {
|
||||
#[derive(Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)]
|
||||
pub struct $name;
|
||||
|
||||
impl $crate::properties::animated_properties::Animatable for $name {
|
||||
impl $crate::values::animated::Animate for $name {
|
||||
#[inline]
|
||||
fn add_weighted(&self, _other: &Self, _self_progress: f64, _other_progress: f64)
|
||||
-> Result<Self, ()> {
|
||||
fn animate(
|
||||
&self,
|
||||
_other: &Self,
|
||||
_procedure: $crate::values::animated::Procedure,
|
||||
) -> Result<Self, ()> {
|
||||
Ok($name)
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ class Longhand(object):
|
||||
self.animatable = False
|
||||
self.transitionable = False
|
||||
self.animation_type = None
|
||||
# NB: Animatable implies clone because a property animation requires a
|
||||
# NB: Animate implies clone because a property animation requires a
|
||||
# copy of the computed value.
|
||||
#
|
||||
# See components/style/helpers/animated_properties.mako.rs.
|
||||
|
@ -133,17 +133,12 @@
|
||||
);
|
||||
|
||||
% if need_animatable or animation_value_type == "ComputedValue":
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
|
||||
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)
|
||||
impl Animate for T {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(T(self.0.animate(&other.0, procedure)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1115,9 +1115,8 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::CSSFloat;
|
||||
use values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
@ -1137,12 +1136,12 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||
}
|
||||
}
|
||||
|
||||
impl Animatable for T {
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
|
||||
-> Result<Self, ()> {
|
||||
match (*self, *other) {
|
||||
(T::Number(ref number), T::Number(ref other)) =>
|
||||
Ok(T::Number(number.add_weighted(other, self_portion, other_portion)?)),
|
||||
impl Animate for T {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(&T::Number(ref number), &T::Number(ref other)) => {
|
||||
Ok(T::Number(number.animate(other, procedure)?))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||
use values::specified::length::NonNegativeLength;
|
||||
|
||||
pub mod computed_value {
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use values::computed::NonNegativeAu;
|
||||
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
@ -38,15 +37,12 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-simple-list
|
||||
impl Animatable for T {
|
||||
impl Animate for T {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
|
||||
-> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(T {
|
||||
horizontal: self.horizontal.add_weighted(&other.horizontal,
|
||||
self_portion, other_portion)?,
|
||||
vertical: self.vertical.add_weighted(&other.vertical,
|
||||
self_portion, other_portion)?,
|
||||
horizontal: self.horizontal.animate(&other.horizontal, procedure)?,
|
||||
vertical: self.vertical.animate(&other.vertical, procedure)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
//! Animated types for CSS colors.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
|
||||
/// An animated RGBA color.
|
||||
@ -39,13 +38,13 @@ impl RGBA {
|
||||
}
|
||||
}
|
||||
|
||||
/// Unlike Animatable for computed colors, we don't clamp any component values.
|
||||
/// Unlike Animate for computed colors, we don't clamp any component values.
|
||||
///
|
||||
/// FIXME(nox): Why do computed colors even implement Animatable?
|
||||
impl Animatable for RGBA {
|
||||
/// FIXME(nox): Why do computed colors even implement Animate?
|
||||
impl Animate for RGBA {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
let mut alpha = self.alpha.add_weighted(&other.alpha, self_portion, other_portion)?;
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
let mut alpha = self.alpha.animate(&other.alpha, procedure)?;
|
||||
if alpha <= 0. {
|
||||
// Ideally we should return color value that only alpha component is
|
||||
// 0, but this is what current gecko does.
|
||||
@ -53,15 +52,9 @@ impl Animatable for RGBA {
|
||||
}
|
||||
|
||||
alpha = alpha.min(1.);
|
||||
let red = (self.red * self.alpha).add_weighted(
|
||||
&(other.red * other.alpha), self_portion, other_portion
|
||||
)? * 1. / alpha;
|
||||
let green = (self.green * self.alpha).add_weighted(
|
||||
&(other.green * other.alpha), self_portion, other_portion
|
||||
)? * 1. / alpha;
|
||||
let blue = (self.blue * self.alpha).add_weighted(
|
||||
&(other.blue * other.alpha), self_portion, other_portion
|
||||
)? * 1. / alpha;
|
||||
let red = (self.red * self.alpha).animate(&(other.red * other.alpha), procedure)? * 1. / alpha;
|
||||
let green = (self.green * self.alpha).animate(&(other.green * other.alpha), procedure)? * 1. / alpha;
|
||||
let blue = (self.blue * self.alpha).animate(&(other.blue * other.alpha), procedure)? * 1. / alpha;
|
||||
|
||||
Ok(RGBA::new(red, green, blue, alpha))
|
||||
}
|
||||
@ -123,9 +116,9 @@ impl Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl Animatable for Color {
|
||||
impl Animate for Color {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
// Common cases are interpolating between two numeric colors,
|
||||
// two currentcolors, and a numeric color and a currentcolor.
|
||||
//
|
||||
@ -133,35 +126,35 @@ impl Animatable for Color {
|
||||
// equals to one, so it may be broken for additive operation.
|
||||
// To properly support additive color interpolation, we would
|
||||
// need two ratio fields in computed color types.
|
||||
let (this_weight, other_weight) = procedure.weights();
|
||||
if self.foreground_ratio == other.foreground_ratio {
|
||||
if self.is_currentcolor() {
|
||||
Ok(Color::currentcolor())
|
||||
} else {
|
||||
Ok(Color {
|
||||
color: self.color.add_weighted(&other.color, self_portion, other_portion)?,
|
||||
color: self.color.animate(&other.color, procedure)?,
|
||||
foreground_ratio: self.foreground_ratio,
|
||||
})
|
||||
}
|
||||
} else if self.is_currentcolor() && other.is_numeric() {
|
||||
Ok(Color {
|
||||
color: other.color,
|
||||
foreground_ratio: self_portion as f32,
|
||||
foreground_ratio: this_weight as f32,
|
||||
})
|
||||
} else if self.is_numeric() && other.is_currentcolor() {
|
||||
Ok(Color {
|
||||
color: self.color,
|
||||
foreground_ratio: other_portion as f32,
|
||||
foreground_ratio: other_weight as f32,
|
||||
})
|
||||
} else {
|
||||
// For interpolating between two complex colors, we need to
|
||||
// generate colors with effective alpha value.
|
||||
let self_color = self.effective_intermediate_rgba();
|
||||
let other_color = other.effective_intermediate_rgba();
|
||||
let color = self_color.add_weighted(&other_color, self_portion, other_portion)?;
|
||||
let color = self_color.animate(&other_color, procedure)?;
|
||||
// Then we compute the final foreground ratio, and derive
|
||||
// the final alpha value from the effective alpha value.
|
||||
let foreground_ratio = self.foreground_ratio
|
||||
.add_weighted(&other.foreground_ratio, self_portion, other_portion)?;
|
||||
let foreground_ratio = self.foreground_ratio.animate(&other.foreground_ratio, procedure)?;
|
||||
let alpha = color.alpha / (1. - foreground_ratio);
|
||||
Ok(Color {
|
||||
color: RGBA {
|
||||
@ -177,7 +170,7 @@ impl Animatable for Color {
|
||||
impl ComputeSquaredDistance for Color {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
// All comments in add_weighted also applies here.
|
||||
// All comments from the Animate impl also applies here.
|
||||
if self.foreground_ratio == other.foreground_ratio {
|
||||
if self.is_currentcolor() {
|
||||
Ok(SquaredDistance::Value(0.))
|
||||
|
@ -4,14 +4,13 @@
|
||||
|
||||
//! Animated types for CSS values related to effects.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use properties::longhands::box_shadow::computed_value::T as ComputedBoxShadowList;
|
||||
use properties::longhands::filter::computed_value::T as ComputedFilterList;
|
||||
use properties::longhands::text_shadow::computed_value::T as ComputedTextShadowList;
|
||||
use std::cmp;
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
use values::Impossible;
|
||||
use values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use values::animated::color::RGBA;
|
||||
use values::computed::{Angle, NonNegativeNumber};
|
||||
use values::computed::length::{Length, NonNegativeLength};
|
||||
@ -66,42 +65,36 @@ impl ToAnimatedValue for ComputedBoxShadowList {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Animatable for ShadowList<S>
|
||||
impl<S> Animate for ShadowList<S>
|
||||
where
|
||||
S: Animatable + Clone + ToAnimatedZero,
|
||||
S: Animate + Clone + ToAnimatedZero,
|
||||
{
|
||||
#[inline]
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
if procedure == Procedure::Add {
|
||||
return Ok(ShadowList(
|
||||
self.0.iter().chain(&other.0).cloned().collect(),
|
||||
));
|
||||
}
|
||||
// FIXME(nox): Use itertools here, to avoid the need for `unreachable!`.
|
||||
let max_len = cmp::max(self.0.len(), other.0.len());
|
||||
let mut shadows = Vec::with_capacity(max_len);
|
||||
for i in 0..max_len {
|
||||
shadows.push(match (self.0.get(i), other.0.get(i)) {
|
||||
(Some(shadow), Some(other)) => {
|
||||
shadow.add_weighted(other, self_portion, other_portion)?
|
||||
shadow.animate(other, procedure)?
|
||||
},
|
||||
(Some(shadow), None) => {
|
||||
shadow.add_weighted(&shadow.to_animated_zero()?, self_portion, other_portion)?
|
||||
shadow.animate(&shadow.to_animated_zero()?, procedure)?
|
||||
},
|
||||
(None, Some(shadow)) => {
|
||||
shadow.to_animated_zero()?.add_weighted(&shadow, self_portion, other_portion)?
|
||||
shadow.to_animated_zero()?.animate(shadow, procedure)?
|
||||
},
|
||||
(None, None) => unreachable!(),
|
||||
});
|
||||
}
|
||||
Ok(ShadowList(shadows))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add(&self, other: &Self) -> Result<Self, ()> {
|
||||
Ok(ShadowList(
|
||||
self.0.iter().cloned().chain(other.0.iter().cloned()).collect(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> ComputeSquaredDistance for ShadowList<S>
|
||||
@ -146,20 +139,15 @@ impl ToAnimatedValue for ComputedTextShadowList {
|
||||
}
|
||||
}
|
||||
|
||||
impl Animatable for BoxShadow {
|
||||
impl Animate for BoxShadow {
|
||||
#[inline]
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
if self.inset != other.inset {
|
||||
return Err(());
|
||||
}
|
||||
Ok(BoxShadow {
|
||||
base: self.base.add_weighted(&other.base, self_portion, other_portion)?,
|
||||
spread: self.spread.add_weighted(&other.spread, self_portion, other_portion)?,
|
||||
base: self.base.animate(&other.base, procedure)?,
|
||||
spread: self.spread.animate(&other.spread, procedure)?,
|
||||
inset: self.inset,
|
||||
})
|
||||
}
|
||||
@ -224,19 +212,14 @@ impl ToAnimatedZero for FilterList {
|
||||
}
|
||||
}
|
||||
|
||||
impl Animatable for SimpleShadow {
|
||||
impl Animate for SimpleShadow {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
let color = self.color.add_weighted(&other.color, self_portion, other_portion)?;
|
||||
let horizontal = self.horizontal.add_weighted(&other.horizontal, self_portion, other_portion)?;
|
||||
let vertical = self.vertical.add_weighted(&other.vertical, self_portion, other_portion)?;
|
||||
let blur = self.blur.add_weighted(&other.blur, self_portion, other_portion)?;
|
||||
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(SimpleShadow {
|
||||
color: color,
|
||||
horizontal: horizontal,
|
||||
vertical: vertical,
|
||||
blur: blur,
|
||||
color: self.color.animate(&other.color, procedure)?,
|
||||
horizontal: self.horizontal.animate(&other.horizontal, procedure)?,
|
||||
vertical: self.vertical.animate(&other.vertical, procedure)?,
|
||||
blur: self.blur.animate(&other.blur, procedure)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -245,7 +228,7 @@ impl ToAnimatedZero for SimpleShadow {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
Ok(SimpleShadow {
|
||||
color: Some(RGBA::transparent()),
|
||||
color: self.color.to_animated_zero()?,
|
||||
horizontal: self.horizontal.to_animated_zero()?,
|
||||
vertical: self.vertical.to_animated_zero()?,
|
||||
blur: self.blur.to_animated_zero()?,
|
||||
|
@ -9,6 +9,7 @@
|
||||
//! module's raison d'être is to ultimately contain all these types.
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::{Point2D, Size2D};
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp::max;
|
||||
use values::computed::Angle as ComputedAngle;
|
||||
@ -27,6 +28,26 @@ use values::specified::url::SpecifiedUrl;
|
||||
pub mod color;
|
||||
pub mod effects;
|
||||
|
||||
/// Animating from one value to another.
|
||||
pub trait Animate: Sized {
|
||||
/// Animate a value towards another one, given an animation procedure.
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()>;
|
||||
}
|
||||
|
||||
/// An animation procedure.
|
||||
///
|
||||
/// https://w3c.github.io/web-animations/#procedures-for-animating-properties
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Procedure {
|
||||
/// https://w3c.github.io/web-animations/#animation-interpolation
|
||||
Interpolate { progress: f64 },
|
||||
/// https://w3c.github.io/web-animations/#animation-addition
|
||||
Add,
|
||||
/// https://w3c.github.io/web-animations/#animation-accumulation
|
||||
Accumulate { count: u64 },
|
||||
}
|
||||
|
||||
/// Conversion between computed values and intermediate values for animations.
|
||||
///
|
||||
/// Notably, colors are represented as four floats during animations.
|
||||
@ -41,6 +62,108 @@ pub trait ToAnimatedValue {
|
||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self;
|
||||
}
|
||||
|
||||
/// Marker trait for computed values with the same representation during animations.
|
||||
pub trait AnimatedValueAsComputed {}
|
||||
|
||||
/// Returns a value similar to `self` that represents zero.
|
||||
pub trait ToAnimatedZero: Sized {
|
||||
/// Returns a value that, when added with an underlying value, will produce the underlying
|
||||
/// value. This is used for SMIL animation's "by-animation" where SMIL first interpolates from
|
||||
/// the zero value to the 'by' value, and then adds the result to the underlying value.
|
||||
///
|
||||
/// This is not the necessarily the same as the initial value of a property. For example, the
|
||||
/// initial value of 'stroke-width' is 1, but the zero value is 0, since adding 1 to the
|
||||
/// underlying value will not produce the underlying value.
|
||||
fn to_animated_zero(&self) -> Result<Self, ()>;
|
||||
}
|
||||
|
||||
impl Procedure {
|
||||
/// Returns this procedure as a pair of weights.
|
||||
///
|
||||
/// This is useful for animations that don't animate differently
|
||||
/// depending on the used procedure.
|
||||
#[inline]
|
||||
pub fn weights(self) -> (f64, f64) {
|
||||
match self {
|
||||
Procedure::Interpolate { progress } => (1. - progress, progress),
|
||||
Procedure::Add => (1., 1.),
|
||||
Procedure::Accumulate { count } => (count as f64, 1.),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
||||
impl Animate for i32 {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(((*self as f64).animate(&(*other as f64), procedure)? + 0.5).floor() as i32)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
||||
impl Animate for f32 {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok((*self as f64).animate(&(*other as f64), procedure)? as f32)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
||||
impl Animate for f64 {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
let (self_weight, other_weight) = procedure.weights();
|
||||
Ok(*self * self_weight + *other * other_weight)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Animate for Option<T>
|
||||
where
|
||||
T: Animate,
|
||||
{
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self.as_ref(), other.as_ref()) {
|
||||
(Some(ref this), Some(ref other)) => Ok(Some(this.animate(other, procedure)?)),
|
||||
(None, None) => Ok(None),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Animate for Au {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Au(self.0.animate(&other.0, procedure)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Animate for Size2D<T>
|
||||
where
|
||||
T: Animate + Copy,
|
||||
{
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Size2D::new(
|
||||
self.width.animate(&other.width, procedure)?,
|
||||
self.height.animate(&other.height, procedure)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Animate for Point2D<T>
|
||||
where
|
||||
T: Animate + Copy,
|
||||
{
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Point2D::new(
|
||||
self.x.animate(&other.x, procedure)?,
|
||||
self.y.animate(&other.y, procedure)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToAnimatedValue for Option<T>
|
||||
where
|
||||
T: ToAnimatedValue,
|
||||
@ -92,9 +215,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker trait for computed values with the same representation during animations.
|
||||
pub trait AnimatedValueAsComputed {}
|
||||
|
||||
impl AnimatedValueAsComputed for Au {}
|
||||
impl AnimatedValueAsComputed for ComputedAngle {}
|
||||
impl AnimatedValueAsComputed for SpecifiedUrl {}
|
||||
@ -263,18 +383,6 @@ impl ToAnimatedValue for ComputedMozLength {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a value similar to `self` that represents zero.
|
||||
pub trait ToAnimatedZero: Sized {
|
||||
/// Returns a value that, when added with an underlying value, will produce the underlying
|
||||
/// value. This is used for SMIL animation's "by-animation" where SMIL first interpolates from
|
||||
/// the zero value to the 'by' value, and then adds the result to the underlying value.
|
||||
///
|
||||
/// This is not the necessarily the same as the initial value of a property. For example, the
|
||||
/// initial value of 'stroke-width' is 1, but the zero value is 0, since adding 1 to the
|
||||
/// underlying value will not produce the underlying value.
|
||||
fn to_animated_zero(&self) -> Result<Self, ()>;
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for Au {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> { Ok(Au(0)) }
|
||||
@ -294,3 +402,16 @@ impl ToAnimatedZero for i32 {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> { Ok(0) }
|
||||
}
|
||||
|
||||
impl<T> ToAnimatedZero for Option<T>
|
||||
where
|
||||
T: ToAnimatedZero,
|
||||
{
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
match *self {
|
||||
Some(ref value) => Ok(Some(value.to_animated_zero()?)),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
//! Computed angles.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::{f32, f64, fmt};
|
||||
use std::f64::consts::PI;
|
||||
use style_traits::ToCss;
|
||||
use values::CSSFloat;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
|
||||
/// A computed angle.
|
||||
@ -65,24 +65,34 @@ impl Angle {
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-number
|
||||
impl Animatable for Angle {
|
||||
impl Animate for Angle {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(&Angle::Degree(ref this), &Angle::Degree(ref other)) => {
|
||||
Ok(Angle::Degree(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(Angle::Degree(this.animate(other, procedure)?))
|
||||
},
|
||||
(&Angle::Gradian(ref this), &Angle::Gradian(ref other)) => {
|
||||
Ok(Angle::Gradian(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(Angle::Gradian(this.animate(other, procedure)?))
|
||||
},
|
||||
(&Angle::Turn(ref this), &Angle::Turn(ref other)) => {
|
||||
Ok(Angle::Turn(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(Angle::Turn(this.animate(other, procedure)?))
|
||||
},
|
||||
_ => {
|
||||
self.radians()
|
||||
.add_weighted(&other.radians(), self_portion, other_portion)
|
||||
.map(Angle::from_radians)
|
||||
}
|
||||
Ok(Angle::from_radians(self.radians().animate(&other.radians(), procedure)?))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for Angle {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Angle, ()> {
|
||||
match *self {
|
||||
Angle::Degree(ref this) => Ok(Angle::Degree(this.to_animated_zero()?)),
|
||||
Angle::Gradian(ref this) => Ok(Angle::Gradian(this.to_animated_zero()?)),
|
||||
Angle::Radian(ref this) => Ok(Angle::Radian(this.to_animated_zero()?)),
|
||||
Angle::Turn(ref this) => Ok(Angle::Turn(this.to_animated_zero()?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
//! Computed types for CSS values related to backgrounds.
|
||||
|
||||
use properties::animated_properties::{Animatable, RepeatableListAnimatable};
|
||||
use properties::animated_properties::RepeatableListAnimatable;
|
||||
use properties::longhands::background_size::computed_value::T as BackgroundSizeList;
|
||||
use values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use values::computed::length::LengthOrPercentageOrAuto;
|
||||
use values::generics::background::BackgroundSize as GenericBackgroundSize;
|
||||
|
||||
@ -15,16 +15,16 @@ pub type BackgroundSize = GenericBackgroundSize<LengthOrPercentageOrAuto>;
|
||||
|
||||
impl RepeatableListAnimatable for BackgroundSize {}
|
||||
|
||||
impl Animatable for BackgroundSize {
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
impl Animate for BackgroundSize {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(
|
||||
&GenericBackgroundSize::Explicit { width: self_width, height: self_height },
|
||||
&GenericBackgroundSize::Explicit { width: other_width, height: other_height },
|
||||
) => {
|
||||
Ok(GenericBackgroundSize::Explicit {
|
||||
width: self_width.add_weighted(&other_width, self_portion, other_portion)?,
|
||||
height: self_height.add_weighted(&other_height, self_portion, other_portion)?,
|
||||
width: self_width.animate(&other_width, procedure)?,
|
||||
height: self_height.animate(&other_height, procedure)?,
|
||||
})
|
||||
}
|
||||
_ => Err(()),
|
||||
|
@ -11,6 +11,7 @@ use style_traits::ToCss;
|
||||
use style_traits::values::specified::AllowedLengthType;
|
||||
use super::{Number, ToComputedValue, Context, Percentage};
|
||||
use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal, specified};
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::computed::{NonNegativeAu, NonNegativeNumber};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use values::generics::NonNegative;
|
||||
@ -72,6 +73,17 @@ pub struct CalcLengthOrPercentage {
|
||||
pub percentage: Option<Percentage>,
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for CalcLengthOrPercentage {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
Ok(CalcLengthOrPercentage {
|
||||
clamping_mode: self.clamping_mode,
|
||||
length: self.length.to_animated_zero()?,
|
||||
percentage: self.percentage.to_animated_zero()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeSquaredDistance for CalcLengthOrPercentage {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
|
@ -4,11 +4,10 @@
|
||||
|
||||
//! Computed percentages.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::{CSSFloat, serialize_percentage};
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
|
||||
/// A computed percentage.
|
||||
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, Default, HasViewportPercentage, PartialEq, PartialOrd)]
|
||||
@ -36,10 +35,10 @@ impl Percentage {
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transitions/#animtype-percentage
|
||||
impl Animatable for Percentage {
|
||||
impl Animate for Percentage {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
Ok(Percentage((self.0 as f64 * self_portion + other.0 as f64 * other_portion) as f32))
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Percentage(self.0.animate(&other.0, procedure)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,8 @@
|
||||
|
||||
//! Computed types for text properties.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::{CSSInteger, CSSFloat};
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use values::computed::{NonNegativeAu, NonNegativeNumber};
|
||||
use values::computed::length::{Length, LengthOrPercentage};
|
||||
use values::generics::text::InitialLetter as GenericInitialLetter;
|
||||
@ -25,21 +24,21 @@ pub type WordSpacing = Spacing<LengthOrPercentage>;
|
||||
/// A computed value for the `line-height` property.
|
||||
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeAu>;
|
||||
|
||||
impl Animatable for LineHeight {
|
||||
impl Animate for LineHeight {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
match (*self, *other) {
|
||||
(GenericLineHeight::Length(ref this), GenericLineHeight::Length(ref other)) => {
|
||||
this.add_weighted(other, self_portion, other_portion).map(GenericLineHeight::Length)
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(&GenericLineHeight::Length(ref this), &GenericLineHeight::Length(ref other)) => {
|
||||
Ok(GenericLineHeight::Length(this.animate(other, procedure)?))
|
||||
},
|
||||
(GenericLineHeight::Number(ref this), GenericLineHeight::Number(ref other)) => {
|
||||
this.add_weighted(other, self_portion, other_portion).map(GenericLineHeight::Number)
|
||||
(&GenericLineHeight::Number(ref this), &GenericLineHeight::Number(ref other)) => {
|
||||
Ok(GenericLineHeight::Number(this.animate(other, procedure)?))
|
||||
},
|
||||
(GenericLineHeight::Normal, GenericLineHeight::Normal) => {
|
||||
(&GenericLineHeight::Normal, &GenericLineHeight::Normal) => {
|
||||
Ok(GenericLineHeight::Normal)
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
(GenericLineHeight::MozBlockHeight, GenericLineHeight::MozBlockHeight) => {
|
||||
(&GenericLineHeight::MozBlockHeight, &GenericLineHeight::MozBlockHeight) => {
|
||||
Ok(GenericLineHeight::MozBlockHeight)
|
||||
},
|
||||
_ => Err(()),
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
//! Computed types for CSS values that are related to transformations.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use values::computed::{Length, LengthOrPercentage, Number, Percentage};
|
||||
use values::generics::transform::TimingFunction as GenericTimingFunction;
|
||||
use values::generics::transform::TransformOrigin as GenericTransformOrigin;
|
||||
@ -28,13 +27,13 @@ impl TransformOrigin {
|
||||
}
|
||||
}
|
||||
|
||||
impl Animatable for TransformOrigin {
|
||||
impl Animate for TransformOrigin {
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Self::new(
|
||||
self.horizontal.add_weighted(&other.horizontal, self_portion, other_portion)?,
|
||||
self.vertical.add_weighted(&other.vertical, self_portion, other_portion)?,
|
||||
self.depth.add_weighted(&other.depth, self_portion, other_portion)?,
|
||||
self.horizontal.animate(&other.horizontal, procedure)?,
|
||||
self.vertical.animate(&other.vertical, procedure)?,
|
||||
self.depth.animate(&other.depth, procedure)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,9 @@
|
||||
//! CSS handling for the [`basic-shape`](https://drafts.csswg.org/css-shapes/#typedef-basic-shape)
|
||||
//! types that are generic over their `ToCss` implementations.
|
||||
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::fmt;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use values::generics::border::BorderRadius;
|
||||
@ -123,24 +122,21 @@ define_css_keyword_enum!(FillRule:
|
||||
);
|
||||
add_impls_for_keyword_enum!(FillRule);
|
||||
|
||||
impl<B, T, U> Animatable for ShapeSource<B, T, U>
|
||||
impl<B, T, U> Animate for ShapeSource<B, T, U>
|
||||
where
|
||||
B: Animatable,
|
||||
B: Animate,
|
||||
T: Clone + PartialEq,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(
|
||||
&ShapeSource::Shape(ref this, ref this_box),
|
||||
&ShapeSource::Shape(ref other, ref other_box),
|
||||
) if this_box == other_box => {
|
||||
let shape = this.add_weighted(other, self_portion, other_portion)?;
|
||||
Ok(ShapeSource::Shape(shape, this_box.clone()))
|
||||
Ok(ShapeSource::Shape(
|
||||
this.animate(other, procedure)?,
|
||||
this_box.clone(),
|
||||
))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
@ -178,49 +174,40 @@ impl<B, T, U> HasViewportPercentage for ShapeSource<B, T, U> {
|
||||
fn has_viewport_percentage(&self) -> bool { false }
|
||||
}
|
||||
|
||||
impl<H, V, L> Animatable for BasicShape<H, V, L>
|
||||
impl<H, V, L> Animate for BasicShape<H, V, L>
|
||||
where
|
||||
H: Animatable,
|
||||
V: Animatable,
|
||||
L: Animatable + Copy,
|
||||
H: Animate,
|
||||
V: Animate,
|
||||
L: Animate + Copy,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(&BasicShape::Circle(ref this), &BasicShape::Circle(ref other)) => {
|
||||
Ok(BasicShape::Circle(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(BasicShape::Circle(this.animate(other, procedure)?))
|
||||
},
|
||||
(&BasicShape::Ellipse(ref this), &BasicShape::Ellipse(ref other)) => {
|
||||
Ok(BasicShape::Ellipse(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(BasicShape::Ellipse(this.animate(other, procedure)?))
|
||||
},
|
||||
(&BasicShape::Inset(ref this), &BasicShape::Inset(ref other)) => {
|
||||
Ok(BasicShape::Inset(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(BasicShape::Inset(this.animate(other, procedure)?))
|
||||
},
|
||||
(&BasicShape::Polygon(ref this), &BasicShape::Polygon(ref other)) => {
|
||||
Ok(BasicShape::Polygon(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(BasicShape::Polygon(this.animate(other, procedure)?))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Animatable for InsetRect<L>
|
||||
impl<L> Animate for InsetRect<L>
|
||||
where
|
||||
L: Animatable + Copy,
|
||||
L: Animate + Copy,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
let rect = self.rect.add_weighted(&other.rect, self_portion, other_portion)?;
|
||||
let round = self.round.add_weighted(&other.round, self_portion, other_portion)?;
|
||||
Ok(InsetRect { rect, round })
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(InsetRect {
|
||||
rect: self.rect.animate(&other.rect, procedure)?,
|
||||
round: self.round.animate(&other.round, procedure)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,56 +225,43 @@ impl<L> ToCss for InsetRect<L>
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, V, L> Animatable for Circle<H, V, L>
|
||||
impl<H, V, L> Animate for Circle<H, V, L>
|
||||
where
|
||||
H: Animatable,
|
||||
V: Animatable,
|
||||
L: Animatable,
|
||||
H: Animate,
|
||||
V: Animate,
|
||||
L: Animate,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
let position = self.position.add_weighted(&other.position, self_portion, other_portion)?;
|
||||
let radius = self.radius.add_weighted(&other.radius, self_portion, other_portion)?;
|
||||
Ok(Circle { position, radius })
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Circle {
|
||||
position: self.position.animate(&other.position, procedure)?,
|
||||
radius: self.radius.animate(&other.radius, procedure)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, V, L> Animatable for Ellipse<H, V, L>
|
||||
impl<H, V, L> Animate for Ellipse<H, V, L>
|
||||
where
|
||||
H: Animatable,
|
||||
V: Animatable,
|
||||
L: Animatable,
|
||||
H: Animate,
|
||||
V: Animate,
|
||||
L: Animate,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
let position = self.position.add_weighted(&other.position, self_portion, other_portion)?;
|
||||
let semiaxis_x = self.semiaxis_x.add_weighted(&other.semiaxis_x, self_portion, other_portion)?;
|
||||
let semiaxis_y = self.semiaxis_y.add_weighted(&other.semiaxis_y, self_portion, other_portion)?;
|
||||
Ok(Ellipse { position, semiaxis_x, semiaxis_y })
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Ellipse {
|
||||
position: self.position.animate(&other.position, procedure)?,
|
||||
semiaxis_x: self.semiaxis_x.animate(&other.semiaxis_x, procedure)?,
|
||||
semiaxis_y: self.semiaxis_y.animate(&other.semiaxis_y, procedure)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Animatable for ShapeRadius<L>
|
||||
impl<L> Animate for ShapeRadius<L>
|
||||
where
|
||||
L: Animatable,
|
||||
L: Animate,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
match (self, other) {
|
||||
(&ShapeRadius::Length(ref this), &ShapeRadius::Length(ref other)) => {
|
||||
Ok(ShapeRadius::Length(this.add_weighted(other, self_portion, other_portion)?))
|
||||
Ok(ShapeRadius::Length(this.animate(other, procedure)?))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
@ -299,16 +273,11 @@ impl<L> Default for ShapeRadius<L> {
|
||||
fn default() -> Self { ShapeRadius::ClosestSide }
|
||||
}
|
||||
|
||||
impl<L> Animatable for Polygon<L>
|
||||
impl<L> Animate for Polygon<L>
|
||||
where
|
||||
L: Animatable,
|
||||
L: Animate,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
if self.fill != other.fill {
|
||||
return Err(());
|
||||
}
|
||||
@ -316,9 +285,10 @@ where
|
||||
return Err(());
|
||||
}
|
||||
let coordinates = self.coordinates.iter().zip(other.coordinates.iter()).map(|(this, other)| {
|
||||
let x = this.0.add_weighted(&other.0, self_portion, other_portion)?;
|
||||
let y = this.1.add_weighted(&other.1, self_portion, other_portion)?;
|
||||
Ok((x, y))
|
||||
Ok((
|
||||
this.0.animate(&other.0, procedure)?,
|
||||
this.1.animate(&other.1, procedure)?,
|
||||
))
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(Polygon { fill: self.fill, coordinates })
|
||||
}
|
||||
|
@ -5,9 +5,9 @@
|
||||
//! Generic types for CSS values related to borders.
|
||||
|
||||
use euclid::Size2D;
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::animated::{Animate, Procedure};
|
||||
use values::generics::rect::Rect;
|
||||
|
||||
/// A generic value for a single side of a `border-image-width` property.
|
||||
@ -113,21 +113,17 @@ impl<L> BorderRadius<L>
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Animatable for BorderRadius<L>
|
||||
impl<L> Animate for BorderRadius<L>
|
||||
where
|
||||
L: Animatable + Copy,
|
||||
L: Animate + Copy,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
let tl = self.top_left.add_weighted(&other.top_left, self_portion, other_portion)?;
|
||||
let tr = self.top_right.add_weighted(&other.top_right, self_portion, other_portion)?;
|
||||
let br = self.bottom_right.add_weighted(&other.bottom_right, self_portion, other_portion)?;
|
||||
let bl = self.bottom_left.add_weighted(&other.bottom_left, self_portion, other_portion)?;
|
||||
Ok(BorderRadius::new(tl, tr, br, bl))
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(BorderRadius::new(
|
||||
self.top_left.animate(&other.top_left, procedure)?,
|
||||
self.top_right.animate(&other.top_right, procedure)?,
|
||||
self.bottom_right.animate(&other.bottom_right, procedure)?,
|
||||
self.bottom_left.animate(&other.bottom_left, procedure)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,18 +159,13 @@ impl<L: Clone> From<L> for BorderCornerRadius<L> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Animatable for BorderCornerRadius<L>
|
||||
impl<L> Animate for BorderCornerRadius<L>
|
||||
where
|
||||
L: Animatable + Copy,
|
||||
L: Animate + Copy,
|
||||
{
|
||||
#[inline]
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
Ok(BorderCornerRadius(self.0.add_weighted(&other.0, self_portion, other_portion)?))
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(BorderCornerRadius(self.0.animate(&other.0, procedure)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,9 @@
|
||||
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
use values::animated::{Animate, Procedure};
|
||||
|
||||
/// A CSS value made of four components, where its `ToCss` impl will try to
|
||||
/// serialize as few components as possible, like for example in `border-width`.
|
||||
@ -52,21 +52,17 @@ impl<T> Rect<T>
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> Animatable for Rect<L>
|
||||
impl<L> Animate for Rect<L>
|
||||
where
|
||||
L: Animatable,
|
||||
L: Animate,
|
||||
{
|
||||
fn add_weighted(
|
||||
&self,
|
||||
other: &Self,
|
||||
self_portion: f64,
|
||||
other_portion: f64,
|
||||
) -> Result<Self, ()> {
|
||||
let first = self.0.add_weighted(&other.0, self_portion, other_portion)?;
|
||||
let second = self.1.add_weighted(&other.1, self_portion, other_portion)?;
|
||||
let third = self.2.add_weighted(&other.2, self_portion, other_portion)?;
|
||||
let fourth = self.3.add_weighted(&other.3, self_portion, other_portion)?;
|
||||
Ok(Rect(first, second, third, fourth))
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
Ok(Rect(
|
||||
self.0.animate(&other.0, procedure)?,
|
||||
self.1.animate(&other.1, procedure)?,
|
||||
self.2.animate(&other.2, procedure)?,
|
||||
self.3.animate(&other.3, procedure)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,8 @@
|
||||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use parser::ParserContext;
|
||||
use properties::animated_properties::Animatable;
|
||||
use style_traits::ParseError;
|
||||
use values::animated::ToAnimatedZero;
|
||||
use values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
|
||||
/// A generic value for the `initial-letter` property.
|
||||
@ -72,18 +71,19 @@ impl<Value> Spacing<Value> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Value> Animatable for Spacing<Value>
|
||||
where Value: Animatable + From<Au>,
|
||||
impl<Value> Animate for Spacing<Value>
|
||||
where
|
||||
Value: Animate + From<Au>,
|
||||
{
|
||||
#[inline]
|
||||
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
if let (&Spacing::Normal, &Spacing::Normal) = (self, other) {
|
||||
return Ok(Spacing::Normal);
|
||||
}
|
||||
let zero = Value::from(Au(0));
|
||||
let this = self.value().unwrap_or(&zero);
|
||||
let other = other.value().unwrap_or(&zero);
|
||||
this.add_weighted(other, self_portion, other_portion).map(Spacing::Value)
|
||||
Ok(Spacing::Value(this.animate(other, procedure)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ use style::properties::{IS_FIELDSET_CONTENT, IS_LINK, IS_VISITED_LINK, LonghandI
|
||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyId, ShorthandId};
|
||||
use style::properties::{SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, SourcePropertyDeclaration, StyleBuilder};
|
||||
use style::properties::PROHIBIT_DISPLAY_CONTENTS;
|
||||
use style::properties::animated_properties::{Animatable, AnimatableLonghand, AnimationValue};
|
||||
use style::properties::animated_properties::{AnimatableLonghand, AnimationValue};
|
||||
use style::properties::animated_properties::compare_property_priority;
|
||||
use style::properties::parse_one_declaration_into;
|
||||
use style::rule_tree::StyleSource;
|
||||
@ -128,7 +128,7 @@ use style::traversal::{DomTraversal, TraversalDriver};
|
||||
use style::traversal::resolve_style;
|
||||
use style::traversal_flags::{TraversalFlags, self};
|
||||
use style::values::{CustomIdent, KeyframesName};
|
||||
use style::values::animated::ToAnimatedZero;
|
||||
use style::values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use style::values::computed::Context;
|
||||
use style::values::distance::ComputeSquaredDistance;
|
||||
use style_traits::{PARSING_MODE_DEFAULT, ToCss};
|
||||
@ -319,7 +319,7 @@ pub extern "C" fn Servo_AnimationValues_Interpolate(from: RawServoAnimationValue
|
||||
{
|
||||
let from_value = AnimationValue::as_arc(&from);
|
||||
let to_value = AnimationValue::as_arc(&to);
|
||||
if let Ok(value) = from_value.interpolate(to_value, progress) {
|
||||
if let Ok(value) = from_value.animate(to_value, Procedure::Interpolate { progress }) {
|
||||
Arc::new(value).into_strong()
|
||||
} else {
|
||||
RawServoAnimationValueStrong::null()
|
||||
@ -332,7 +332,7 @@ pub extern "C" fn Servo_AnimationValues_IsInterpolable(from: RawServoAnimationVa
|
||||
-> bool {
|
||||
let from_value = AnimationValue::as_arc(&from);
|
||||
let to_value = AnimationValue::as_arc(&to);
|
||||
from_value.interpolate(to_value, 0.5).is_ok()
|
||||
from_value.animate(to_value, Procedure::Interpolate { progress: 0.5 }).is_ok()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -342,7 +342,7 @@ pub extern "C" fn Servo_AnimationValues_Add(a: RawServoAnimationValueBorrowed,
|
||||
{
|
||||
let a_value = AnimationValue::as_arc(&a);
|
||||
let b_value = AnimationValue::as_arc(&b);
|
||||
if let Ok(value) = a_value.add(b_value) {
|
||||
if let Ok(value) = a_value.animate(b_value, Procedure::Add) {
|
||||
Arc::new(value).into_strong()
|
||||
} else {
|
||||
RawServoAnimationValueStrong::null()
|
||||
@ -357,7 +357,7 @@ pub extern "C" fn Servo_AnimationValues_Accumulate(a: RawServoAnimationValueBorr
|
||||
{
|
||||
let a_value = AnimationValue::as_arc(&a);
|
||||
let b_value = AnimationValue::as_arc(&b);
|
||||
if let Ok(value) = a_value.accumulate(b_value, count) {
|
||||
if let Ok(value) = a_value.animate(b_value, Procedure::Accumulate { count }) {
|
||||
Arc::new(value).into_strong()
|
||||
} else {
|
||||
RawServoAnimationValueStrong::null()
|
||||
@ -463,12 +463,16 @@ pub extern "C" fn Servo_AnimationCompose(raw_value_map: RawServoAnimationValueMa
|
||||
CompositeOperation::Add => {
|
||||
debug_assert!(need_underlying_value,
|
||||
"Should have detected we need an underlying value");
|
||||
underlying_value.as_ref().unwrap().add(keyframe_value).ok()
|
||||
underlying_value.as_ref().unwrap().animate(keyframe_value, Procedure::Add).ok()
|
||||
},
|
||||
CompositeOperation::Accumulate => {
|
||||
debug_assert!(need_underlying_value,
|
||||
"Should have detected we need an underlying value");
|
||||
underlying_value.as_ref().unwrap().accumulate(keyframe_value, 1).ok()
|
||||
underlying_value
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.animate(keyframe_value, Procedure::Accumulate { count: 1 })
|
||||
.ok()
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
@ -507,11 +511,17 @@ pub extern "C" fn Servo_AnimationCompose(raw_value_map: RawServoAnimationValueMa
|
||||
-> Option<AnimationValue> {
|
||||
let count = computed_timing.mCurrentIteration;
|
||||
match composited_value {
|
||||
Some(endpoint) => last_value.accumulate(&endpoint, count)
|
||||
.ok()
|
||||
.or(Some(endpoint)),
|
||||
None => last_value.accumulate(keyframe_value.unwrap(), count)
|
||||
.ok(),
|
||||
Some(endpoint) => {
|
||||
last_value
|
||||
.animate(&endpoint, Procedure::Accumulate { count })
|
||||
.ok()
|
||||
.or(Some(endpoint))
|
||||
},
|
||||
None => {
|
||||
last_value
|
||||
.animate(keyframe_value.unwrap(), Procedure::Accumulate { count })
|
||||
.ok()
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -535,12 +545,12 @@ pub extern "C" fn Servo_AnimationCompose(raw_value_map: RawServoAnimationValueMa
|
||||
return;
|
||||
}
|
||||
|
||||
let position = unsafe {
|
||||
let pos = unsafe {
|
||||
Gecko_GetPositionInSegment(segment, progress, computed_timing.mBeforeFlag)
|
||||
};
|
||||
if let Ok(value) = from_value.interpolate(to_value, position) {
|
||||
if let Ok(value) = from_value.animate(to_value, Procedure::Interpolate { progress: pos }) {
|
||||
value_map.insert(property, value);
|
||||
} else if position < 0.5 {
|
||||
} else if pos < 0.5 {
|
||||
value_map.insert(property, from_value.clone());
|
||||
} else {
|
||||
value_map.insert(property, to_value.clone());
|
||||
@ -2080,8 +2090,8 @@ pub extern "C" fn Servo_MatrixTransform_Operate(matrix_operator: MatrixTransform
|
||||
let from = ComputedMatrix::from(unsafe { from.as_ref() }.expect("not a valid 'from' matrix"));
|
||||
let to = ComputedMatrix::from(unsafe { to.as_ref() }.expect("not a valid 'to' matrix"));
|
||||
let result = match matrix_operator {
|
||||
Interpolate => from.interpolate(&to, progress),
|
||||
Accumulate => from.accumulate(&to, progress as u64),
|
||||
Interpolate => from.animate(&to, Procedure::Interpolate { progress }),
|
||||
Accumulate => from.animate(&to, Procedure::Accumulate { count: progress as u64 }),
|
||||
};
|
||||
|
||||
let output = unsafe { output.as_mut() }.expect("not a valid 'output' matrix");
|
||||
|
@ -4,16 +4,17 @@
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
use style::properties::animated_properties::Animatable;
|
||||
use style::properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
|
||||
use style::properties::longhands::transform::computed_value::T as TransformList;
|
||||
use style::values::animated::ToAnimatedValue;
|
||||
use style::values::animated::{Animate, Procedure, ToAnimatedValue};
|
||||
use style::values::computed::Percentage;
|
||||
|
||||
fn interpolate_rgba(from: RGBA, to: RGBA, progress: f64) -> RGBA {
|
||||
let from = from.to_animated_value();
|
||||
let to = to.to_animated_value();
|
||||
RGBA::from_animated_value(from.interpolate(&to, progress).unwrap())
|
||||
RGBA::from_animated_value(
|
||||
from.animate(&to, Procedure::Interpolate { progress }).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
// Color
|
||||
@ -74,11 +75,14 @@ fn test_transform_interpolation_on_translate() {
|
||||
TransformOperation::Translate(LengthOrPercentage::Length(Au(100)),
|
||||
LengthOrPercentage::Length(Au(0)),
|
||||
Au(75))]));
|
||||
assert_eq!(from.interpolate(&to, 0.5).unwrap(),
|
||||
TransformList(Some(vec![
|
||||
TransformOperation::Translate(LengthOrPercentage::Length(Au(50)),
|
||||
LengthOrPercentage::Length(Au(50)),
|
||||
Au(50))])));
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Translate(
|
||||
LengthOrPercentage::Length(Au(50)),
|
||||
LengthOrPercentage::Length(Au(50)),
|
||||
Au(50),
|
||||
)]))
|
||||
);
|
||||
|
||||
let from = TransformList(Some(vec![TransformOperation::Translate(
|
||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||
@ -90,7 +94,7 @@ fn test_transform_interpolation_on_translate() {
|
||||
LengthOrPercentage::Length(Au(50)),
|
||||
Au(75))]));
|
||||
assert_eq!(
|
||||
from.interpolate(&to, 0.5).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Translate(
|
||||
// calc(50px + 25%)
|
||||
LengthOrPercentage::Calc(CalcLengthOrPercentage::new(Au(50), Some(Percentage(0.25)))),
|
||||
@ -105,8 +109,10 @@ fn test_transform_interpolation_on_translate() {
|
||||
fn test_transform_interpolation_on_scale() {
|
||||
let from = TransformList(Some(vec![TransformOperation::Scale(1.0, 2.0, 1.0)]));
|
||||
let to = TransformList(Some(vec![TransformOperation::Scale(2.0, 4.0, 2.0)]));
|
||||
assert_eq!(from.interpolate(&to, 0.5).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Scale(1.5, 3.0, 1.5)])));
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Scale(1.5, 3.0, 1.5)]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -117,9 +123,12 @@ fn test_transform_interpolation_on_rotate() {
|
||||
Angle::from_radians(0.0))]));
|
||||
let to = TransformList(Some(vec![TransformOperation::Rotate(0.0, 0.0, 1.0,
|
||||
Angle::from_radians(100.0))]));
|
||||
assert_eq!(from.interpolate(&to, 0.5).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Rotate(0.0, 0.0, 1.0,
|
||||
Angle::from_radians(50.0))])));
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
TransformList(Some(vec![
|
||||
TransformOperation::Rotate(0.0, 0.0, 1.0, Angle::from_radians(50.0)),
|
||||
]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -130,9 +139,13 @@ fn test_transform_interpolation_on_skew() {
|
||||
Angle::from_radians(100.0))]));
|
||||
let to = TransformList(Some(vec![TransformOperation::Skew(Angle::from_radians(100.0),
|
||||
Angle::from_radians(0.0))]));
|
||||
assert_eq!(from.interpolate(&to, 0.5).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Skew(Angle::from_radians(50.0),
|
||||
Angle::from_radians(50.0))])));
|
||||
assert_eq!(
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::Skew(
|
||||
Angle::from_radians(50.0),
|
||||
Angle::from_radians(50.0),
|
||||
)]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -146,7 +159,7 @@ fn test_transform_interpolation_on_mismatched_lists() {
|
||||
LengthOrPercentage::Length(Au(0)),
|
||||
Au(0))]));
|
||||
assert_eq!(
|
||||
from.interpolate(&to, 0.5).unwrap(),
|
||||
from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
|
||||
TransformList(Some(vec![TransformOperation::InterpolateMatrix {
|
||||
from_list: from.clone(),
|
||||
to_list: to.clone(),
|
||||
|
@ -5,16 +5,14 @@
|
||||
use cssparser::SourceLocation;
|
||||
use euclid::ScaleFactor;
|
||||
use euclid::TypedSize2D;
|
||||
use html5ever::LocalName;
|
||||
use selectors::parser::{AncestorHashes, Selector};
|
||||
use selectors::parser::LocalName as LocalNameSelector;
|
||||
use servo_arc::Arc;
|
||||
use servo_atoms::Atom;
|
||||
use style::context::QuirksMode;
|
||||
use style::media_queries::{Device, MediaType};
|
||||
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration};
|
||||
use style::properties::{longhands, Importance};
|
||||
use style::selector_map::{self, SelectorMap};
|
||||
use style::selector_map::SelectorMap;
|
||||
use style::selector_parser::{SelectorImpl, SelectorParser};
|
||||
use style::shared_lock::SharedRwLock;
|
||||
use style::stylesheets::StyleRule;
|
||||
|
Loading…
Reference in New Issue
Block a user