Auto merge of #17774 - servo:derive-all-the-things, r=emilio

Prepare some code for future derivation 🌊

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17774)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-07-19 01:56:05 -07:00 committed by GitHub
commit d76d097891
18 changed files with 402 additions and 251 deletions

View file

@ -9,7 +9,6 @@ use Atom;
use bezier::Bezier; use bezier::Bezier;
use context::SharedStyleContext; use context::SharedStyleContext;
use dom::OpaqueNode; use dom::OpaqueNode;
use euclid::Point2D;
use font_metrics::FontMetricsProvider; use font_metrics::FontMetricsProvider;
use properties::{self, CascadeFlags, ComputedValues, Importance}; use properties::{self, CascadeFlags, ComputedValues, Importance};
use properties::animated_properties::{AnimatableLonghand, AnimatedProperty, TransitionProperty}; use properties::animated_properties::{AnimatableLonghand, AnimatedProperty, TransitionProperty};
@ -369,18 +368,10 @@ impl PropertyAnimation {
/// Update the given animation at a given point of progress. /// Update the given animation at a given point of progress.
pub fn update(&self, style: &mut ComputedValues, time: f64) { pub fn update(&self, style: &mut ComputedValues, time: f64) {
let solve_bezier = |(p1, p2): (Point2D<_>, Point2D<_>)| {
let epsilon = 1. / (200. * (self.duration.seconds() as f64)); let epsilon = 1. / (200. * (self.duration.seconds() as f64));
let bezier = Bezier::new(
Point2D::new(p1.x as f64, p1.y as f64),
Point2D::new(p2.x as f64, p2.y as f64),
);
bezier.solve(time, epsilon)
};
let progress = match self.timing_function { let progress = match self.timing_function {
GenericTimingFunction::CubicBezier(p1, p2) => { GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
solve_bezier((p1, p2)) Bezier::new(x1, y1, x2, y2).solve(time, epsilon)
}, },
GenericTimingFunction::Steps(steps, StepPosition::Start) => { GenericTimingFunction::Steps(steps, StepPosition::Start) => {
(time * (steps as f64)).ceil() / (steps as f64) (time * (steps as f64)).ceil() / (steps as f64)
@ -405,7 +396,8 @@ impl PropertyAnimation {
out out
}, },
GenericTimingFunction::Keyword(keyword) => { GenericTimingFunction::Keyword(keyword) => {
solve_bezier(keyword.to_bezier_points()) let (x1, x2, y1, y2) = keyword.to_bezier();
Bezier::new(x1, x2, y1, y2).solve(time, epsilon)
}, },
}; };

View file

@ -8,7 +8,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use euclid::Point2D; use values::CSSFloat;
const NEWTON_METHOD_ITERATIONS: u8 = 8; const NEWTON_METHOD_ITERATIONS: u8 = 8;
@ -31,12 +31,12 @@ impl Bezier {
/// The start and end points are always (0, 0) and (1, 1) so that a transition or animation /// The start and end points are always (0, 0) and (1, 1) so that a transition or animation
/// starts at 0% and ends at 100%. /// starts at 0% and ends at 100%.
#[inline] #[inline]
pub fn new(p1: Point2D<f64>, p2: Point2D<f64>) -> Bezier { pub fn new(x1: CSSFloat, y1: CSSFloat, x2: CSSFloat, y2: CSSFloat) -> Bezier {
let cx = 3.0 * p1.x; let cx = 3. * x1 as f64;
let bx = 3.0 * (p2.x - p1.x) - cx; let bx = 3. * (x2 as f64 - x1 as f64) - cx;
let cy = 3.0 * p1.y; let cy = 3. * y1 as f64;
let by = 3.0 * (p2.y - p1.y) - cy; let by = 3. * (y2 as f64 - y1 as f64) - cy;
Bezier { Bezier {
ax: 1.0 - cx - bx, ax: 1.0 - cx - bx,

View file

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use euclid::{Point2D, TypedPoint2D};
use gecko_bindings::structs::{nsTimingFunction, nsTimingFunction_Type}; use gecko_bindings::structs::{nsTimingFunction, nsTimingFunction_Type};
use std::mem; use std::mem;
use values::computed::ToComputedValue; use values::computed::ToComputedValue;
@ -28,18 +27,19 @@ impl nsTimingFunction {
} }
} }
fn set_as_bezier(&mut self, fn set_as_bezier(
&mut self,
function_type: nsTimingFunction_Type, function_type: nsTimingFunction_Type,
p1: Point2D<f32>, x1: f32, y1: f32, x2: f32, y2: f32,
p2: Point2D<f32>) { ) {
self.mType = function_type; self.mType = function_type;
unsafe { unsafe {
let ref mut gecko_cubic_bezier = let ref mut gecko_cubic_bezier =
unsafe { self.__bindgen_anon_1.mFunc.as_mut() }; unsafe { self.__bindgen_anon_1.mFunc.as_mut() };
gecko_cubic_bezier.mX1 = p1.x; gecko_cubic_bezier.mX1 = x1;
gecko_cubic_bezier.mY1 = p1.y; gecko_cubic_bezier.mY1 = y1;
gecko_cubic_bezier.mX2 = p2.x; gecko_cubic_bezier.mX2 = x2;
gecko_cubic_bezier.mY2 = p2.y; gecko_cubic_bezier.mY2 = y2;
} }
} }
} }
@ -67,14 +67,15 @@ impl From<TimingFunction> for nsTimingFunction {
debug_assert!(frames.value() >= 2); debug_assert!(frames.value() >= 2);
tf.set_as_frames(frames.value() as u32); tf.set_as_frames(frames.value() as u32);
}, },
GenericTimingFunction::CubicBezier(p1, p2) => { GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
tf.set_as_bezier(nsTimingFunction_Type::CubicBezier, tf.set_as_bezier(
Point2D::new(p1.x.get(), p1.y.get()), nsTimingFunction_Type::CubicBezier,
Point2D::new(p2.x.get(), p2.y.get())); x1.get(), y1.get(), x2.get(), y2.get(),
);
}, },
GenericTimingFunction::Keyword(keyword) => { GenericTimingFunction::Keyword(keyword) => {
let (p1, p2) = keyword.to_bezier_points(); let (x1, y1, x2, y2) = keyword.to_bezier();
tf.set_as_bezier(keyword.into(), p1, p2) tf.set_as_bezier(keyword.into(), x1, y1, x2, y2);
}, },
} }
tf tf
@ -114,11 +115,14 @@ impl From<nsTimingFunction> for ComputedTimingFunction {
GenericTimingFunction::Keyword(TimingKeyword::EaseInOut) GenericTimingFunction::Keyword(TimingKeyword::EaseInOut)
}, },
nsTimingFunction_Type::CubicBezier => { nsTimingFunction_Type::CubicBezier => {
GenericTimingFunction::CubicBezier( unsafe {
TypedPoint2D::new(unsafe { function.__bindgen_anon_1.mFunc.as_ref().mX1 }, GenericTimingFunction::CubicBezier {
unsafe { function.__bindgen_anon_1.mFunc.as_ref().mY1 }), x1: function.__bindgen_anon_1.mFunc.as_ref().mX1,
TypedPoint2D::new(unsafe { function.__bindgen_anon_1.mFunc.as_ref().mX2 }, y1: function.__bindgen_anon_1.mFunc.as_ref().mY1,
unsafe { function.__bindgen_anon_1.mFunc.as_ref().mY2 })) x2: function.__bindgen_anon_1.mFunc.as_ref().mX2,
y2: function.__bindgen_anon_1.mFunc.as_ref().mY2,
}
}
}, },
} }
} }

View file

@ -112,5 +112,10 @@ macro_rules! define_keyword_type {
impl $crate::values::computed::ComputedValueAsSpecified for $name {} impl $crate::values::computed::ComputedValueAsSpecified for $name {}
impl $crate::values::animated::AnimatedValueAsComputed for $name {} impl $crate::values::animated::AnimatedValueAsComputed for $name {}
no_viewport_percentage!($name); no_viewport_percentage!($name);
impl $crate::values::animated::ToAnimatedZero for $name {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Ok($name) }
}
}; };
} }

View file

@ -129,6 +129,8 @@
% if animation_value_type == "ComputedValue": % if animation_value_type == "ComputedValue":
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
use values::animated::ToAnimatedZero;
impl Animatable for T { impl Animatable for T {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> { -> Result<Self, ()> {
@ -149,6 +151,11 @@
self.0.compute_squared_distance(&other.0) self.0.compute_squared_distance(&other.0)
} }
} }
impl ToAnimatedZero for T {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
% endif % endif
pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>; pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>;

View file

@ -33,7 +33,7 @@ use super::ComputedValues;
#[cfg(any(feature = "gecko", feature = "testing"))] #[cfg(any(feature = "gecko", feature = "testing"))]
use values::Auto; use values::Auto;
use values::{CSSFloat, CustomIdent, Either}; use values::{CSSFloat, CustomIdent, Either};
use values::animated::ToAnimatedValue; use values::animated::{ToAnimatedValue, ToAnimatedZero};
use values::animated::effects::BoxShadowList as AnimatedBoxShadowList; use values::animated::effects::BoxShadowList as AnimatedBoxShadowList;
use values::animated::effects::Filter as AnimatedFilter; use values::animated::effects::Filter as AnimatedFilter;
use values::animated::effects::FilterList as AnimatedFilterList; use values::animated::effects::FilterList as AnimatedFilterList;
@ -47,6 +47,49 @@ use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::effects::Filter; use values::generics::effects::Filter;
use values::generics::position as generic_position; use values::generics::position as generic_position;
/// A trait used to implement various procedures used during animation.
pub trait Animatable: Sized {
/// Performs a weighted sum of this value and |other|. This is used for
/// interpolation and addition of animation values.
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()>;
/// [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)
}
/// [Accumulates][animation-accumulation] this value onto itself (|count| - 1) times then
/// accumulates |other| onto the result.
/// If |count| is zero, the result will be |other|.
///
/// [animation-accumulation]: https://w3c.github.io/web-animations/#animation-accumulation
fn accumulate(&self, other: &Self, count: u64) -> Result<Self, ()> {
self.add_weighted(other, count as f64, 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)
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-repeatable-list
pub trait RepeatableListAnimatable: Animatable {}
/// A longhand property whose animation type is not "none". /// A longhand property whose animation type is not "none".
/// ///
@ -692,19 +735,6 @@ impl Animatable for AnimationValue {
} }
} }
fn get_zero_value(&self) -> Result<Self, ()> {
match *self {
% for prop in data.longhands:
% if prop.animatable and prop.animation_value_type != "discrete":
AnimationValue::${prop.camel_case}(ref base) => {
Ok(AnimationValue::${prop.camel_case}(base.get_zero_value()?))
},
% endif
% endfor
_ => Err(()),
}
}
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (self, other) { match (self, other) {
% for prop in data.longhands: % for prop in data.longhands:
@ -730,61 +760,22 @@ impl Animatable for AnimationValue {
} }
} }
impl ToAnimatedZero for AnimationValue {
/// A trait used to implement various procedures used during animation.
pub trait Animatable: Sized {
/// Performs a weighted sum of this value and |other|. This is used for
/// interpolation and addition of animation values.
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()>;
/// [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)
}
/// [Accumulates][animation-accumulation] this value onto itself (|count| - 1) times then
/// accumulates |other| onto the result.
/// If |count| is zero, the result will be |other|.
///
/// [animation-accumulation]: https://w3c.github.io/web-animations/#animation-accumulation
fn accumulate(&self, other: &Self, count: u64) -> Result<Self, ()> {
self.add_weighted(other, count as f64, 1.0)
}
/// 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.
#[inline] #[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Err(()) } fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
/// Compute distance between a value and another for a given property. % for prop in data.longhands:
fn compute_distance(&self, _other: &Self) -> Result<f64, ()> { Err(()) } % if prop.animatable and prop.animation_value_type != "discrete":
AnimationValue::${prop.camel_case}(ref base) => {
/// In order to compute the Euclidean distance of a list or property value with multiple Ok(AnimationValue::${prop.camel_case}(base.to_animated_zero()?))
/// 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. % endif
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> { % endfor
self.compute_distance(other).map(|d| d * d) _ => Err(()),
}
} }
} }
/// https://drafts.csswg.org/css-transitions/#animtype-repeatable-list
pub trait RepeatableListAnimatable: Animatable {}
impl RepeatableListAnimatable for LengthOrPercentage {} impl RepeatableListAnimatable for LengthOrPercentage {}
impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {} impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
@ -834,9 +825,6 @@ impl Animatable for Au {
Ok(Au((self.0 as f64 * self_portion + other.0 as f64 * other_portion).round() as i32)) Ok(Au((self.0 as f64 * self_portion + other.0 as f64 * other_portion).round() as i32))
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(Au(0)) }
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.0.compute_distance(&other.0) self.0.compute_distance(&other.0)
@ -887,9 +875,6 @@ impl Animatable for f32 {
Ok((*self as f64 * self_portion + *other as f64 * other_portion) as f32) Ok((*self as f64 * self_portion + *other as f64 * other_portion) as f32)
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(0.) }
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
Ok((*self - *other).abs() as f64) Ok((*self - *other).abs() as f64)
@ -903,9 +888,6 @@ impl Animatable for f64 {
Ok(*self * self_portion + *other * other_portion) Ok(*self * self_portion + *other * other_portion)
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(0.) }
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
Ok((*self - *other).abs()) Ok((*self - *other).abs())
@ -919,9 +901,6 @@ impl Animatable for i32 {
Ok((*self as f64 * self_portion + *other as f64 * other_portion).round() as i32) Ok((*self as f64 * self_portion + *other as f64 * other_portion).round() as i32)
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(0) }
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
Ok((*self - *other).abs() as f64) Ok((*self - *other).abs() as f64)
@ -956,15 +935,19 @@ impl Animatable for Percentage {
Ok(Percentage((self.0 as f64 * self_portion + other.0 as f64 * other_portion) as f32)) Ok(Percentage((self.0 as f64 * self_portion + other.0 as f64 * other_portion) as f32))
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(Percentage(0.)) }
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
Ok((self.0 as f64 - other.0 as f64).abs()) Ok((self.0 as f64 - other.0 as f64).abs())
} }
} }
impl ToAnimatedZero for Percentage {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(Percentage(0.))
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-visibility /// https://drafts.csswg.org/css-transitions/#animtype-visibility
impl Animatable for Visibility { impl Animatable for Visibility {
#[inline] #[inline]
@ -990,6 +973,13 @@ impl Animatable for Visibility {
} }
} }
impl ToAnimatedZero for Visibility {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Err(())
}
}
impl<T: Animatable + Copy> Animatable for Size2D<T> { impl<T: Animatable + Copy> Animatable for Size2D<T> {
#[inline] #[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
@ -1028,6 +1018,11 @@ impl Animatable for BorderCornerRadius {
} }
} }
impl ToAnimatedZero for BorderCornerRadius {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// https://drafts.csswg.org/css-transitions/#animtype-length /// https://drafts.csswg.org/css-transitions/#animtype-length
impl Animatable for VerticalAlign { impl Animatable for VerticalAlign {
#[inline] #[inline]
@ -1055,6 +1050,11 @@ impl Animatable for VerticalAlign {
} }
} }
impl ToAnimatedZero for VerticalAlign {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animatable for CalcLengthOrPercentage { impl Animatable for CalcLengthOrPercentage {
#[inline] #[inline]
@ -1125,11 +1125,6 @@ impl Animatable for LengthOrPercentage {
} }
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
Ok(LengthOrPercentage::zero())
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (*self, *other) { match (*self, *other) {
@ -1173,6 +1168,13 @@ impl Animatable for LengthOrPercentage {
} }
} }
impl ToAnimatedZero for LengthOrPercentage {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(LengthOrPercentage::zero())
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animatable for LengthOrPercentageOrAuto { impl Animatable for LengthOrPercentageOrAuto {
#[inline] #[inline]
@ -1202,18 +1204,6 @@ impl Animatable for LengthOrPercentageOrAuto {
} }
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
match *self {
LengthOrPercentageOrAuto::Length(_) |
LengthOrPercentageOrAuto::Percentage(_) |
LengthOrPercentageOrAuto::Calc(_) => {
Ok(LengthOrPercentageOrAuto::Length(Au(0)))
},
LengthOrPercentageOrAuto::Auto => Err(()),
}
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (*self, *other) { match (*self, *other) {
@ -1262,6 +1252,20 @@ impl Animatable for LengthOrPercentageOrAuto {
} }
} }
impl ToAnimatedZero for LengthOrPercentageOrAuto {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
LengthOrPercentageOrAuto::Length(_) |
LengthOrPercentageOrAuto::Percentage(_) |
LengthOrPercentageOrAuto::Calc(_) => {
Ok(LengthOrPercentageOrAuto::Length(Au(0)))
},
LengthOrPercentageOrAuto::Auto => Err(()),
}
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animatable for LengthOrPercentageOrNone { impl Animatable for LengthOrPercentageOrNone {
#[inline] #[inline]
@ -1291,18 +1295,6 @@ impl Animatable for LengthOrPercentageOrNone {
} }
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
match *self {
LengthOrPercentageOrNone::Length(_) |
LengthOrPercentageOrNone::Percentage(_) |
LengthOrPercentageOrNone::Calc(_) => {
Ok(LengthOrPercentageOrNone::Length(Au(0)))
},
LengthOrPercentageOrNone::None => Err(()),
}
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (*self, *other) { match (*self, *other) {
@ -1324,6 +1316,20 @@ impl Animatable for LengthOrPercentageOrNone {
} }
} }
impl ToAnimatedZero for LengthOrPercentageOrNone {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
LengthOrPercentageOrNone::Length(_) |
LengthOrPercentageOrNone::Percentage(_) |
LengthOrPercentageOrNone::Calc(_) => {
Ok(LengthOrPercentageOrNone::Length(Au(0)))
},
LengthOrPercentageOrNone::None => Err(()),
}
}
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animatable for MozLength { impl Animatable for MozLength {
#[inline] #[inline]
@ -1350,6 +1356,11 @@ impl Animatable for MozLength {
} }
} }
impl ToAnimatedZero for MozLength {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animatable for MaxLength { impl Animatable for MaxLength {
#[inline] #[inline]
@ -1376,6 +1387,11 @@ impl Animatable for MaxLength {
} }
} }
impl ToAnimatedZero for MaxLength {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// http://dev.w3.org/csswg/css-transitions/#animtype-font-weight /// http://dev.w3.org/csswg/css-transitions/#animtype-font-weight
impl Animatable for FontWeight { impl Animatable for FontWeight {
#[inline] #[inline]
@ -1388,9 +1404,6 @@ impl Animatable for FontWeight {
Ok(FontWeight(weight as u16)) Ok(FontWeight(weight as u16))
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(FontWeight::normal()) }
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
let a = self.0 as f64; let a = self.0 as f64;
@ -1399,6 +1412,13 @@ impl Animatable for FontWeight {
} }
} }
impl ToAnimatedZero for FontWeight {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(FontWeight::normal())
}
}
/// https://drafts.csswg.org/css-fonts/#font-stretch-prop /// https://drafts.csswg.org/css-fonts/#font-stretch-prop
impl Animatable for FontStretch { impl Animatable for FontStretch {
#[inline] #[inline]
@ -1422,6 +1442,11 @@ impl Animatable for FontStretch {
} }
} }
impl ToAnimatedZero for FontStretch {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// We should treat font stretch as real number in order to interpolate this property. /// We should treat font stretch as real number in order to interpolate this property.
/// https://drafts.csswg.org/css-fonts-3/#font-stretch-animation /// https://drafts.csswg.org/css-fonts-3/#font-stretch-animation
impl From<FontStretch> for f64 { impl From<FontStretch> for f64 {
@ -1462,14 +1487,6 @@ impl<H: Animatable, V: Animatable> Animatable for generic_position::Position<H,
}) })
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
Ok(generic_position::Position {
horizontal: self.horizontal.get_zero_value()?,
vertical: self.vertical.get_zero_value()?,
})
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt()) self.compute_squared_distance(other).map(|sd| sd.sqrt())
@ -1482,6 +1499,20 @@ impl<H: Animatable, V: Animatable> Animatable for generic_position::Position<H,
} }
} }
impl<H, V> ToAnimatedZero for generic_position::Position<H, V>
where
H: ToAnimatedZero,
V: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(generic_position::Position {
horizontal: self.horizontal.to_animated_zero()?,
vertical: self.vertical.to_animated_zero()?,
})
}
}
impl<H, V> RepeatableListAnimatable for generic_position::Position<H, V> impl<H, V> RepeatableListAnimatable for generic_position::Position<H, V>
where H: RepeatableListAnimatable, V: RepeatableListAnimatable {} where H: RepeatableListAnimatable, V: RepeatableListAnimatable {}
@ -1515,6 +1546,11 @@ impl Animatable for ClipRect {
} }
} }
impl ToAnimatedZero for ClipRect {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// Check if it's possible to do a direct numerical interpolation /// Check if it's possible to do a direct numerical interpolation
/// between these two transform lists. /// between these two transform lists.
/// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation /// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
@ -2589,9 +2625,13 @@ impl Animatable for TransformList {
} }
} }
} }
}
impl ToAnimatedZero for TransformList {
#[inline] #[inline]
fn get_zero_value(&self) -> Result<Self, ()> { Ok(TransformList(None)) } fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(TransformList(None))
}
} }
impl<T, U> Animatable for Either<T, U> impl<T, U> Animatable for Either<T, U>
@ -2613,18 +2653,6 @@ impl<T, U> Animatable for Either<T, U>
} }
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
match *self {
Either::First(ref this) => {
Ok(Either::First(this.get_zero_value()?))
},
Either::Second(ref this) => {
Ok(Either::Second(this.get_zero_value()?))
},
}
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (self, other) { match (self, other) {
@ -2652,6 +2680,24 @@ impl<T, U> Animatable for Either<T, U>
} }
} }
impl<A, B> ToAnimatedZero for Either<A, B>
where
A: ToAnimatedZero,
B: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
Either::First(ref first) => {
Ok(Either::First(first.to_animated_zero()?))
},
Either::Second(ref second) => {
Ok(Either::Second(second.to_animated_zero()?))
},
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// Unlike RGBA, each component value may exceed the range [0.0, 1.0]. /// Unlike RGBA, each component value may exceed the range [0.0, 1.0].
@ -2730,11 +2776,6 @@ impl Animatable for IntermediateRGBA {
} }
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
Ok(IntermediateRGBA::transparent())
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sq| sq.sqrt()) self.compute_squared_distance(other).map(|sq| sq.sqrt())
@ -2759,6 +2800,13 @@ impl Animatable for IntermediateRGBA {
} }
} }
impl ToAnimatedZero for IntermediateRGBA {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(IntermediateRGBA::transparent())
}
}
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
@ -2897,6 +2945,11 @@ impl Animatable for IntermediateColor {
} }
} }
impl ToAnimatedZero for IntermediateColor {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// Animatable SVGPaint /// Animatable SVGPaint
pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>; pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>;
@ -2922,12 +2975,14 @@ impl Animatable for IntermediateSVGPaint {
Ok(self.kind.compute_squared_distance(&other.kind)? + Ok(self.kind.compute_squared_distance(&other.kind)? +
self.fallback.compute_squared_distance(&other.fallback)?) self.fallback.compute_squared_distance(&other.fallback)?)
} }
}
impl ToAnimatedZero for IntermediateSVGPaint {
#[inline] #[inline]
fn get_zero_value(&self) -> Result<Self, ()> { fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(IntermediateSVGPaint { Ok(IntermediateSVGPaint {
kind: self.kind.get_zero_value()?, kind: self.kind.to_animated_zero()?,
fallback: self.fallback.and_then(|v| v.get_zero_value().ok()), fallback: self.fallback.and_then(|v| v.to_animated_zero().ok()),
}) })
} }
} }
@ -2960,12 +3015,14 @@ impl Animatable for IntermediateSVGPaintKind {
_ => Err(()) _ => Err(())
} }
} }
}
impl ToAnimatedZero for IntermediateSVGPaintKind {
#[inline] #[inline]
fn get_zero_value(&self) -> Result<Self, ()> { fn to_animated_zero(&self) -> Result<Self, ()> {
match *self { match *self {
SVGPaintKind::Color(ref color) => { SVGPaintKind::Color(ref color) => {
Ok(SVGPaintKind::Color(color.get_zero_value()?)) Ok(SVGPaintKind::Color(color.to_animated_zero()?))
}, },
SVGPaintKind::None | SVGPaintKind::None |
SVGPaintKind::ContextFill | SVGPaintKind::ContextFill |

View file

@ -1044,6 +1044,7 @@ ${helpers.single_keyword_system("font-variant-caps",
pub mod computed_value { pub mod computed_value {
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
use values::CSSFloat; use values::CSSFloat;
use values::animated::ToAnimatedZero;
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Copy, Clone, Debug, PartialEq, ToCss)] #[derive(Copy, Clone, Debug, PartialEq, ToCss)]
@ -1081,6 +1082,11 @@ ${helpers.single_keyword_system("font-variant-caps",
} }
} }
} }
impl ToAnimatedZero for T {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
} }
#[inline] #[inline]

View file

@ -28,6 +28,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
pub mod computed_value { pub mod computed_value {
use app_units::Au; use app_units::Au;
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
use values::animated::ToAnimatedZero;
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, PartialEq, ToCss)]
@ -60,6 +61,11 @@ ${helpers.single_keyword("caption-side", "top bottom",
self.vertical.compute_squared_distance(&other.vertical)?) self.vertical.compute_squared_distance(&other.vertical)?)
} }
} }
impl ToAnimatedZero for T {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
} }
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View file

