Skip to content

Commit 5332d4b

Browse files
committed
Stylo - support image-orientation property
First, we need to make Servo's image-orientation parser to be agreed with Gecko's. Numbers without any AngleUnit, including unitless 0 angle, should be invalid for image-orientation. However, rotate() and skew() for transform properties accept unitless 0 angle. In order to make all these properties work properly, I fixed Angle::parse() to match Gecko. For the existing users of Angle::parse(), I create Angle::parse_with_unitless() and use it as an alternative for them. Once w3c/csswg-drafts#1162 is resolved, we shall be able to use an unified version of Angle::parse() then. The parser of image-orientation is also fixed to report parsing errors on empty string. Then, with the newly added binding functions support in Gecko side, we shall reuse the same methods from Gecko to pass the computed value from Servo to Gecko. Gecko bug: Bug 1341758
1 parent b5a0032 commit 5332d4b

File tree

5 files changed

+66
-21
lines changed

5 files changed

+66
-21
lines changed

components/style/properties/gecko.mako.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2776,6 +2776,34 @@ fn static_assert() {
27762776
}
27772777
self:impl_trait>
27782778

2779+
<%self:impl_trait style_struct_name="InheritedBox"
2780+
skip_longhands="image-orientation">
2781+
// FIXME: Gecko uses a tricky way to store computed value of image-orientation
2782+
// within an u8. We could inline following glue codes by implementing all
2783+
// those tricky parts for Servo as well. But, it's not done yet just for
2784+
// convenience.
2785+
pub fn set_image_orientation(&mut self, v: longhands::image_orientation::computed_value::T) {
2786+
use properties::longhands::image_orientation::computed_value::T;
2787+
match v {
2788+
T::FromImage => {
2789+
unsafe {
2790+
bindings::Gecko_SetImageOrientationAsFromImage(&mut self.gecko);
2791+
}
2792+
},
2793+
T::AngleWithFlipped(ref angle, flipped) => {
2794+
unsafe {
2795+
bindings::Gecko_SetImageOrientation(&mut self.gecko, angle.radians() as f64, flipped);
2796+
}
2797+
}
2798+
}
2799+
}
2800+
2801+
pub fn copy_image_orientation_from(&mut self, other: &Self) {
2802+
unsafe {
2803+
bindings::Gecko_CopyImageOrientationFrom(&mut self.gecko, &other.gecko);
2804+
}
2805+
}
2806+
self:impl_trait>
27792807

27802808
<%self:impl_trait style_struct_name="InheritedTable"
27812809
skip_longhands="border-spacing">
@@ -2789,7 +2817,6 @@ fn static_assert() {
27892817
self.gecko.mBorderSpacingCol = other.gecko.mBorderSpacingCol;
27902818
self.gecko.mBorderSpacingRow = other.gecko.mBorderSpacingRow;
27912819
}
2792-
27932820
self:impl_trait>
27942821

27952822

components/style/properties/longhand/box.mako.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
13321332
computed_value::T(None)
13331333
}
13341334

