Don't use Point2D<f32> for cubic curves anymore

This commit is contained in:
Anthony Ramine 2017-07-17 16:29:47 +02:00
parent e57ed3d42f
commit 5ffa523ccd
5 changed files with 70 additions and 83 deletions

View file

@ -9,7 +9,6 @@ use Atom;
use bezier::Bezier;
use context::SharedStyleContext;
use dom::OpaqueNode;
use euclid::Point2D;
use font_metrics::FontMetricsProvider;
use properties::{self, CascadeFlags, ComputedValues, ComputedValuesInner, Importance};
use properties::animated_properties::{AnimatableLonghand, AnimatedProperty, TransitionProperty};
@ -369,18 +368,10 @@ impl PropertyAnimation {
/// Update the given animation at a given point of progress.
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 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 epsilon = 1. / (200. * (self.duration.seconds() as f64));
let progress = match self.timing_function {
GenericTimingFunction::CubicBezier(p1, p2) => {
solve_bezier((p1, p2))
GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
Bezier::new(x1, y1, x2, y2).solve(time, epsilon)
},
GenericTimingFunction::Steps(steps, StepPosition::Start) => {
(time * (steps as f64)).ceil() / (steps as f64)
@ -405,7 +396,8 @@ impl PropertyAnimation {
out
},
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)]
use euclid::Point2D;
use values::CSSFloat;
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
/// starts at 0% and ends at 100%.
#[inline]
pub fn new(p1: Point2D<f64>, p2: Point2D<f64>) -> Bezier {
let cx = 3.0 * p1.x;
let bx = 3.0 * (p2.x - p1.x) - cx;
pub fn new(x1: CSSFloat, y1: CSSFloat, x2: CSSFloat, y2: CSSFloat) -> Bezier {
let cx = 3. * x1 as f64;
let bx = 3. * (x2 as f64 - x1 as f64) - cx;
let cy = 3.0 * p1.y;
let by = 3.0 * (p2.y - p1.y) - cy;
let cy = 3. * y1 as f64;
let by = 3. * (y2 as f64 - y1 as f64) - cy;
Bezier {
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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use euclid::{Point2D, TypedPoint2D};
use gecko_bindings::structs::{nsTimingFunction, nsTimingFunction_Type};
use std::mem;
use values::computed::ToComputedValue;
@ -28,18 +27,19 @@ impl nsTimingFunction {
}
}
fn set_as_bezier(&mut self,
function_type: nsTimingFunction_Type,
p1: Point2D<f32>,
p2: Point2D<f32>) {
fn set_as_bezier(
&mut self,
function_type: nsTimingFunction_Type,
x1: f32, y1: f32, x2: f32, y2: f32,
) {
self.mType = function_type;
unsafe {
let ref mut gecko_cubic_bezier =
unsafe { self.__bindgen_anon_1.mFunc.as_mut() };
gecko_cubic_bezier.mX1 = p1.x;
gecko_cubic_bezier.mY1 = p1.y;
gecko_cubic_bezier.mX2 = p2.x;
gecko_cubic_bezier.mY2 = p2.y;
gecko_cubic_bezier.mX1 = x1;
gecko_cubic_bezier.mY1 = y1;
gecko_cubic_bezier.mX2 = x2;
gecko_cubic_bezier.mY2 = y2;
}
}
}
@ -67,14 +67,15 @@ impl From<TimingFunction> for nsTimingFunction {
debug_assert!(frames.value() >= 2);
tf.set_as_frames(frames.value() as u32);
},
GenericTimingFunction::CubicBezier(p1, p2) => {
tf.set_as_bezier(nsTimingFunction_Type::CubicBezier,
Point2D::new(p1.x.get(), p1.y.get()),
Point2D::new(p2.x.get(), p2.y.get()));
GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
tf.set_as_bezier(
nsTimingFunction_Type::CubicBezier,
x1.get(), y1.get(), x2.get(), y2.get(),
);
},
GenericTimingFunction::Keyword(keyword) => {
let (p1, p2) = keyword.to_bezier_points();
tf.set_as_bezier(keyword.into(), p1, p2)
let (x1, y1, x2, y2) = keyword.to_bezier();
tf.set_as_bezier(keyword.into(), x1, y1, x2, y2);
},
}
tf
@ -114,11 +115,14 @@ impl From<nsTimingFunction> for ComputedTimingFunction {
GenericTimingFunction::Keyword(TimingKeyword::EaseInOut)
},
nsTimingFunction_Type::CubicBezier => {
GenericTimingFunction::CubicBezier(
TypedPoint2D::new(unsafe { function.__bindgen_anon_1.mFunc.as_ref().mX1 },
unsafe { function.__bindgen_anon_1.mFunc.as_ref().mY1 }),
TypedPoint2D::new(unsafe { function.__bindgen_anon_1.mFunc.as_ref().mX2 },
unsafe { function.__bindgen_anon_1.mFunc.as_ref().mY2 }))
unsafe {
GenericTimingFunction::CubicBezier {
x1: function.__bindgen_anon_1.mFunc.as_ref().mX1,
y1: function.__bindgen_anon_1.mFunc.as_ref().mY1,
x2: function.__bindgen_anon_1.mFunc.as_ref().mX2,
y2: function.__bindgen_anon_1.mFunc.as_ref().mY2,
}
}
},
}
}

View file

@ -4,7 +4,6 @@
//! Generic types for CSS values that are related to transformations.
use euclid::Point2D;
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use values::CSSFloat;
@ -44,7 +43,8 @@ pub enum TimingFunction<Integer, Number> {
/// `linear | ease | ease-in | ease-out | ease-in-out`
Keyword(TimingKeyword),
/// `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 ]?)`
Steps(Integer, StepPosition),
/// `frames(<integer>)`
@ -100,15 +100,15 @@ where
{
match *self {
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(")?;
p1.x.to_css(dest)?;
x1.to_css(dest)?;
dest.write_str(", ")?;
p1.y.to_css(dest)?;
y1.to_css(dest)?;
dest.write_str(", ")?;
p2.x.to_css(dest)?;
x2.to_css(dest)?;
dest.write_str(", ")?;
p2.y.to_css(dest)?;
y2.to_css(dest)?;
dest.write_str(")")
},
TimingFunction::Steps(ref intervals, position) => {
@ -130,15 +130,16 @@ where
}
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]
pub fn to_bezier_points(self) -> (Point2D<CSSFloat>, Point2D<CSSFloat>) {
pub fn to_bezier(self) -> (CSSFloat, CSSFloat, CSSFloat, CSSFloat) {
match self {
TimingKeyword::Linear => (Point2D::new(0., 0.), Point2D::new(1., 1.)),
TimingKeyword::Ease => (Point2D::new(0.25, 0.1), Point2D::new(0.25, 1.)),
TimingKeyword::EaseIn => (Point2D::new(0.42, 0.), Point2D::new(1., 1.)),
TimingKeyword::EaseOut => (Point2D::new(0., 0.), Point2D::new(0.58, 1.)),
TimingKeyword::EaseInOut => (Point2D::new(0.42, 0.), Point2D::new(0.58, 1.)),
TimingKeyword::Linear => (0., 0., 1., 1.),
TimingKeyword::Ease => (0.25, 0.1, 0.25, 1.),
TimingKeyword::EaseIn => (0.42, 0., 1., 1.),
TimingKeyword::EaseOut => (0., 0., 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.
use cssparser::Parser;
use euclid::Point2D;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use style_traits::{ParseError, StyleParseError};
@ -160,20 +159,19 @@ impl Parse for TimingFunction {
input.parse_nested_block(move |i| {
(match_ignore_ascii_case! { &function,
"cubic-bezier" => {
let p1x = Number::parse(context, i)?;
let x1 = Number::parse(context, i)?;
i.expect_comma()?;
let p1y = Number::parse(context, i)?;
let y1 = Number::parse(context, i)?;
i.expect_comma()?;
let p2x = Number::parse(context, i)?;
let x2 = Number::parse(context, i)?;
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());
}
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
Ok(GenericTimingFunction::CubicBezier(p1, p2))
Ok(GenericTimingFunction::CubicBezier { x1, y1, x2, y2 })
},
"steps" => {
let steps = Integer::parse_positive(context, i)?;
@ -206,17 +204,13 @@ impl ToComputedValue for TimingFunction {
GenericTimingFunction::Keyword(keyword) => {
GenericTimingFunction::Keyword(keyword)
},
GenericTimingFunction::CubicBezier(p1, p2) => {
GenericTimingFunction::CubicBezier(
Point2D::new(
p1.x.to_computed_value(context),
p1.y.to_computed_value(context),
),
Point2D::new(
p2.x.to_computed_value(context),
p2.y.to_computed_value(context),
),
)
GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
GenericTimingFunction::CubicBezier {
x1: x1.to_computed_value(context),
y1: y1.to_computed_value(context),
x2: x2.to_computed_value(context),
y2: y2.to_computed_value(context),
}
},
GenericTimingFunction::Steps(steps, position) => {
GenericTimingFunction::Steps(
@ -238,17 +232,13 @@ impl ToComputedValue for TimingFunction {
GenericTimingFunction::Keyword(keyword) => {
GenericTimingFunction::Keyword(keyword)
},
GenericTimingFunction::CubicBezier(p1, p2) => {
GenericTimingFunction::CubicBezier(
Point2D::new(
Number::from_computed_value(&p1.x),
Number::from_computed_value(&p1.y),
),
Point2D::new(
Number::from_computed_value(&p2.x),
Number::from_computed_value(&p2.y),
),
)
GenericTimingFunction::CubicBezier { ref x1, ref y1, ref x2, ref y2 } => {
GenericTimingFunction::CubicBezier {
x1: Number::from_computed_value(x1),
y1: Number::from_computed_value(y1),
x2: Number::from_computed_value(x2),
y2: Number::from_computed_value(y2),
}
},
GenericTimingFunction::Steps(steps, position) => {
GenericTimingFunction::Steps(