@ -11,7 +11,7 @@ use properties::longhands::text_shadow::computed_value::T as ComputedTextShadowL
use std::cmp; use std::cmp;
#[cfg(not(feature = "gecko"))] #[cfg(not(feature = "gecko"))]
use values::Impossible; use values::Impossible;
use values::animated::ToAnimatedValue; use values::animated::{ToAnimatedValue, ToAnimatedZero};
use values::computed::{Angle, Number}; use values::computed::{Angle, Number};
use values::computed::length::Length; use values::computed::length::Length;
use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::BoxShadow as GenericBoxShadow;
@ -66,7 +66,7 @@ impl ToAnimatedValue for ComputedBoxShadowList {
impl<S> Animatable for ShadowList<S> impl<S> Animatable for ShadowList<S>
where where
S: Animatable + Clone, S: Animatable + Clone + ToAnimatedZero,
{ {
#[inline] #[inline]
fn add_weighted( fn add_weighted(
@ -83,10 +83,10 @@ where
shadow.add_weighted(other, self_portion, other_portion)? shadow.add_weighted(other, self_portion, other_portion)?
}, },
(Some(shadow), None) => { (Some(shadow), None) => {
shadow.add_weighted(&shadow.get_zero_value()?, self_portion, other_portion)? shadow.add_weighted(&shadow.to_animated_zero()?, self_portion, other_portion)?
}, },
(None, Some(shadow)) => { (None, Some(shadow)) => {
shadow.get_zero_value()?.add_weighted(&shadow, self_portion, other_portion)? shadow.to_animated_zero()?.add_weighted(&shadow, self_portion, other_portion)?
}, },
(None, None) => unreachable!(), (None, None) => unreachable!(),
}); });
@ -102,6 +102,13 @@ where
} }
} }
impl<S> ToAnimatedZero for ShadowList<S> {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(ShadowList(vec![]))
}
}
impl ToAnimatedValue for ComputedTextShadowList { impl ToAnimatedValue for ComputedTextShadowList {
type AnimatedValue = TextShadowList; type AnimatedValue = TextShadowList;
@ -134,15 +141,6 @@ impl Animatable for BoxShadow {
}) })
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
Ok(BoxShadow {
base: self.base.get_zero_value()?,
spread: self.spread.get_zero_value()?,
inset: self.inset,
})
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt()) self.compute_squared_distance(other).map(|sd| sd.sqrt())
@ -160,6 +158,17 @@ impl Animatable for BoxShadow {
} }
} }
impl ToAnimatedZero for BoxShadow {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(BoxShadow {
base: self.base.to_animated_zero()?,
spread: self.spread.to_animated_zero()?,
inset: self.inset,
})
}
}
impl ToAnimatedValue for ComputedFilterList { impl ToAnimatedValue for ComputedFilterList {
type AnimatedValue = FilterList; type AnimatedValue = FilterList;
@ -188,6 +197,13 @@ impl ToAnimatedValue for ComputedFilterList {
} }
} }
impl ToAnimatedZero for FilterList {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(FilterList(vec![]))
}
}
impl Animatable for SimpleShadow { impl Animatable for SimpleShadow {
#[inline] #[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
@ -204,16 +220,6 @@ impl Animatable for SimpleShadow {
}) })
} }
#[inline]
fn get_zero_value(&self) -> Result<Self, ()> {
Ok(SimpleShadow {
color: IntermediateColor::transparent(),
horizontal: self.horizontal.get_zero_value()?,
vertical: self.vertical.get_zero_value()?,
blur: self.blur.get_zero_value()?,
})
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt()) self.compute_squared_distance(other).map(|sd| sd.sqrt())
@ -229,3 +235,15 @@ impl Animatable for SimpleShadow {
) )
} }
} }
impl ToAnimatedZero for SimpleShadow {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(SimpleShadow {
color: IntermediateColor::transparent(),
horizontal: self.horizontal.to_animated_zero()?,
vertical: self.vertical.to_animated_zero()?,
blur: self.blur.to_animated_zero()?,
})
}
}