1335+
// Allow unitless zero angle for rotate() and skew() to align with gecko
13351336
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
13361337
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
13371338
return Ok(SpecifiedValue(Vec::new()))
@@ -1469,28 +1470,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
14691470
},
14701471
"rotate" => {
14711472
try!(input.parse_nested_block(|input| {
1472-
let theta = try!(specified::Angle::parse(context,input));
1473+
let theta = try!(specified::Angle::parse_with_unitless(context,input));
14731474
result.push(SpecifiedOperation::Rotate(theta));
14741475
Ok(())
14751476
}))
14761477
},
14771478
"rotatex" => {
14781479
try!(input.parse_nested_block(|input| {
1479-
let theta = try!(specified::Angle::parse(context,input));
1480+
let theta = try!(specified::Angle::parse_with_unitless(context,input));
14801481
result.push(SpecifiedOperation::RotateX(theta));
14811482
Ok(())
14821483
}))
14831484
},
14841485
"rotatey" => {
14851486
try!(input.parse_nested_block(|input| {
1486-
let theta = try!(specified::Angle::parse(context,input));
1487+
let theta = try!(specified::Angle::parse_with_unitless(context,input));
14871488
result.push(SpecifiedOperation::RotateY(theta));
14881489
Ok(())
14891490
}))
14901491
},
14911492
"rotatez" => {
14921493
try!(input.parse_nested_block(|input| {
1493-
let theta = try!(specified::Angle::parse(context,input));
1494+
let theta = try!(specified::Angle::parse_with_unitless(context,input));
14941495
result.push(SpecifiedOperation::RotateZ(theta));
14951496
Ok(())
14961497
}))
@@ -1503,17 +1504,17 @@ ${helpers.predefined_type("scroll-snap-coordinate",
15031504
try!(input.expect_comma());
15041505
let az = try!(specified::parse_number(input));
15051506
try!(input.expect_comma());
1506-
let theta = try!(specified::Angle::parse(context,input));
1507+
let theta = try!(specified::Angle::parse_with_unitless(context,input));
15071508
// TODO(gw): Check the axis can be normalized!!
15081509
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
15091510
Ok(())
15101511
}))
15111512
},
15121513
"skew" => {
15131514
try!(input.parse_nested_block(|input| {
1514-
let theta_x = try!(specified::Angle::parse(context, input));
1515+
let theta_x = try!(specified::Angle::parse_with_unitless(context, input));
15151516
if input.try(|input| input.expect_comma()).is_ok() {
1516-
let theta_y = try!(specified::Angle::parse(context, input));
1517+
let theta_y = try!(specified::Angle::parse_with_unitless(context, input));
15171518
result.push(SpecifiedOperation::Skew(theta_x, Some(theta_y)));
15181519
} else {
15191520
result.push(SpecifiedOperation::Skew(theta_x, None));
@@ -1523,14 +1524,14 @@ ${helpers.predefined_type("scroll-snap-coordinate",
15231524
},
15241525
"skewx" => {
15251526
try!(input.parse_nested_block(|input| {
1526-
let theta_x = try!(specified::Angle::parse(context,input));
1527+
let theta_x = try!(specified::Angle::parse_with_unitless(context,input));
15271528
result.push(SpecifiedOperation::SkewX(theta_x));
15281529
Ok(())
15291530
}))
15301531
},
15311532
"skewy" => {
15321533
try!(input.parse_nested_block(|input| {
1533-
let theta_y = try!(specified::Angle::parse(context,input));
1534+
let theta_y = try!(specified::Angle::parse_with_unitless(context,input));
15341535
result.push(SpecifiedOperation::SkewY(theta_y));
15351536
Ok(())
15361537
}))

components/style/properties/longhand/inherited_box.mako.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ ${helpers.single_keyword("image-rendering",
8383

8484
// Image Orientation
8585
<%helpers:longhand name="image-orientation"
86-
products="None"
86+
products="gecko"
8787
animation_type="none"
8888
spec="https://drafts.csswg.org/css-images/#propdef-image-orientation, \
8989
/// additional values in https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation">
@@ -199,21 +199,23 @@ ${helpers.single_keyword("image-rendering",
199199
}
200200
}
201201

202+
// from-image | | [? flip]
202203
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
203204
if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
204205
// Handle from-image
205206
Ok(SpecifiedValue { angle: None, flipped: false })
207+
} else if input.try(|input| input.expect_ident_matching("flip")).is_ok() {
208+
// Handle flip
209+
Ok(SpecifiedValue { angle: Some(Angle::zero()), flipped: true })
206210
} else {
207-
// Handle | ? flip
211+
// Handle | flip
208212
let angle = input.try(|input| Angle::parse(context, input)).ok();
209-
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
210-
let explicit_angle = if angle.is_none() && !flipped {
211-
Some(Angle::zero())
212-
} else {
213-
angle
214-
};
213+
if angle.is_none() {
214+
return Err(());
215+
}
215216

216-
Ok(SpecifiedValue { angle: explicit_angle, flipped: flipped })
217+
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
218+
Ok(SpecifiedValue { angle: angle, flipped: flipped })
217219
}
218220
}
219221
helpers:longhand>

components/style/values/specified/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,6 @@ impl Parse for Angle {
430430
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
431431
match try!(input.next()) {
432432
Token::Dimension(ref value, ref unit) => Angle::parse_dimension(value.value, unit),
433-
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
434433
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
435434
input.parse_nested_block(CalcLengthOrPercentage::parse_angle)
436435
},
@@ -451,6 +450,22 @@ impl Angle {
451450
};
452451
Ok(angle)
453452
}
453+
/// Parse an angle, including unitless 0 degree.
454+
/// Note that numbers without any AngleUnit, including unitless 0
455+
/// angle, should be invalid. However, some properties still accept
456+
/// unitless 0 angle and stores it as '0deg'. We can remove this and
457+
/// get back to the unified version Angle::parse once
458+
/// https://github.com/w3c/csswg-drafts/issues/1162 is resolved.
459+
pub fn parse_with_unitless(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
460+
match try!(input.next()) {
461+
Token::Dimension(ref value, ref unit) => Angle::parse_dimension(value.value, unit),
462+
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
463+
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
464+
input.parse_nested_block(CalcLengthOrPercentage::parse_angle)
465+
},
466+
_ => Err(())
467+
}
468+
}
454469
}
455470

456471
#[allow(missing_docs)]

tests/unit/style/parsing/inherited_box.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn image_orientation_longhand_should_parse_properly() {
1717
assert_eq!(from_image, SpecifiedValue { angle: None, flipped: false });
1818

1919
let flip = parse_longhand!(image_orientation, "flip");
20-
assert_eq!(flip, SpecifiedValue { angle: None, flipped: true });
20+
assert_eq!(flip, SpecifiedValue { angle: Some(Angle::from_degrees(0.0)), flipped: true });
2121

2222
let zero = parse_longhand!(image_orientation, "0deg");
2323
assert_eq!(zero, SpecifiedValue { angle: Some(Angle::from_degrees(0.0)), flipped: false });

0 commit comments

Comments
 (0)