diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-07-11 11:22:26 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-11 11:22:26 -0700 |
commit | de331c6bc8f987521d600043285d32f42be07048 (patch) | |
tree | 3346d6a5d8fa416fcf66c5db6a20d6a8dd56fe17 | |
parent | bc1ac6e64cd9735d87e4057f4bbe61023ffc22f5 (diff) | |
parent | e554146e2a6d1b4ecf409ab8980574e0dd007e8e (diff) | |
download | servo-de331c6bc8f987521d600043285d32f42be07048.tar.gz servo-de331c6bc8f987521d600043285d32f42be07048.zip |
Auto merge of #17654 - jyc:image-orientation, r=Manishearth
Make Servo's rounding of image-orientation values agree with Gecko's, and pass orientations directly as an enum instead of as angles.
Has been reviewed: https://reviewboard.mozilla.org/r/155336/
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [ ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Bugzilla issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1355380
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17654)
<!-- Reviewable:end -->
-rw-r--r-- | components/style/gecko/generated/bindings.rs | 2 | ||||
-rw-r--r-- | components/style/properties/gecko.mako.rs | 4 | ||||
-rw-r--r-- | components/style/properties/longhand/inherited_box.mako.rs | 79 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 29 |
4 files changed, 85 insertions, 29 deletions
diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index 427992d8939..f5c64216008 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -897,7 +897,7 @@ extern "C" { } extern "C" { pub fn Gecko_SetImageOrientation(aVisibility: *mut nsStyleVisibility, - aRadians: f64, aFlip: bool); + aOrientation: u8, aFlip: bool); } extern "C" { pub fn Gecko_SetImageOrientationAsFromImage(aVisibility: diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 13f7b130841..240139c33cb 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3846,9 +3846,9 @@ fn static_assert() { bindings::Gecko_SetImageOrientationAsFromImage(&mut self.gecko); } }, - T::AngleWithFlipped(ref angle, flipped) => { + T::AngleWithFlipped(ref orientation, flipped) => { unsafe { - bindings::Gecko_SetImageOrientation(&mut self.gecko, angle.radians() as f64, flipped); + bindings::Gecko_SetImageOrientation(&mut self.gecko, *orientation as u8, flipped); } } } diff --git a/components/style/properties/longhand/inherited_box.mako.rs b/components/style/properties/longhand/inherited_box.mako.rs index 772847df0ba..b6830761abf 100644 --- a/components/style/properties/longhand/inherited_box.mako.rs +++ b/components/style/properties/longhand/inherited_box.mako.rs @@ -68,9 +68,8 @@ ${helpers.single_keyword("image-rendering", no_viewport_percentage!(SpecifiedValue); - use std::f32::consts::PI; - use values::CSSFloat; - const TWO_PI: CSSFloat = 2.0 * PI; + use std::f64::consts::PI; + const TWO_PI: f64 = 2.0 * PI; #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -99,31 +98,77 @@ ${helpers.single_keyword("image-rendering", } pub mod computed_value { - use values::computed::Angle; + use std::fmt; + use style_traits::ToCss; + use values::specified::Angle; + + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + pub enum Orientation { + Angle0 = 0, + Angle90, + Angle180, + Angle270, + } + + impl Orientation { + pub fn angle(&self) -> Angle { + match *self { + Orientation::Angle0 => Angle::from_degrees(0.0, false), + Orientation::Angle90 => Angle::from_degrees(90.0, false), + Orientation::Angle180 => Angle::from_degrees(180.0, false), + Orientation::Angle270 => Angle::from_degrees(270.0, false), + } + } + } + + impl ToCss for Orientation { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + // Should agree with Angle::to_css. + match *self { + Orientation::Angle0 => dest.write_str("0deg"), + Orientation::Angle90 => dest.write_str("90deg"), + Orientation::Angle180 => dest.write_str("180deg"), + Orientation::Angle270 => dest.write_str("270deg"), + } + } + } #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum T { FromImage, - AngleWithFlipped(Angle, bool), + AngleWithFlipped(Orientation, bool), } } + use self::computed_value::Orientation; + #[inline] pub fn get_initial_value() -> computed_value::T { - computed_value::T::AngleWithFlipped(computed::Angle::zero(), false) + computed_value::T::AngleWithFlipped(Orientation::Angle0, false) } // According to CSS Content Module Level 3: // The computed value of the property is calculated by rounding the specified angle // to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn. + // This mirrors the Gecko implementation in + // nsStyleImageOrientation::CreateAsAngleAndFlip. #[inline] - fn normalize_angle(angle: &computed::Angle) -> computed::Angle { - let radians = angle.radians(); - let rounded_quarter_turns = (4.0 * radians / TWO_PI).round(); - let normalized_quarter_turns = (rounded_quarter_turns % 4.0 + 4.0) % 4.0; - let normalized_radians = normalized_quarter_turns/4.0 * TWO_PI; - computed::Angle::from_radians(normalized_radians) + fn orientation_of_angle(angle: &computed::Angle) -> Orientation { + // Note that `angle` can be negative. + let mut rounded_angle = angle.radians64() % TWO_PI; + if rounded_angle < 0.0 { + // This computation introduces rounding error. Gecko previously + // didn't handle the negative case correctly; by branching we can + // match Gecko's behavior when it was correct. + rounded_angle = rounded_angle + TWO_PI; + } + if rounded_angle < 0.25 * PI { Orientation::Angle0 } + else if rounded_angle < 0.75 * PI { Orientation::Angle90 } + else if rounded_angle < 1.25 * PI { Orientation::Angle180 } + else if rounded_angle < 1.75 * PI { Orientation::Angle270 } + else { Orientation::Angle0 } } impl ToComputedValue for SpecifiedValue { @@ -133,11 +178,11 @@ ${helpers.single_keyword("image-rendering", fn to_computed_value(&self, context: &Context) -> computed_value::T { if let Some(ref angle) = self.angle { let angle = angle.to_computed_value(context); - let normalized_angle = normalize_angle(&angle); - computed_value::T::AngleWithFlipped(normalized_angle, self.flipped) + let orientation = orientation_of_angle(&angle); + computed_value::T::AngleWithFlipped(orientation, self.flipped) } else { if self.flipped { - computed_value::T::AngleWithFlipped(computed::Angle::zero(), true) + computed_value::T::AngleWithFlipped(Orientation::Angle0, true) } else { computed_value::T::FromImage } @@ -148,9 +193,9 @@ ${helpers.single_keyword("image-rendering", fn from_computed_value(computed: &computed_value::T) -> Self { match *computed { computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false }, - computed_value::T::AngleWithFlipped(ref angle, flipped) => { + computed_value::T::AngleWithFlipped(ref orientation, flipped) => { SpecifiedValue { - angle: Some(Angle::from_computed_value(angle)), + angle: Some(orientation.angle()), flipped: flipped, } } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 9b08cd6e2bb..1183cbd3044 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -13,7 +13,8 @@ use media_queries::Device; use properties; use properties::{ComputedValues, StyleBuilder}; use std::f32; -use std::f32::consts::PI; +use std::f64; +use std::f64::consts::PI; use std::fmt; use style_traits::ToCss; use super::{CSSFloat, CSSInteger, RGBA}; @@ -313,17 +314,27 @@ impl Angle { /// Return the amount of radians this angle represents. #[inline] pub fn radians(&self) -> CSSFloat { - const RAD_PER_DEG: CSSFloat = PI / 180.0; - const RAD_PER_GRAD: CSSFloat = PI / 200.0; - const RAD_PER_TURN: CSSFloat = PI * 2.0; + self.radians64().min(f32::MAX as f64).max(f32::MIN as f64) as f32 + } + + /// Return the amount of radians this angle represents as a 64-bit float. + /// Gecko stores angles as singles, but does this computation using doubles. + /// See nsCSSValue::GetAngleValueInRadians. + /// This is significant enough to mess up rounding to the nearest + /// quarter-turn for 225 degrees, for example. + #[inline] + pub fn radians64(&self) -> f64 { + const RAD_PER_DEG: f64 = PI / 180.0; + const RAD_PER_GRAD: f64 = PI / 200.0; + const RAD_PER_TURN: f64 = PI * 2.0; let radians = match *self { - Angle::Degree(val) => val * RAD_PER_DEG, - Angle::Gradian(val) => val * RAD_PER_GRAD, - Angle::Turn(val) => val * RAD_PER_TURN, - Angle::Radian(val) => val, + Angle::Degree(val) => val as f64 * RAD_PER_DEG, + Angle::Gradian(val) => val as f64 * RAD_PER_GRAD, + Angle::Turn(val) => val as f64 * RAD_PER_TURN, + Angle::Radian(val) => val as f64, }; - radians.min(f32::MAX).max(f32::MIN) + radians.min(f64::MAX).max(f64::MIN) } /// Returns an angle that represents a rotation of zero radians. |