Skip to content

Commit e2edea3

Browse files
emilioaditj
authored andcommitted
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 w3c/csswg-drafts#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
1 parent 9d826a3 commit e2edea3

File tree

22 files changed

+339
-645
lines changed

22 files changed

+339
-645
lines changed

components/style/gecko/conversions.rs

+26-71
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::stylesheets::{Origin, RulesMutateError};
2020
use crate::values::computed::image::LineDirection;
2121
use crate::values::computed::transform::Matrix3D;
2222
use crate::values::computed::url::ComputedImageUrl;
23-
use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
23+
use crate::values::computed::{Angle, Gradient, Image};
2424
use crate::values::computed::{Integer, LengthOrPercentage};
2525
use crate::values::computed::{LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto};
2626
use crate::values::computed::{Percentage, TextAlign};
@@ -31,9 +31,10 @@ use crate::values::generics::rect::Rect;
3131
use crate::values::generics::NonNegative;
3232
use app_units::Au;
3333
use std::f32::consts::PI;
34+
use style_traits::values::specified::AllowedNumericType;
3435

35-
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
36-
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
36+
impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
37+
fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
3738
let has_percentage = other.percentage.is_some();
3839
nsStyleCoord_CalcValue {
3940
mLength: other.unclamped_length().to_i32_au(),
@@ -43,93 +44,54 @@ impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
4344
}
4445
}
4546

46-
impl From<nsStyleCoord_CalcValue> for CalcLengthOrPercentage {
47-
fn from(other: nsStyleCoord_CalcValue) -> CalcLengthOrPercentage {
47+
impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
48+
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
4849
let percentage = if other.mHasPercent {
4950
Some(Percentage(other.mPercent))
5051
} else {
5152
None
5253
};
53-
Self::new(Au(other.mLength).into(), percentage)
54-
}
55-
}
56-
57-
impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
58-
fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
59-
match other {
60-
LengthOrPercentage::Length(px) => nsStyleCoord_CalcValue {
61-
mLength: px.to_i32_au(),
62-
mPercent: 0.0,
63-
mHasPercent: false,
64-
},
65-
LengthOrPercentage::Percentage(pc) => nsStyleCoord_CalcValue {
66-
mLength: 0,
67-
mPercent: pc.0,
68-
mHasPercent: true,
69-
},
70-
LengthOrPercentage::Calc(calc) => calc.into(),
71-
}
54+
Self::with_clamping_mode(
55+
Au(other.mLength).into(),
56+
percentage,
57+
AllowedNumericType::All,
58+
/* was_calc = */ true,
59+
)
7260
}
7361
}
7462

7563
impl LengthOrPercentageOrAuto {
7664
/// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
7765
pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
7866
match *self {
79-
LengthOrPercentageOrAuto::Length(px) => Some(nsStyleCoord_CalcValue {
80-
mLength: px.to_i32_au(),
81-
mPercent: 0.0,
82-
mHasPercent: false,
83-
}),
84-
LengthOrPercentageOrAuto::Percentage(pc) => Some(nsStyleCoord_CalcValue {
85-
mLength: 0,
86-
mPercent: pc.0,
87-
mHasPercent: true,
88-
}),
89-
LengthOrPercentageOrAuto::Calc(calc) => Some(calc.into()),
67+
LengthOrPercentageOrAuto::LengthOrPercentage(len) => Some(From::from(len)),
9068
LengthOrPercentageOrAuto::Auto => None,
9169
}
9270
}
9371
}
9472

95-
impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
96-
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
97-
match (other.mHasPercent, other.mLength) {
98-
(false, _) => LengthOrPercentage::Length(Au(other.mLength).into()),
99-
(true, 0) => LengthOrPercentage::Percentage(Percentage(other.mPercent)),
100-
_ => LengthOrPercentage::Calc(other.into()),
101-
}
102-
}
103-
}
104-
10573
impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
10674
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentageOrAuto {
107-
match (other.mHasPercent, other.mLength) {
108-
(false, _) => LengthOrPercentageOrAuto::Length(Au(other.mLength).into()),
109-
(true, 0) => LengthOrPercentageOrAuto::Percentage(Percentage(other.mPercent)),
110-
_ => LengthOrPercentageOrAuto::Calc(other.into()),
111-
}
75+
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::from(other))
11276
}
11377
}
11478

11579
// FIXME(emilio): A lot of these impl From should probably become explicit or
11680
// disappear as we move more stuff to cbindgen.
11781
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
11882
fn from(other: nsStyleCoord_CalcValue) -> Self {
119-
use style_traits::values::specified::AllowedNumericType;
120-
NonNegative(if other.mLength < 0 || other.mPercent < 0. {
121-
LengthOrPercentageOrAuto::Calc(CalcLengthOrPercentage::with_clamping_mode(
83+
NonNegative(
84+
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::with_clamping_mode(
12285
Au(other.mLength).into(),
12386
if other.mHasPercent {
12487
Some(Percentage(other.mPercent))
12588
} else {
12689
None
12790
},
12891
AllowedNumericType::NonNegative,
92+
/* was_calc = */ true,
12993
))
130-
} else {
131-
other.into()
132-
})
94+
)
13395
}
13496
}
13597

@@ -143,30 +105,23 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
143105
use crate::values::computed::position::Position;
144106
use crate::values::specified::position::{X, Y};
145107

146-
let horizontal_percentage = match horizontal {
147-
LengthOrPercentage::Percentage(percentage) => Some(percentage.0),
148-
_ => None,
149-
};
150-
151-
let vertical_percentage = match vertical {
152-
LengthOrPercentage::Percentage(percentage) => Some(percentage.0),
153-
_ => None,
154-
};
108+
let horizontal_percentage = horizontal.as_percentage();
109+
let vertical_percentage = vertical.as_percentage();
155110

156111
let horizontal_as_corner = horizontal_percentage.and_then(|percentage| {
157-
if percentage == 0.0 {
112+
if percentage.0 == 0.0 {
158113
Some(X::Left)
159-
} else if percentage == 1.0 {
114+
} else if percentage.0 == 1.0 {
160115
Some(X::Right)
161116
} else {
162117
None
163118
}
164119
});
165120

166121
let vertical_as_corner = vertical_percentage.and_then(|percentage| {
167-
if percentage == 0.0 {
122+
if percentage.0 == 0.0 {
168123
Some(Y::Top)
169-
} else if percentage == 1.0 {
124+
} else if percentage.0 == 1.0 {
170125
Some(Y::Bottom)
171126
} else {
172127
None
@@ -178,13 +133,13 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
178133
}
179134

180135
if let Some(hc) = horizontal_as_corner {
181-
if vertical_percentage == Some(0.5) {
136+
if vertical_percentage == Some(Percentage(0.5)) {
182137
return LineDirection::Horizontal(hc);
183138
}
184139
}
185140

186141
if let Some(vc) = vertical_as_corner {
187-
if horizontal_percentage == Some(0.5) {
142+
if horizontal_percentage == Some(Percentage(0.5)) {
188143
return LineDirection::Vertical(vc);
189144
}
190145
}

components/style/gecko/values.rs

+21-35
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,21 @@ impl GeckoStyleCoordConvertible for NumberOrPercentage {
148148

149149
impl GeckoStyleCoordConvertible for LengthOrPercentage {
150150
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
151-
let value = match *self {
152-
LengthOrPercentage::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
153-
LengthOrPercentage::Percentage(p) => CoordDataValue::Percent(p.0),
154-
LengthOrPercentage::Calc(calc) => CoordDataValue::Calc(calc.into()),
155-
};
156-
coord.set_value(value);
151+
if self.was_calc {
152+
return coord.set_value(CoordDataValue::Calc((*self).into()))
153+
}
154+
debug_assert!(self.percentage.is_none() || self.unclamped_length() == Length::zero());
155+
if let Some(p) = self.percentage {
156+
return coord.set_value(CoordDataValue::Percent(p.0));
157+
}
158+
coord.set_value(CoordDataValue::Coord(self.unclamped_length().to_i32_au()))
157159
}
158160

159161
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
160162
match coord.as_value() {
161-
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::Length(Au(coord).into())),
162-
CoordDataValue::Percent(p) => Some(LengthOrPercentage::Percentage(Percentage(p))),
163-
CoordDataValue::Calc(calc) => Some(LengthOrPercentage::Calc(calc.into())),
163+
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::new(Au(coord).into(), None)),
164+
CoordDataValue::Percent(p) => Some(LengthOrPercentage::new(Au(0).into(), Some(Percentage(p)))),
165+
CoordDataValue::Calc(calc) => Some(calc.into()),
164166
_ => None,
165167
}
166168
}
@@ -181,48 +183,32 @@ impl GeckoStyleCoordConvertible for Length {
181183

182184
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
183185
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
184-
let value = match *self {
185-
LengthOrPercentageOrAuto::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
186-
LengthOrPercentageOrAuto::Percentage(p) => CoordDataValue::Percent(p.0),
187-
LengthOrPercentageOrAuto::Auto => CoordDataValue::Auto,
188-
LengthOrPercentageOrAuto::Calc(calc) => CoordDataValue::Calc(calc.into()),
189-
};
190-
coord.set_value(value);
186+
match *self {
187+
LengthOrPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto),
188+
LengthOrPercentageOrAuto::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord),
189+
}
191190
}
192191

193192
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
194193
match coord.as_value() {
195-
CoordDataValue::Coord(coord) => {
196-
Some(LengthOrPercentageOrAuto::Length(Au(coord).into()))
197-
},
198-
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrAuto::Percentage(Percentage(p))),
199194
CoordDataValue::Auto => Some(LengthOrPercentageOrAuto::Auto),
200-
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrAuto::Calc(calc.into())),
201-
_ => None,
195+
_ => LengthOrPercentage::from_gecko_style_coord(coord).map(LengthOrPercentageOrAuto::LengthOrPercentage),
202196
}
203197
}
204198
}
205199

206200
impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
207201
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
208-
let value = match *self {
209-
LengthOrPercentageOrNone::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
210-
LengthOrPercentageOrNone::Percentage(p) => CoordDataValue::Percent(p.0),
211-
LengthOrPercentageOrNone::None => CoordDataValue::None,
212-
LengthOrPercentageOrNone::Calc(calc) => CoordDataValue::Calc(calc.into()),
213-
};
214-
coord.set_value(value);
202+
match *self {
203+
LengthOrPercentageOrNone::None => coord.set_value(CoordDataValue::None),
204+
LengthOrPercentageOrNone::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord),
205+
}
215206
}
216207

217208
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
218209
match coord.as_value() {
219-
CoordDataValue::Coord(coord) => {
220-
Some(LengthOrPercentageOrNone::Length(Au(coord).into()))
221-
},
222-
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrNone::Percentage(Percentage(p))),
223210
CoordDataValue::None => Some(LengthOrPercentageOrNone::None),
224-
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrNone::Calc(calc.into())),
225-
_ => None,
211+
_ => LengthOrPercentage::from_gecko_style_coord(coord).map(LengthOrPercentageOrNone::LengthOrPercentage),
226212
}
227213
}
228214
}

components/style/gecko_bindings/sugar/ns_css_value.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,14 @@ impl nsCSSValue {
6969

7070
/// Sets LengthOrPercentage value to this nsCSSValue.
7171
pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) {
72-
match lop {
73-
LengthOrPercentage::Length(px) => self.set_px(px.px()),
74-
LengthOrPercentage::Percentage(pc) => self.set_percentage(pc.0),
75-
LengthOrPercentage::Calc(calc) => bindings::Gecko_CSSValue_SetCalc(self, calc.into()),
72+
if lop.was_calc {
73+
return bindings::Gecko_CSSValue_SetCalc(self, lop.into())
7674
}
75+
debug_assert!(lop.percentage.is_none() || lop.unclamped_length() == Length::zero());
76+
if let Some(p) = lop.percentage {
77+
return self.set_percentage(p.0);
78+
}
79+
self.set_px(lop.unclamped_length().px());
7780
}
7881

7982
/// Sets a px value to this nsCSSValue.
@@ -90,13 +93,16 @@ impl nsCSSValue {
9093
pub unsafe fn get_lop(&self) -> LengthOrPercentage {
9194
match self.mUnit {
9295
nsCSSUnit::eCSSUnit_Pixel => {
93-
LengthOrPercentage::Length(Length::new(bindings::Gecko_CSSValue_GetNumber(self)))
96+
LengthOrPercentage::new(
97+
Length::new(bindings::Gecko_CSSValue_GetNumber(self)),
98+
None,
99+
)
94100
},
95-
nsCSSUnit::eCSSUnit_Percent => LengthOrPercentage::Percentage(Percentage(
101+
nsCSSUnit::eCSSUnit_Percent => LengthOrPercentage::new_percent(Percentage(
96102
bindings::Gecko_CSSValue_GetPercentage(self),
97103
)),
98104
nsCSSUnit::eCSSUnit_Calc => {
99-
LengthOrPercentage::Calc(bindings::Gecko_CSSValue_GetCalc(self).into())
105+
bindings::Gecko_CSSValue_GetCalc(self).into()
100106
},
101107
_ => panic!("Unexpected unit"),
102108
}

components/style/properties/gecko.mako.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -558,18 +558,16 @@ def set_gecko_property(ffi_name, expr):
558558
},
559559
CoordDataValue::Coord(coord) => {
560560
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
561-
LengthOrPercentage::Length(Au(coord).into())
561+
LengthOrPercentage::new(Au(coord).into(), None)
562562
)
563563
},
564564
CoordDataValue::Percent(p) => {
565565
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
566-
LengthOrPercentage::Percentage(Percentage(p))
566+
LengthOrPercentage::new(Au(0).into(), Some(Percentage(p)))
567567
)
568568
},
569569
CoordDataValue::Calc(calc) => {
570-
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
571-
LengthOrPercentage::Calc(calc.into())
572-
)
570+
SvgLengthOrPercentageOrNumber::LengthOrPercentage(calc.into())
573571
},
574572
_ => unreachable!("Unexpected coordinate in ${ident}"),
575573
};
@@ -5062,6 +5060,7 @@ clip-path
50625060
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
50635061
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
50645062
use crate::values::computed::LengthOrPercentage;
5063+
use crate::values::generics::NonNegative;
50655064
use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
50665065

50675066
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
@@ -5075,13 +5074,13 @@ clip-path
50755074
vec.push(SvgLengthOrPercentageOrNumber::Number(number.into())),
50765075
CoordDataValue::Coord(coord) =>
50775076
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
5078-
LengthOrPercentage::Length(Au(coord).into()).into())),
5077+
NonNegative(LengthOrPercentage::new(Au(coord).into(), None).into()))),
50795078
CoordDataValue::Percent(p) =>
50805079
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
5081-
LengthOrPercentage::Percentage(Percentage(p)).into())),
5080+
NonNegative(LengthOrPercentage::new_percent(Percentage(p)).into()))),
50825081
CoordDataValue::Calc(calc) =>
50835082
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
5084-
LengthOrPercentage::Calc(calc.into()).into())),
5083+
NonNegative(LengthOrPercentage::from(calc).clamp_to_non_negative()))),
50855084
_ => unreachable!(),
50865085
}
50875086
}

components/style/properties/longhands/inherited_text.mako.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ ${helpers.single_keyword(
5454
${helpers.predefined_type(
5555
"text-indent",
5656
"LengthOrPercentage",
57-
"computed::LengthOrPercentage::Length(computed::Length::new(0.))",
57+
"computed::LengthOrPercentage::zero()",
5858
animation_value_type="ComputedValue",
5959
spec="https://drafts.csswg.org/css-text/#propdef-text-indent",
6060
allow_quirks=True,

components/style/properties/longhands/margin.mako.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
${helpers.predefined_type(
1616
"margin-%s" % side[0],
1717
"LengthOrPercentageOrAuto",
18-
"computed::LengthOrPercentageOrAuto::Length(computed::Length::new(0.))",
18+
"computed::LengthOrPercentageOrAuto::zero()",
1919
alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"),
2020
allow_quirks=not side[1],
2121
animation_value_type="ComputedValue",

0 commit comments

Comments
 (0)