View file

@ -88,3 +88,34 @@ where
} }
} }
/// 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)) }
}
impl ToAnimatedZero for f32 {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Ok(0.) }
}
impl ToAnimatedZero for f64 {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Ok(0.) }
}
impl ToAnimatedZero for i32 {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Ok(0) }
}

View file

@ -5,6 +5,7 @@
//! Computed types for CSS values related to backgrounds. //! Computed types for CSS values related to backgrounds.
use properties::animated_properties::{Animatable, RepeatableListAnimatable}; use properties::animated_properties::{Animatable, RepeatableListAnimatable};
use values::animated::ToAnimatedZero;
use values::computed::length::LengthOrPercentageOrAuto; use values::computed::length::LengthOrPercentageOrAuto;
use values::generics::background::BackgroundSize as GenericBackgroundSize; use values::generics::background::BackgroundSize as GenericBackgroundSize;
@ -50,3 +51,8 @@ impl Animatable for BackgroundSize {
} }
} }
} }
impl ToAnimatedZero for BackgroundSize {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}

View file

@ -7,6 +7,7 @@
use app_units::Au; use app_units::Au;
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
use values::{CSSInteger, CSSFloat}; use values::{CSSInteger, CSSFloat};
use values::animated::ToAnimatedZero;
use values::computed::length::{Length, LengthOrPercentage}; use values::computed::length::{Length, LengthOrPercentage};
use values::generics::text::InitialLetter as GenericInitialLetter; use values::generics::text::InitialLetter as GenericInitialLetter;
use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::LineHeight as GenericLineHeight;
@ -61,3 +62,8 @@ impl Animatable for LineHeight {
} }
} }
} }
impl ToAnimatedZero for LineHeight {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}

View file

@ -5,6 +5,7 @@
//! Computed types for CSS values that are related to transformations. //! Computed types for CSS values that are related to transformations.
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
use values::animated::ToAnimatedZero;
use values::computed::{Length, LengthOrPercentage, Number, Percentage}; use values::computed::{Length, LengthOrPercentage, Number, Percentage};
use values::generics::transform::TimingFunction as GenericTimingFunction; use values::generics::transform::TimingFunction as GenericTimingFunction;
use values::generics::transform::TransformOrigin as GenericTransformOrigin; use values::generics::transform::TransformOrigin as GenericTransformOrigin;
@ -51,3 +52,14 @@ impl Animatable for TransformOrigin {
) )
} }
} }
impl ToAnimatedZero for TransformOrigin {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(Self::new(
self.horizontal.to_animated_zero()?,
self.vertical.to_animated_zero()?,
self.depth.to_animated_zero()?,
))
}
}

View file

@ -9,6 +9,7 @@ use cssparser::Parser;
use parser::ParserContext; use parser::ParserContext;
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
use style_traits::ParseError; use style_traits::ParseError;
use values::animated::ToAnimatedZero;
/// A generic value for the `initial-letter` property. /// A generic value for the `initial-letter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -93,6 +94,14 @@ impl<Value> Animatable for Spacing<Value>
} }
} }
impl<V> ToAnimatedZero for Spacing<V>
where
V: From<Au>,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// A generic value for the `line-height` property. /// A generic value for the `line-height` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToCss)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToCss)]

