style: linear(...) easing: Parsing should split a linear stop value into two for entries with both linear-stop-length set

This brings the behaviour inline with `linear-gradient(...)`

Differential Revision: https://phabricator.services.mozilla.com/D149926
This commit is contained in:
David Shin 2022-06-28 11:31:34 +00:00 committed by Martin Robinson
parent 09fc10c5c2
commit e3e2ee64de
3 changed files with 36 additions and 30 deletions

View file

@ -24,8 +24,8 @@ impl ComputedLinearStop {
) -> PiecewiseLinearFunctionBuildParameters { ) -> PiecewiseLinearFunctionBuildParameters {
( (
x.output, x.output,
x.input_start.into_rust().map(|x| x.0), x.input.into_rust().map(|x| x.0),
x.input_end.into_rust().map(|x| x.0), None,
) )
} }
} }

View file

@ -27,12 +27,9 @@ use crate::values::generics::Optional;
pub struct LinearStop<Number, Percentage> { pub struct LinearStop<Number, Percentage> {
/// Output of the function at the given point. /// Output of the function at the given point.
pub output: Number, pub output: Number,
/// Playback progress at which this output starts. /// Playback progress at which this output is given.
#[css(skip_if = "Optional::is_none")] #[css(skip_if = "Optional::is_none")]
pub input_start: Optional<Percentage>, pub input: Optional<Percentage>,
/// Playback progress at which this output ends.
#[css(skip_if = "Optional::is_none")]
pub input_end: Optional<Percentage>,
} }
/// A generic easing function. /// A generic easing function.

View file

@ -12,7 +12,7 @@ use crate::values::generics::easing::{
}; };
use crate::values::generics::easing::{StepPosition, TimingKeyword}; use crate::values::generics::easing::{StepPosition, TimingKeyword};
use crate::values::specified::{Integer, Number, Percentage}; use crate::values::specified::{Integer, Number, Percentage};
use cssparser::Parser; use cssparser::{Delimiter, Parser, Token};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use std::iter::FromIterator; use std::iter::FromIterator;
use style_traits::{ParseError, StyleParseErrorKind}; use style_traits::{ParseError, StyleParseErrorKind};
@ -20,6 +20,8 @@ use style_traits::{ParseError, StyleParseErrorKind};
/// A specified timing function. /// A specified timing function.
pub type TimingFunction = GenericTimingFunction<Integer, Number, Percentage>; pub type TimingFunction = GenericTimingFunction<Integer, Number, Percentage>;
type LinearStop = GenericLinearStop<Number, Percentage>;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
fn linear_timing_function_enabled() -> bool { fn linear_timing_function_enabled() -> bool {
static_prefs::pref!("layout.css.linear-easing-function.enabled") static_prefs::pref!("layout.css.linear-easing-function.enabled")
@ -115,23 +117,35 @@ impl TimingFunction {
if input.is_exhausted() { if input.is_exhausted() {
return Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::default())) return Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::default()))
} }
let entries = input.parse_comma_separated(|i| { let mut result = vec![];
let mut input_start = i.try_parse(|i| Percentage::parse(context, i)).ok(); loop {
let mut input_end = i.try_parse(|i| Percentage::parse(context, i)).ok(); input.parse_until_before(Delimiter::Comma, |i| {
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();
let output = Number::parse(context, i)?; let output = Number::parse(context, i)?;
if input_start.is_none() { if input_start.is_none() {
debug_assert!(input_end.is_none(), "Input end parsed without input start?"); debug_assert!(input_end.is_none(), "Input end parsed without input start?");
input_start = i.try_parse(|i| Percentage::parse(context, i)).ok(); input_start = i.try_parse(|i| Percentage::parse(context, i)).ok();
input_end = 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() });
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() });
}
Ok(())
})?;
match input.next() {
Err(_) => break,
Ok(&Token::Comma) => continue,
Ok(_) => unreachable!(),
} }
Ok(GenericLinearStop { }
output,
input_start: input_start.into(), Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::from(result)))
input_end: input_end.into()
})
})?;
Ok(GenericTimingFunction::LinearFunction(crate::OwnedSlice::from(entries)))
} }
} }
@ -157,13 +171,8 @@ impl TimingFunction {
GenericTimingFunction::LinearFunction(steps) => { GenericTimingFunction::LinearFunction(steps) => {
let iter = steps.iter().map(|e| ComputedLinearStop { let iter = steps.iter().map(|e| ComputedLinearStop {
output: e.output.get(), output: e.output.get(),
input_start: e input: e
.input_start .input
.into_rust()
.map(|x| ComputedPercentage(x.get()))
.into(),
input_end: e
.input_end
.into_rust() .into_rust()
.map(|x| ComputedPercentage(x.get())) .map(|x| ComputedPercentage(x.get()))
.into(), .into(),