mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
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:
parent
bffe2a699e
commit
ca503b4908
22 changed files with 338 additions and 644 deletions
|
@ -20,7 +20,7 @@ use crate::stylesheets::{Origin, RulesMutateError};
|
|||
use crate::values::computed::image::LineDirection;
|
||||
use crate::values::computed::transform::Matrix3D;
|
||||
use crate::values::computed::url::ComputedImageUrl;
|
||||
use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
|
||||
use crate::values::computed::{Angle, Gradient, Image};
|
||||
use crate::values::computed::{Integer, LengthOrPercentage};
|
||||
use crate::values::computed::{LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto};
|
||||
use crate::values::computed::{Percentage, TextAlign};
|
||||
|
@ -31,9 +31,10 @@ use crate::values::generics::rect::Rect;
|
|||
use crate::values::generics::NonNegative;
|
||||
use app_units::Au;
|
||||
use std::f32::consts::PI;
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
||||
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||
impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||
fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||
let has_percentage = other.percentage.is_some();
|
||||
nsStyleCoord_CalcValue {
|
||||
mLength: other.unclamped_length().to_i32_au(),
|
||||
|
@ -43,32 +44,19 @@ impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<nsStyleCoord_CalcValue> for CalcLengthOrPercentage {
|
||||
fn from(other: nsStyleCoord_CalcValue) -> CalcLengthOrPercentage {
|
||||
impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
|
||||
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
|
||||
let percentage = if other.mHasPercent {
|
||||
Some(Percentage(other.mPercent))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Self::new(Au(other.mLength).into(), percentage)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||
fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||
match other {
|
||||
LengthOrPercentage::Length(px) => nsStyleCoord_CalcValue {
|
||||
mLength: px.to_i32_au(),
|
||||
mPercent: 0.0,
|
||||
mHasPercent: false,
|
||||
},
|
||||
LengthOrPercentage::Percentage(pc) => nsStyleCoord_CalcValue {
|
||||
mLength: 0,
|
||||
mPercent: pc.0,
|
||||
mHasPercent: true,
|
||||
},
|
||||
LengthOrPercentage::Calc(calc) => calc.into(),
|
||||
}
|
||||
Self::with_clamping_mode(
|
||||
Au(other.mLength).into(),
|
||||
percentage,
|
||||
AllowedNumericType::All,
|
||||
/* was_calc = */ true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,39 +64,15 @@ impl LengthOrPercentageOrAuto {
|
|||
/// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
|
||||
pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
|
||||
match *self {
|
||||
LengthOrPercentageOrAuto::Length(px) => Some(nsStyleCoord_CalcValue {
|
||||
mLength: px.to_i32_au(),
|
||||
mPercent: 0.0,
|
||||
mHasPercent: false,
|
||||
}),
|
||||
LengthOrPercentageOrAuto::Percentage(pc) => Some(nsStyleCoord_CalcValue {
|
||||
mLength: 0,
|
||||
mPercent: pc.0,
|
||||
mHasPercent: true,
|
||||
}),
|
||||
LengthOrPercentageOrAuto::Calc(calc) => Some(calc.into()),
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(len) => Some(From::from(len)),
|
||||
LengthOrPercentageOrAuto::Auto => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
|
||||
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
|
||||
match (other.mHasPercent, other.mLength) {
|
||||
(false, _) => LengthOrPercentage::Length(Au(other.mLength).into()),
|
||||
(true, 0) => LengthOrPercentage::Percentage(Percentage(other.mPercent)),
|
||||
_ => LengthOrPercentage::Calc(other.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
|
||||
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentageOrAuto {
|
||||
match (other.mHasPercent, other.mLength) {
|
||||
(false, _) => LengthOrPercentageOrAuto::Length(Au(other.mLength).into()),
|
||||
(true, 0) => LengthOrPercentageOrAuto::Percentage(Percentage(other.mPercent)),
|
||||
_ => LengthOrPercentageOrAuto::Calc(other.into()),
|
||||
}
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::from(other))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +80,8 @@ impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
|
|||
// disappear as we move more stuff to cbindgen.
|
||||
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
|
||||
fn from(other: nsStyleCoord_CalcValue) -> Self {
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
NonNegative(if other.mLength < 0 || other.mPercent < 0. {
|
||||
LengthOrPercentageOrAuto::Calc(CalcLengthOrPercentage::with_clamping_mode(
|
||||
NonNegative(
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::with_clamping_mode(
|
||||
Au(other.mLength).into(),
|
||||
if other.mHasPercent {
|
||||
Some(Percentage(other.mPercent))
|
||||
|
@ -126,10 +89,9 @@ impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
|
|||
None
|
||||
},
|
||||
AllowedNumericType::NonNegative,
|
||||
/* was_calc = */ true,
|
||||
))
|
||||
} else {
|
||||
other.into()
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,20 +105,13 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
|
|||
use crate::values::computed::position::Position;
|
||||
use crate::values::specified::position::{X, Y};
|
||||
|
||||
let horizontal_percentage = match horizontal {
|
||||
LengthOrPercentage::Percentage(percentage) => Some(percentage.0),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let vertical_percentage = match vertical {
|
||||
LengthOrPercentage::Percentage(percentage) => Some(percentage.0),
|
||||
_ => None,
|
||||
};
|
||||
let horizontal_percentage = horizontal.as_percentage();
|
||||
let vertical_percentage = vertical.as_percentage();
|
||||
|
||||
let horizontal_as_corner = horizontal_percentage.and_then(|percentage| {
|
||||
if percentage == 0.0 {
|
||||
if percentage.0 == 0.0 {
|
||||
Some(X::Left)
|
||||
} else if percentage == 1.0 {
|
||||
} else if percentage.0 == 1.0 {
|
||||
Some(X::Right)
|
||||
} else {
|
||||
None
|
||||
|
@ -164,9 +119,9 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
|
|||
});
|
||||
|
||||
let vertical_as_corner = vertical_percentage.and_then(|percentage| {
|
||||
if percentage == 0.0 {
|
||||
if percentage.0 == 0.0 {
|
||||
Some(Y::Top)
|
||||
} else if percentage == 1.0 {
|
||||
} else if percentage.0 == 1.0 {
|
||||
Some(Y::Bottom)
|
||||
} else {
|
||||
None
|
||||
|
@ -178,13 +133,13 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
|
|||
}
|
||||
|
||||
if let Some(hc) = horizontal_as_corner {
|
||||
if vertical_percentage == Some(0.5) {
|
||||
if vertical_percentage == Some(Percentage(0.5)) {
|
||||
return LineDirection::Horizontal(hc);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(vc) = vertical_as_corner {
|
||||
if horizontal_percentage == Some(0.5) {
|
||||
if horizontal_percentage == Some(Percentage(0.5)) {
|
||||
return LineDirection::Vertical(vc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,19 +148,21 @@ impl GeckoStyleCoordConvertible for NumberOrPercentage {
|
|||
|
||||
impl GeckoStyleCoordConvertible for LengthOrPercentage {
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
let value = match *self {
|
||||
LengthOrPercentage::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
|
||||
LengthOrPercentage::Percentage(p) => CoordDataValue::Percent(p.0),
|
||||
LengthOrPercentage::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
||||
};
|
||||
coord.set_value(value);
|
||||
if self.was_calc {
|
||||
return coord.set_value(CoordDataValue::Calc((*self).into()))
|
||||
}
|
||||
debug_assert!(self.percentage.is_none() || self.unclamped_length() == Length::zero());
|
||||
if let Some(p) = self.percentage {
|
||||
return coord.set_value(CoordDataValue::Percent(p.0));
|
||||
}
|
||||
coord.set_value(CoordDataValue::Coord(self.unclamped_length().to_i32_au()))
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::Length(Au(coord).into())),
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentage::Percentage(Percentage(p))),
|
||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentage::Calc(calc.into())),
|
||||
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::new(Au(coord).into(), None)),
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentage::new(Au(0).into(), Some(Percentage(p)))),
|
||||
CoordDataValue::Calc(calc) => Some(calc.into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -181,48 +183,32 @@ impl GeckoStyleCoordConvertible for Length {
|
|||
|
||||
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
let value = match *self {
|
||||
LengthOrPercentageOrAuto::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
|
||||
LengthOrPercentageOrAuto::Percentage(p) => CoordDataValue::Percent(p.0),
|
||||
LengthOrPercentageOrAuto::Auto => CoordDataValue::Auto,
|
||||
LengthOrPercentageOrAuto::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
||||
};
|
||||
coord.set_value(value);
|
||||
match *self {
|
||||
LengthOrPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto),
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Coord(coord) => {
|
||||
Some(LengthOrPercentageOrAuto::Length(Au(coord).into()))
|
||||
},
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrAuto::Percentage(Percentage(p))),
|
||||
CoordDataValue::Auto => Some(LengthOrPercentageOrAuto::Auto),
|
||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrAuto::Calc(calc.into())),
|
||||
_ => None,
|
||||
_ => LengthOrPercentage::from_gecko_style_coord(coord).map(LengthOrPercentageOrAuto::LengthOrPercentage),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
|
||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||
let value = match *self {
|
||||
LengthOrPercentageOrNone::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
|
||||
LengthOrPercentageOrNone::Percentage(p) => CoordDataValue::Percent(p.0),
|
||||
LengthOrPercentageOrNone::None => CoordDataValue::None,
|
||||
LengthOrPercentageOrNone::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
||||
};
|
||||
coord.set_value(value);
|
||||
match *self {
|
||||
LengthOrPercentageOrNone::None => coord.set_value(CoordDataValue::None),
|
||||
LengthOrPercentageOrNone::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Coord(coord) => {
|
||||
Some(LengthOrPercentageOrNone::Length(Au(coord).into()))
|
||||
},
|
||||
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrNone::Percentage(Percentage(p))),
|
||||
CoordDataValue::None => Some(LengthOrPercentageOrNone::None),
|
||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrNone::Calc(calc.into())),
|
||||
_ => None,
|
||||
_ => LengthOrPercentage::from_gecko_style_coord(coord).map(LengthOrPercentageOrNone::LengthOrPercentage),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue