mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1848170
: Use fully-computed piecewise linear function for both computed and specified value. r=emilio
Later spec change specifies that the serialized value always has one input and one output entries for each linear stop entry, so specified and computed values no longer have any difference. Get rid of prefs for WPT too, since they're default-enabled on on channels. Differential Revision: https://phabricator.services.mozilla.com/D186021
This commit is contained in:
parent
833ce835ea
commit
19eba0b7a1
@ -24,6 +24,7 @@ type ValueType = CSSFloat;
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
@ -54,6 +55,7 @@ impl ToCss for PiecewiseLinearFunctionEntry {
|
||||
SpecifiedValueInfo,
|
||||
ToResolvedValue,
|
||||
ToCss,
|
||||
ToShmem,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
@ -61,7 +63,9 @@ impl ToCss for PiecewiseLinearFunctionEntry {
|
||||
#[css(comma)]
|
||||
pub struct PiecewiseLinearFunction {
|
||||
#[css(iterable)]
|
||||
entries: crate::OwnedSlice<PiecewiseLinearFunctionEntry>,
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
#[shmem(field_bound)]
|
||||
entries: crate::ArcSlice<PiecewiseLinearFunctionEntry>,
|
||||
}
|
||||
|
||||
/// Parameters to define one linear stop.
|
||||
@ -133,18 +137,6 @@ impl PiecewiseLinearFunction {
|
||||
unreachable!("Input is supposed to be within the entries' min & max!");
|
||||
}
|
||||
|
||||
/// Create the piecewise linear function from an iterator that generates the parameter tuple.
|
||||
pub fn from_iter<Iter>(iter: Iter) -> Self
|
||||
where
|
||||
Iter: Iterator<Item = PiecewiseLinearFunctionBuildParameters> + ExactSizeIterator,
|
||||
{
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::with_capacity(iter.len());
|
||||
for (y, x_start) in iter {
|
||||
builder = builder.push(y, x_start);
|
||||
}
|
||||
builder.build()
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn iter(&self) -> Iter<PiecewiseLinearFunctionEntry> {
|
||||
self.entries.iter()
|
||||
@ -167,11 +159,6 @@ pub struct PiecewiseLinearFunctionBuilder {
|
||||
}
|
||||
|
||||
impl PiecewiseLinearFunctionBuilder {
|
||||
#[allow(missing_docs)]
|
||||
pub fn new() -> Self {
|
||||
PiecewiseLinearFunctionBuilder::default()
|
||||
}
|
||||
|
||||
/// Create a builder for a known amount of linear stop entries.
|
||||
pub fn with_capacity(len: usize) -> Self {
|
||||
PiecewiseLinearFunctionBuilder {
|
||||
@ -208,9 +195,8 @@ impl PiecewiseLinearFunctionBuilder {
|
||||
/// the x value is calculated later. If the end x value is specified, a flat segment
|
||||
/// is generated. If start x value is not specified but end x is, it is treated as
|
||||
/// start x.
|
||||
pub fn push(mut self, y: CSSFloat, x_start: Option<CSSFloat>) -> Self {
|
||||
self.create_entry(y, x_start);
|
||||
self
|
||||
pub fn push(&mut self, y: CSSFloat, x_start: Option<CSSFloat>) {
|
||||
self.create_entry(y, x_start)
|
||||
}
|
||||
|
||||
/// Finish building the piecewise linear function by resolving all undefined x values,
|
||||
@ -222,10 +208,10 @@ impl PiecewiseLinearFunctionBuilder {
|
||||
if self.entries.len() == 1 {
|
||||
// Don't bother resolving anything.
|
||||
return PiecewiseLinearFunction {
|
||||
entries: crate::OwnedSlice::from_slice(&[PiecewiseLinearFunctionEntry {
|
||||
entries: crate::ArcSlice::from_iter(std::iter::once(PiecewiseLinearFunctionEntry {
|
||||
x: 0.,
|
||||
y: self.entries[0].y,
|
||||
}]),
|
||||
})),
|
||||
};
|
||||
}
|
||||
// Guaranteed at least two elements.
|
||||
@ -287,7 +273,7 @@ impl PiecewiseLinearFunctionBuilder {
|
||||
"Should've mapped one-to-one!"
|
||||
);
|
||||
PiecewiseLinearFunction {
|
||||
entries: result.into(),
|
||||
entries: crate::ArcSlice::from_iter(result.into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
//! Specified types for CSS Easing functions.
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::piecewise_linear::{PiecewiseLinearFunction, PiecewiseLinearFunctionBuildParameters};
|
||||
use crate::piecewise_linear::{PiecewiseLinearFunction, PiecewiseLinearFunctionBuilder};
|
||||
use crate::values::computed::easing::TimingFunction as ComputedTimingFunction;
|
||||
use crate::values::computed::{Context, ToComputedValue};
|
||||
use crate::values::generics::easing::TimingFunction as GenericTimingFunction;
|
||||
@ -12,35 +12,10 @@ use crate::values::generics::easing::{StepPosition, TimingKeyword};
|
||||
use crate::values::specified::{Integer, Number, Percentage};
|
||||
use cssparser::{Delimiter, Parser, Token};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::iter::FromIterator;
|
||||
use style_traits::{ParseError, StyleParseErrorKind};
|
||||
|
||||
/// An entry for linear easing function.
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||
pub struct LinearStop {
|
||||
/// Output of the function at the given point.
|
||||
pub output: Number,
|
||||
/// Playback progress at which this output is given.
|
||||
#[css(skip_if = "Option::is_none")]
|
||||
pub input: Option<Percentage>,
|
||||
}
|
||||
|
||||
/// A list of specified linear stops.
|
||||
#[derive(Clone, Default, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||
#[css(comma)]
|
||||
pub struct LinearStops {
|
||||
#[css(iterable)]
|
||||
entries: crate::OwnedSlice<LinearStop>,
|
||||
}
|
||||
|
||||
impl LinearStops {
|
||||
fn new(list: crate::OwnedSlice<LinearStop>) -> Self {
|
||||
LinearStops { entries: list }
|
||||
}
|
||||
}
|
||||
|
||||
/// A specified timing function.
|
||||
pub type TimingFunction = GenericTimingFunction<Integer, Number, LinearStops>;
|
||||
pub type TimingFunction = GenericTimingFunction<Integer, Number, PiecewiseLinearFunction>;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn linear_timing_function_enabled() -> bool {
|
||||
@ -136,10 +111,12 @@ impl TimingFunction {
|
||||
if !linear_timing_function_enabled() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::ExperimentalProperty));
|
||||
}
|
||||
let mut result = vec![];
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
let mut num_specified_stops = 0;
|
||||
// Closely follows `parse_comma_separated`, but can generate multiple entries for one comma-separated entry.
|
||||
loop {
|
||||
input.parse_until_before(Delimiter::Comma, |i| {
|
||||
let builder = &mut builder;
|
||||
let mut input_start = i.try_parse(|i| Percentage::parse(context, i)).ok();
|
||||
let mut input_end = i.try_parse(|i| Percentage::parse(context, i)).ok();
|
||||
|
||||
@ -149,19 +126,14 @@ impl TimingFunction {
|
||||
input_start = i.try_parse(|i| Percentage::parse(context, i)).ok();
|
||||
input_end = i.try_parse(|i| Percentage::parse(context, i)).ok();
|
||||
}
|
||||
result.push(LinearStop {
|
||||
output,
|
||||
input: input_start.into(),
|
||||
});
|
||||
builder.push(output.into(), input_start.map(|v| v.get()).into());
|
||||
num_specified_stops += 1;
|
||||
if input_end.is_some() {
|
||||
debug_assert!(
|
||||
input_start.is_some(),
|
||||
"Input end valid but not input start?"
|
||||
);
|
||||
result.push(LinearStop {
|
||||
output,
|
||||
input: input_end.into(),
|
||||
});
|
||||
builder.push(output.into(), input_end.map(|v| v.get()).into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -173,22 +145,13 @@ impl TimingFunction {
|
||||
Ok(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
if result.len() < 2 {
|
||||
// By spec, specifying only a single stop makes the function invalid, even if that single entry may generate
|
||||
// two entries.
|
||||
if num_specified_stops < 2 {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
|
||||
Ok(GenericTimingFunction::LinearFunction(LinearStops::new(
|
||||
crate::OwnedSlice::from(result),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl LinearStop {
|
||||
/// Convert this type to entries that can be used to build PiecewiseLinearFunction.
|
||||
pub fn to_piecewise_linear_build_parameters(
|
||||
x: &LinearStop,
|
||||
) -> PiecewiseLinearFunctionBuildParameters {
|
||||
(x.output.get(), x.input.map(|x| x.get()))
|
||||
Ok(GenericTimingFunction::LinearFunction(builder.build()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,13 +174,8 @@ impl TimingFunction {
|
||||
}
|
||||
},
|
||||
GenericTimingFunction::Keyword(keyword) => GenericTimingFunction::Keyword(*keyword),
|
||||
GenericTimingFunction::LinearFunction(steps) => {
|
||||
GenericTimingFunction::LinearFunction(PiecewiseLinearFunction::from_iter(
|
||||
steps
|
||||
.entries
|
||||
.iter()
|
||||
.map(|e| LinearStop::to_piecewise_linear_build_parameters(e)),
|
||||
))
|
||||
GenericTimingFunction::LinearFunction(function) => {
|
||||
GenericTimingFunction::LinearFunction(function.clone())
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -240,12 +198,7 @@ impl ToComputedValue for TimingFunction {
|
||||
},
|
||||
ComputedTimingFunction::Keyword(keyword) => GenericTimingFunction::Keyword(*keyword),
|
||||
ComputedTimingFunction::LinearFunction(function) => {
|
||||
GenericTimingFunction::LinearFunction(LinearStops {
|
||||
entries: crate::OwnedSlice::from_iter(function.iter().map(|e| LinearStop {
|
||||
output: Number::new(e.y),
|
||||
input: Some(Percentage::new(e.x)).into(),
|
||||
})),
|
||||
})
|
||||
GenericTimingFunction::LinearFunction(function.clone())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use euclid::approxeq::ApproxEq;
|
||||
use style::piecewise_linear::{PiecewiseLinearFunction, PiecewiseLinearFunctionBuilder};
|
||||
|
||||
fn get_linear_keyword_equivalent() -> PiecewiseLinearFunction {
|
||||
PiecewiseLinearFunctionBuilder::new().build()
|
||||
PiecewiseLinearFunctionBuilder::default().build()
|
||||
}
|
||||
#[test]
|
||||
fn linear_keyword_equivalent_in_bound() {
|
||||
@ -24,9 +24,9 @@ fn linear_keyword_equivalent_out_of_bounds() {
|
||||
}
|
||||
|
||||
fn get_const_function() -> PiecewiseLinearFunction {
|
||||
PiecewiseLinearFunctionBuilder::new()
|
||||
.push(CONST_VALUE as f32, None)
|
||||
.build()
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(CONST_VALUE as f32, None);
|
||||
builder.build()
|
||||
}
|
||||
|
||||
const CONST_VALUE: f32 = 0.2;
|
||||
@ -48,14 +48,19 @@ fn const_function_out_of_bounds() {
|
||||
|
||||
#[test]
|
||||
fn implied_input_spacing() {
|
||||
let explicit_spacing = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let implied_spacing = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, None)
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let explicit_spacing = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
let implied_spacing = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, None);
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
|
||||
assert!(implied_spacing.at(0.).approx_eq(&explicit_spacing.at(0.)));
|
||||
assert!(implied_spacing.at(0.5).approx_eq(&explicit_spacing.at(0.5)));
|
||||
assert!(implied_spacing.at(1.0).approx_eq(&explicit_spacing.at(1.0)));
|
||||
@ -63,11 +68,13 @@ fn implied_input_spacing() {
|
||||
|
||||
#[test]
|
||||
fn interpolation() {
|
||||
let interpolate = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, None)
|
||||
.push(0.7, None)
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let interpolate = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, None);
|
||||
builder.push(0.7, None);
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
assert!(interpolate.at(0.1).approx_eq(&0.14));
|
||||
assert!(interpolate.at(0.25).approx_eq(&0.35));
|
||||
assert!(interpolate.at(0.45).approx_eq(&0.63));
|
||||
@ -78,16 +85,18 @@ fn interpolation() {
|
||||
|
||||
#[test]
|
||||
fn implied_multiple_input_spacing() {
|
||||
let multiple_implied = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, None)
|
||||
.push(0.8, None)
|
||||
.push(0.6, None)
|
||||
.push(0.4, None)
|
||||
.push(0.5, Some(0.4))
|
||||
.push(0.1, None)
|
||||
.push(0.9, None)
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let multiple_implied = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, None);
|
||||
builder.push(0.8, None);
|
||||
builder.push(0.6, None);
|
||||
builder.push(0.4, None);
|
||||
builder.push(0.5, Some(0.4));
|
||||
builder.push(0.1, None);
|
||||
builder.push(0.9, None);
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
assert!(multiple_implied.at(0.1).approx_eq(&0.8));
|
||||
assert!(multiple_implied.at(0.2).approx_eq(&0.6));
|
||||
assert!(multiple_implied.at(0.3).approx_eq(&0.4));
|
||||
@ -99,10 +108,12 @@ fn implied_multiple_input_spacing() {
|
||||
|
||||
#[test]
|
||||
fn nonzero_edge_values() {
|
||||
let nonzero_edges = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.1, Some(0.0))
|
||||
.push(0.7, Some(1.0))
|
||||
.build();
|
||||
let nonzero_edges = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.1, Some(0.0));
|
||||
builder.push(0.7, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(nonzero_edges.at(0.).approx_eq(&0.1));
|
||||
assert!(nonzero_edges.at(0.5).approx_eq(&0.4));
|
||||
assert!(nonzero_edges.at(1.0).approx_eq(&0.7));
|
||||
@ -111,11 +122,13 @@ fn nonzero_edge_values() {
|
||||
#[test]
|
||||
fn out_of_bounds_extrapolate() {
|
||||
// General case: extrapolate from the edges' slope
|
||||
let oob_extend = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, None)
|
||||
.push(0.7, None)
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let oob_extend = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, None);
|
||||
builder.push(0.7, None);
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
assert!(oob_extend.at(-0.25).approx_eq(&-0.35));
|
||||
assert!(oob_extend.at(1.25).approx_eq(&1.15));
|
||||
}
|
||||
@ -123,25 +136,29 @@ fn out_of_bounds_extrapolate() {
|
||||
#[test]
|
||||
fn out_of_bounds_flat() {
|
||||
// Repeated endpoints: flat extrapolation out-of-bounds
|
||||
let oob_flat = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.7, None)
|
||||
.push(1.0, Some(1.0))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let oob_flat = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.7, None);
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(oob_flat.at(0.0).approx_eq(&oob_flat.at(-0.25)));
|
||||
assert!(oob_flat.at(1.0).approx_eq(&oob_flat.at(1.25)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flat_region() {
|
||||
let flat = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.5, Some(0.25))
|
||||
.push(0.5, Some(0.7))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let flat = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.5, Some(0.25));
|
||||
builder.push(0.5, Some(0.7));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(flat.at(0.125).approx_eq(&0.25));
|
||||
assert!(flat.at(0.5).approx_eq(&0.5));
|
||||
assert!(flat.at(0.85).approx_eq(&0.75));
|
||||
@ -149,12 +166,14 @@ fn flat_region() {
|
||||
|
||||
#[test]
|
||||
fn step() {
|
||||
let step = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.0, Some(0.5))
|
||||
.push(1.0, Some(0.5))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let step = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.0, Some(0.5));
|
||||
builder.push(1.0, Some(0.5));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(step.at(0.25).approx_eq(&0.0));
|
||||
// At the discontinuity, take the right hand side value
|
||||
assert!(step.at(0.5).approx_eq(&1.0));
|
||||
@ -163,14 +182,16 @@ fn step() {
|
||||
|
||||
#[test]
|
||||
fn step_multiple_conflicting() {
|
||||
let step = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.0, Some(0.5))
|
||||
.push(0.75, Some(0.5))
|
||||
.push(0.75, Some(0.5))
|
||||
.push(1.0, Some(0.5))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let step = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.0, Some(0.5));
|
||||
builder.push(0.75, Some(0.5));
|
||||
builder.push(0.75, Some(0.5));
|
||||
builder.push(1.0, Some(0.5));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(step.at(0.25).approx_eq(&0.0));
|
||||
assert!(step.at(0.5).approx_eq(&1.0));
|
||||
assert!(step.at(0.75).approx_eq(&1.0));
|
||||
@ -178,12 +199,14 @@ fn step_multiple_conflicting() {
|
||||
|
||||
#[test]
|
||||
fn always_monotonic() {
|
||||
let monotonic = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.3, Some(0.5))
|
||||
.push(0.4, Some(0.4))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let monotonic = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.3, Some(0.5));
|
||||
builder.push(0.4, Some(0.4));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(monotonic.at(0.25).approx_eq(&0.15));
|
||||
// A discontinuity at x = 0.5 from y = 0.3 to 0.4
|
||||
assert!(monotonic.at(0.5).approx_eq(&0.4));
|
||||
@ -192,13 +215,15 @@ fn always_monotonic() {
|
||||
|
||||
#[test]
|
||||
fn always_monotonic_flat() {
|
||||
let monotonic = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.2, Some(0.2))
|
||||
.push(0.4, Some(0.1))
|
||||
.push(0.4, Some(0.15))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let monotonic = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.2, Some(0.2));
|
||||
builder.push(0.4, Some(0.1));
|
||||
builder.push(0.4, Some(0.15));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(monotonic.at(0.2).approx_eq(&0.4));
|
||||
// A discontinuity at x = 0.2 from y = 0.2 to 0.4
|
||||
assert!(monotonic.at(0.3).approx_eq(&0.475));
|
||||
@ -206,13 +231,15 @@ fn always_monotonic_flat() {
|
||||
|
||||
#[test]
|
||||
fn always_monotonic_flat_backwards() {
|
||||
let monotonic = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.2, Some(0.2))
|
||||
.push(0.3, Some(0.3))
|
||||
.push(0.3, Some(0.2))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let monotonic = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.2, Some(0.2));
|
||||
builder.push(0.3, Some(0.3));
|
||||
builder.push(0.3, Some(0.2));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(monotonic.at(0.2).approx_eq(&0.2));
|
||||
assert!(monotonic.at(0.3).approx_eq(&0.3));
|
||||
assert!(monotonic.at(0.4).approx_eq(&0.4));
|
||||
@ -220,10 +247,12 @@ fn always_monotonic_flat_backwards() {
|
||||
|
||||
#[test]
|
||||
fn input_out_of_bounds() {
|
||||
let oob = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(-0.5))
|
||||
.push(1.0, Some(1.5))
|
||||
.build();
|
||||
let oob = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(-0.5));
|
||||
builder.push(1.0, Some(1.5));
|
||||
builder.build()
|
||||
};
|
||||
assert!(oob.at(-0.5).approx_eq(&0.0));
|
||||
assert!(oob.at(0.0).approx_eq(&0.25));
|
||||
assert!(oob.at(0.5).approx_eq(&0.5));
|
||||
@ -233,16 +262,20 @@ fn input_out_of_bounds() {
|
||||
|
||||
#[test]
|
||||
fn invalid_builder_input() {
|
||||
let built_from_invalid = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(f32::NEG_INFINITY))
|
||||
.push(0.7, Some(f32::NAN))
|
||||
.push(1.0, Some(f32::INFINITY))
|
||||
.build();
|
||||
let equivalent = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, None)
|
||||
.push(0.7, None)
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let built_from_invalid = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(f32::NEG_INFINITY));
|
||||
builder.push(0.7, Some(f32::NAN));
|
||||
builder.push(1.0, Some(f32::INFINITY));
|
||||
builder.build()
|
||||
};
|
||||
let equivalent = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, None);
|
||||
builder.push(0.7, None);
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
|
||||
assert!(built_from_invalid.at(0.0).approx_eq(&equivalent.at(0.0)));
|
||||
assert!(built_from_invalid.at(0.25).approx_eq(&equivalent.at(0.25)));
|
||||
@ -253,10 +286,12 @@ fn invalid_builder_input() {
|
||||
|
||||
#[test]
|
||||
fn input_domain_not_complete() {
|
||||
let not_covered = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.2, Some(0.2))
|
||||
.push(0.8, Some(0.8))
|
||||
.build();
|
||||
let not_covered = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.2, Some(0.2));
|
||||
builder.push(0.8, Some(0.8));
|
||||
builder.build()
|
||||
};
|
||||
assert!(not_covered.at(0.0).approx_eq(&0.0));
|
||||
assert!(not_covered.at(0.5).approx_eq(&0.5));
|
||||
assert!(not_covered.at(1.0).approx_eq(&1.0));
|
||||
@ -264,22 +299,26 @@ fn input_domain_not_complete() {
|
||||
|
||||
#[test]
|
||||
fn input_second_negative() {
|
||||
let function = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, None)
|
||||
.push(0.0, Some(-0.1))
|
||||
.push(0.3, Some(-0.05))
|
||||
.push(0.5, None)
|
||||
.push(0.2, Some(0.6))
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let equivalent = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.0, Some(0.0))
|
||||
.push(0.3, Some(0.0))
|
||||
.push(0.5, Some(0.3))
|
||||
.push(0.2, Some(0.6))
|
||||
.push(1.0, Some(1.0))
|
||||
.build();
|
||||
let function = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, None);
|
||||
builder.push(0.0, Some(-0.1));
|
||||
builder.push(0.3, Some(-0.05));
|
||||
builder.push(0.5, None);
|
||||
builder.push(0.2, Some(0.6));
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
let equivalent = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(0.3, Some(0.0));
|
||||
builder.push(0.5, Some(0.3));
|
||||
builder.push(0.2, Some(0.6));
|
||||
builder.push(1.0, Some(1.0));
|
||||
builder.build()
|
||||
};
|
||||
assert!(function.at(-0.1).approx_eq(&equivalent.at(-0.1)));
|
||||
assert!(function.at(0.0).approx_eq(&equivalent.at(0.0)));
|
||||
assert!(function.at(0.3).approx_eq(&equivalent.at(0.3)));
|
||||
@ -289,11 +328,13 @@ fn input_second_negative() {
|
||||
|
||||
#[test]
|
||||
fn input_second_last_above_1() {
|
||||
let function = PiecewiseLinearFunctionBuilder::new()
|
||||
.push(0.0, Some(0.0))
|
||||
.push(1.0, Some(2.0))
|
||||
.push(1.0, None)
|
||||
.build();
|
||||
let function = {
|
||||
let mut builder = PiecewiseLinearFunctionBuilder::default();
|
||||
builder.push(0.0, Some(0.0));
|
||||
builder.push(1.0, Some(2.0));
|
||||
builder.push(1.0, None);
|
||||
builder.build()
|
||||
};
|
||||
assert!(function.at(-0.5).approx_eq(&-0.25));
|
||||
assert!(function.at(0.0).approx_eq(&0.0));
|
||||
assert!(function.at(0.5).approx_eq(&0.25));
|
||||
|
@ -1 +0,0 @@
|
||||
prefs: [layout.css.linear-easing-function.enabled:true]
|
@ -1,15 +0,0 @@
|
||||
prefs: [layout.css.linear-easing-function.enabled:true]
|
||||
[linear-timing-functions-syntax.tentative.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[e.style['animation-timing-function'\] = "linear(0, 0.5 25% 75%, 1 100% 100%)" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['animation-timing-function'\] = "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['animation-timing-function'\] = "linear(0 0% 100%)" should not set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['animation-timing-function'\] = "linear(0% 100% 0)" should not set the property value]
|
||||
expected: FAIL
|
Loading…
Reference in New Issue
Block a user