style: Simplify computed::LengthOrPercentage and friends.

This is a first step to share LengthOrPercentage representation between Rust and
Gecko.

We need to preserve whether the value came from a calc() expression, for now at
least, since we do different things depending on whether we're calc or not right
now. See https://github.com/w3c/csswg-drafts/issues/3482 and dependent bugs for
example.

That means that the gecko conversion code needs to handle calc() in a bit of an
awkward way until I change it to not be needed (patches for that incoming in the
next few weeks I hope).

I need to add a hack to exclude other things from the PartialEq implementation
because the new conversion code is less lossy than the old one, and we relied on
the lousiness in AnimationValue comparison (in order to start transitions and
such, in [1] for example).

I expect to remove that manual PartialEq implementation as soon as I'm done with
the conversion.

The less lossy conversion does fix a few serialization bugs for animation values
though, like not loosing 0% values in calc() when interpolating lengths and
percentages, see the two modified tests:

 * property-types.js
 * test_animation_properties.html

Differential Revision: https://phabricator.services.mozilla.com/D15793
This commit is contained in:
Emilio Cobos Álvarez 2019-01-06 23:01:00 +01:00
parent bffe2a699e
commit ca503b4908
22 changed files with 338 additions and 644 deletions

View file

@ -4,15 +4,14 @@
//! Animation implementation for various length-related types.
use super::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
use crate::values::computed::length::{CalcLengthOrPercentage, Length};
use crate::values::computed::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
use super::{Animate, Procedure, ToAnimatedValue};
use crate::values::computed::length::LengthOrPercentage;
use crate::values::computed::MaxLength as ComputedMaxLength;
use crate::values::computed::MozLength as ComputedMozLength;
use crate::values::computed::Percentage;
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
impl Animate for CalcLengthOrPercentage {
impl Animate for LengthOrPercentage {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
let animate_percentage_half = |this: Option<Percentage>, other: Option<Percentage>| {
@ -28,42 +27,17 @@ impl Animate for CalcLengthOrPercentage {
.unclamped_length()
.animate(&other.unclamped_length(), procedure)?;
let percentage = animate_percentage_half(self.percentage, other.percentage)?;
Ok(CalcLengthOrPercentage::with_clamping_mode(
let is_calc = self.was_calc || other.was_calc || self.percentage.is_some() != other.percentage.is_some();
Ok(Self::with_clamping_mode(
length,
percentage,
self.clamping_mode,
is_calc,
))
}
}
impl ToAnimatedZero for LengthOrPercentageOrAuto {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
LengthOrPercentageOrAuto::Length(_) |
LengthOrPercentageOrAuto::Percentage(_) |
LengthOrPercentageOrAuto::Calc(_) => {
Ok(LengthOrPercentageOrAuto::Length(Length::new(0.)))
},
LengthOrPercentageOrAuto::Auto => Err(()),
}
}
}
impl ToAnimatedZero for LengthOrPercentageOrNone {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match *self {
LengthOrPercentageOrNone::Length(_) |
LengthOrPercentageOrNone::Percentage(_) |
LengthOrPercentageOrNone::Calc(_) => {
Ok(LengthOrPercentageOrNone::Length(Length::new(0.)))
},
LengthOrPercentageOrNone::None => Err(()),
}
}
}
// FIXME(emilio): These should use NonNegative<> instead.
impl ToAnimatedValue for ComputedMaxLength {
type AnimatedValue = Self;
@ -74,18 +48,15 @@ impl ToAnimatedValue for ComputedMaxLength {
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
use crate::values::computed::{Length, LengthOrPercentageOrNone, Percentage};
use crate::values::computed::LengthOrPercentageOrNone;
use crate::values::generics::length::MaxLength as GenericMaxLength;
match animated {
GenericMaxLength::LengthOrPercentageOrNone(lopn) => {
let result = match lopn {
LengthOrPercentageOrNone::Length(px) => {
LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
LengthOrPercentageOrNone::LengthOrPercentage(len) => {
LengthOrPercentageOrNone::LengthOrPercentage(len.clamp_to_non_negative())
},
LengthOrPercentageOrNone::Percentage(percentage) => {
LengthOrPercentageOrNone::Percentage(Percentage(percentage.0.max(0.)))
},
_ => lopn,
LengthOrPercentageOrNone::None => lopn,
};
GenericMaxLength::LengthOrPercentageOrNone(result)
},
@ -104,20 +75,10 @@ impl ToAnimatedValue for ComputedMozLength {
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
use crate::values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
use crate::values::generics::length::MozLength as GenericMozLength;
match animated {
GenericMozLength::LengthOrPercentageOrAuto(lopa) => {
let result = match lopa {
LengthOrPercentageOrAuto::Length(px) => {
LengthOrPercentageOrAuto::Length(Length::new(px.px().max(0.)))
},
LengthOrPercentageOrAuto::Percentage(percentage) => {
LengthOrPercentageOrAuto::Percentage(Percentage(percentage.0.max(0.)))
},
_ => lopa,
};
GenericMozLength::LengthOrPercentageOrAuto(result)
GenericMozLength::LengthOrPercentageOrAuto(lopa.clamp_to_non_negative())
},
_ => animated,
}