View file

@ -4,7 +4,6 @@
//! Generic types for CSS values that are related to transformations. //! Generic types for CSS values that are related to transformations.
use euclid::Point2D;
use std::fmt; use std::fmt;
use style_traits::{HasViewportPercentage, ToCss}; use style_traits::{HasViewportPercentage, ToCss};
use values::CSSFloat; use values::CSSFloat;
@ -44,7 +43,8 @@ pub enum TimingFunction<Integer, Number> {
/// `linear | ease | ease-in | ease-out | ease-in-out` /// `linear | ease | ease-in | ease-out | ease-in-out`
Keyword(TimingKeyword), Keyword(TimingKeyword),
/// `cubic-bezier(<number>, <number>, <number>, <number>)` /// `cubic-bezier(<number>, <number>, <number>, <number>)`
CubicBezier(Point2D<Number>, Point2D<Number>), #[allow(missing_docs)]
CubicBezier { x1: Number, y1: Number, x2: Number, y2: Number },
/// `step-start | step-end | steps(<integer>, [ start | end ]?)` /// `step-start | step-end | steps(<integer>, [ start | end ]?)`
Steps(Integer, StepPosition), Steps(Integer, StepPosition),
/// `frames(<integer>)` /// `frames(<integer>)`
@ -100,15 +100,15 @@ where
{ {
match *self { match *self {
TimingFunction::Keyword(keyword) => keyword.to_css(dest), TimingFunction::Keyword(keyword) => keyword.to_css(dest),
TimingFunction::CubicBezier(ref p1, ref p2) => { TimingFunction::CubicBezier { ref x1, ref y1, ref x2, ref y2 } => {
dest.write_str("cubic-bezier(")?; dest.write_str("cubic-bezier(")?;
p1.x.to_css(dest)?; x1.to_css(dest)?;
dest.write_str(", ")?; dest.write_str(", ")?;
p1.y.to_css(dest)?; y1.to_css(dest)?;
dest.write_str(", ")?; dest.write_str(", ")?;
p2.x.to_css(dest)?; x2.to_css(dest)?;
dest.write_str(", ")?; dest.write_str(", ")?;
p2.y.to_css(dest)?; y2.to_css(dest)?;
dest.write_str(")") dest.write_str(")")
}, },
TimingFunction::Steps(ref intervals, position) => { TimingFunction::Steps(ref intervals, position) => {
@ -130,15 +130,16 @@ where
} }
impl TimingKeyword { impl TimingKeyword {
/// Returns this timing keyword as a pair of `cubic-bezier()` points. /// Returns the keyword as a quadruplet of Bezier point coordinates
/// `(x1, y1, x2, y2)`.
#[inline] #[inline]
pub fn to_bezier_points(self) -> (Point2D<CSSFloat>, Point2D<CSSFloat>) { pub fn to_bezier(self) -> (CSSFloat, CSSFloat, CSSFloat, CSSFloat) {
match self { match self {
TimingKeyword::Linear => (Point2D::new(0., 0.), Point2D::new(1., 1.)), TimingKeyword::Linear => (0., 0., 1., 1.),
TimingKeyword::Ease => (Point2D::new(0.25, 0.1), Point2D::new(0.25, 1.)), TimingKeyword::Ease => (0.25, 0.1, 0.25, 1.),
TimingKeyword::EaseIn => (Point2D::new(0.42, 0.), Point2D::new(1., 1.)), TimingKeyword::EaseIn => (0.42, 0., 1., 1.),
TimingKeyword::EaseOut => (Point2D::new(0., 0.), Point2D::new(0.58, 1.)), TimingKeyword::EaseOut => (0., 0., 0.58, 1.),
TimingKeyword::EaseInOut => (Point2D::new(0.42, 0.), Point2D::new(0.58, 1.)), TimingKeyword::EaseInOut => (0.42, 0., 0.58, 1.),
} }
} }
} }

View file

@ -5,7 +5,6 @@
//! Specified types for CSS values that are related to transformations. //! Specified types for CSS values that are related to transformations.
use cssparser::Parser; use cssparser::Parser;
use euclid::Point2D;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError; use selectors::parser::SelectorParseError;
use style_traits::{ParseError, StyleParseError}; use style_traits::{ParseError, StyleParseError};
@ -160,20 +159,19 @@ impl Parse for TimingFunction {
input.parse_nested_block(move |i| { input.parse_nested_block(move |i| {
(match_ignore_ascii_case! { &function, (match_ignore_ascii_case! { &function,
"cubic-bezier" => { "cubic-bezier" => {
let p1x = Number::parse(context, i)?; let x1 = Number::parse(context, i)?;
i.expect_comma()?; i.expect_comma()?;
let p1y = Number::parse(context, i)?; let y1 = Number::parse(context, i)?;
i.expect_comma()?; i.expect_comma()?;
let p2x = Number::parse(context, i)?; let x2 = Number::parse(context, i)?;
i.expect_comma()?; i.expect_comma()?;
let p2y = Number::parse(context, i)?; let y2 = Number::parse(context, i)?;
if p1x.get() < 0.0 || p1x.get() > 1.0 || p2x.get() < 0.0 || p2x.get() > 1.0 { if x1.get() < 0.0 || x1.get() > 1.0 || x2.get() < 0.0 || x2.get() > 1.0 {
return Err(StyleParseError::UnspecifiedError.into()); return Err(StyleParseError::UnspecifiedError.into());
} }
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y)); Ok(GenericTimingFunction::CubicBezier { x1, y1, x2, y2 })
Ok(GenericTimingFunction::CubicBezier(p1, p2))
}, },
"steps" => { "steps" => {
let steps = Integer::parse_positive(context, i)?; let steps = Integer::parse_positive(context, i)?;
@ -206,17 +204,13 @@ impl ToComputedValue for TimingFunction {
GenericTimingFunction::Keyword(keyword) => { GenericTimingFunction::Keyword(keyword) => {
GenericTimingFunction::Keyword(keyword) GenericTimingFunction::Keyword(keyword)
}, },
GenericTimingFunction::CubicBezier(p1, p2) => { GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
GenericTimingFunction::CubicBezier( GenericTimingFunction::CubicBezier {
Point2D::new( x1: x1.to_computed_value(context),
p1.x.to_computed_value(context), y1: y1.to_computed_value(context),
p1.y.to_computed_value(context), x2: x2.to_computed_value(context),
), y2: y2.to_computed_value(context),
Point2D::new( }
p2.x.to_computed_value(context),
p2.y.to_computed_value(context),
),
)
}, },
GenericTimingFunction::Steps(steps, position) => { GenericTimingFunction::Steps(steps, position) => {
GenericTimingFunction::Steps( GenericTimingFunction::Steps(
@ -238,17 +232,13 @@ impl ToComputedValue for TimingFunction {
GenericTimingFunction::Keyword(keyword) => { GenericTimingFunction::Keyword(keyword) => {
GenericTimingFunction::Keyword(keyword) GenericTimingFunction::Keyword(keyword)
}, },
GenericTimingFunction::CubicBezier(p1, p2) => { GenericTimingFunction::CubicBezier { ref x1, ref y1, ref x2, ref y2 } => {
GenericTimingFunction::CubicBezier( GenericTimingFunction::CubicBezier {
Point2D::new( x1: Number::from_computed_value(x1),
Number::from_computed_value(&p1.x), y1: Number::from_computed_value(y1),
Number::from_computed_value(&p1.y), x2: Number::from_computed_value(x2),
), y2: Number::from_computed_value(y2),
Point2D::new( }
Number::from_computed_value(&p2.x),
Number::from_computed_value(&p2.y),
),
)
}, },
GenericTimingFunction::Steps(steps, position) => { GenericTimingFunction::Steps(steps, position) => {
GenericTimingFunction::Steps( GenericTimingFunction::Steps(

View file

@ -117,6 +117,7 @@ use style::traversal::{ANIMATION_ONLY, DomTraversal, FOR_CSS_RULE_CHANGES, FOR_R
use style::traversal::{TraversalDriver, TraversalFlags, UNSTYLED_CHILDREN_ONLY}; use style::traversal::{TraversalDriver, TraversalFlags, UNSTYLED_CHILDREN_ONLY};
use style::traversal::resolve_style; use style::traversal::resolve_style;
use style::values::{CustomIdent, KeyframesName}; use style::values::{CustomIdent, KeyframesName};
use style::values::animated::ToAnimatedZero;
use style::values::computed::Context; use style::values::computed::Context;
use style_traits::{PARSING_MODE_DEFAULT, ToCss}; use style_traits::{PARSING_MODE_DEFAULT, ToCss};
use super::error_reporter::ErrorReporter; use super::error_reporter::ErrorReporter;
@ -375,7 +376,7 @@ pub extern "C" fn Servo_AnimationValues_GetZeroValue(
-> RawServoAnimationValueStrong -> RawServoAnimationValueStrong
{ {
let value_to_match = AnimationValue::as_arc(&value_to_match); let value_to_match = AnimationValue::as_arc(&value_to_match);
if let Ok(zero_value) = value_to_match.get_zero_value() { if let Ok(zero_value) = value_to_match.to_animated_zero() {
Arc::new(zero_value).into_strong() Arc::new(zero_value).into_strong()
} else { } else {
RawServoAnimationValueStrong::null() RawServoAnimationValueStrong::null()

View file

@ -4,7 +4,7 @@
use app_units::Au; use app_units::Au;
use cssparser::RGBA; use cssparser::RGBA;
use style::properties::animated_properties::{Animatable, IntermediateRGBA}; use style::properties::animated_properties::Animatable;
use style::properties::longhands::transform::computed_value::ComputedOperation as TransformOperation; use style::properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
use style::properties::longhands::transform::computed_value::T as TransformList; use style::properties::longhands::transform::computed_value::T as TransformList;
use style::values::animated::ToAnimatedValue; use style::values::animated::ToAnimatedValue;