servo: Merge #14703 - Add gecko glue for perspective/transform properties (from canaltinova:perspective-transform); r=Wafflespeanut
authorNazım Can Altınova <canaltinova@gmail.com>
Mon, 26 Dec 2016 21:48:52 -0800
changeset 340427 3f4d3ac3afe2cb29e6d77bab5dfebfda69aede58
parent 340426 72029e42297f8a40f102e144a76bd06aa2c803cf
child 340428 14bdb85b2c96619dd963451c49524670610ef681
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWafflespeanut
servo: Merge #14703 - Add gecko glue for perspective/transform properties (from canaltinova:perspective-transform); r=Wafflespeanut <!-- Please describe your changes on the following line: --> To be able to add glue for these properties, we needed to change their structs. They are moved from effects to box and added stylo glue. This PR covers these properties: - perspective - perspective-origin - backface-visibility - transform-box - transform-style - transform-origin --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> - [X] These changes do not require tests because they are stylo changes <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: a6d206eb6687da31c957094bbed380c9e47daac4
servo/components/layout/display_list_builder.rs
servo/components/layout/fragment.rs
servo/components/style/gecko/values.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/effects.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/servo/restyle_damage.rs
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -1562,19 +1562,19 @@ impl FragmentDisplayListBuilding for Fra
         // First, compute the offset of our border box (including relative positioning)
         // from our flow origin, since that is what `BaseFlow::overflow` is relative to.
         let border_box_offset =
             border_box.translate(&-base_flow.stacking_relative_position).origin;
         // Then, using that, compute our overflow region relative to our border box.
         let overflow = base_flow.overflow.paint.translate(&-border_box_offset);
 
         let transform = self.transform_matrix(&border_box);
-        let perspective = match self.style().get_effects().perspective {
+        let perspective = match self.style().get_box().perspective {
             Either::First(length) => {
-                let perspective_origin = self.style().get_effects().perspective_origin;
+                let perspective_origin = self.style().get_box().perspective_origin;
                 let perspective_origin =
                     Point2D::new(model::specified(perspective_origin.horizontal,
                                                   border_box.size.width).to_f32_px(),
                                  model::specified(perspective_origin.vertical,
                                                   border_box.size.height).to_f32_px());
 
                 let pre_transform = Matrix4D::create_translation(perspective_origin.x,
                                                                  perspective_origin.y,
@@ -1817,17 +1817,17 @@ impl FragmentDisplayListBuilding for Fra
 
     fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Matrix4D<f32> {
         let mut transform = Matrix4D::identity();
         let operations = match self.style.get_box().transform.0 {
             None => return transform,
             Some(ref operations) => operations,
         };
 
-        let transform_origin = &self.style.get_effects().transform_origin;
+        let transform_origin = &self.style.get_box().transform_origin;
         let transform_origin_x = model::specified(transform_origin.horizontal,
                                                   stacking_relative_border_box.size
                                                                               .width).to_f32_px();
         let transform_origin_y = model::specified(transform_origin.vertical,
                                                   stacking_relative_border_box.size
                                                                               .height).to_f32_px();
         let transform_origin_z = transform_origin.depth.to_f32_px();
 
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -2365,17 +2365,17 @@ impl Fragment {
             return true
         }
         if self.style().get_box().transform.0.is_some() {
             return true
         }
 
         // TODO(mrobinson): Determine if this is necessary, since blocks with
         // transformations already create stacking contexts.
-        if let Either::First(ref _length) = self.style().get_effects().perspective {
+        if let Either::First(ref _length) = self.style().get_box().perspective {
             return true
         }
 
         // Fixed position blocks always create stacking contexts.
         if self.style.get_box().position == position::T::fixed {
             return true
         }
 
--- a/servo/components/style/gecko/values.rs
+++ b/servo/components/style/gecko/values.rs
@@ -4,17 +4,17 @@
 
 #![allow(unsafe_code)]
 
 use app_units::Au;
 use cssparser::RGBA;
 use gecko_bindings::structs::{nsStyleCoord, StyleShapeRadius};
 use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
 use std::cmp::max;
-use values::{Auto, Either};
+use values::{Auto, Either, None_};
 use values::computed::{Angle, LengthOrPercentageOrNone, Number};
 use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
 use values::computed::basic_shape::ShapeRadius;
 
 pub trait StyleCoordHelpers {
     fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T);
 }
 
@@ -202,16 +202,30 @@ impl GeckoStyleCoordConvertible for Auto
         if let CoordDataValue::Auto = coord.as_value() {
             Some(Auto)
         } else {
             None
         }
     }
 }
 
+impl GeckoStyleCoordConvertible for None_ {
+    fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
+        coord.set_value(CoordDataValue::None)
+    }
+
+    fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
+        if let CoordDataValue::None = coord.as_value() {
+            Some(None_)
+        } else {
+            None
+        }
+    }
+}
+
 pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
     (((rgba.alpha * 255.0).round() as u32) << 24) |
     (((rgba.blue  * 255.0).round() as u32) << 16) |
     (((rgba.green * 255.0).round() as u32) << 8) |
      ((rgba.red   * 255.0).round() as u32)
 }
 
 pub fn convert_nscolor_to_rgba(color: u32) -> RGBA {
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -470,18 +470,16 @@ impl Debug for ${style_struct.gecko_stru
 <%
     longhands = [x for x in style_struct.longhands
                 if not (skip_longhands == "*" or x.name in skip_longhands.split())]
 
     #
     # Make a list of types we can't auto-generate.
     #
     force_stub = [];
-    # These are currently being shuffled to a different style struct on the gecko side.
-    force_stub += ["backface-visibility", "transform-box", "transform-style"]
     # These live in an nsFont member in Gecko. Should be straightforward to do manually.
     force_stub += ["font-variant"]
     # These have unusual representations in gecko.
     force_stub += ["list-style-type"]
     # In a nsTArray, have to be done manually, but probably not too much work
     # (the "filling them", not the "making them work")
     force_stub += ["animation-name", "animation-duration",
                   "animation-timing-function", "animation-iteration-count",
@@ -500,16 +498,17 @@ impl Debug for ${style_struct.gecko_stru
 
     # Types used with predefined_type()-defined properties that we can auto-generate.
     predefined_types = {
         "length::LengthOrAuto": impl_style_coord,
         "Length": impl_style_coord,
         "LengthOrPercentage": impl_style_coord,
         "LengthOrPercentageOrAuto": impl_style_coord,
         "LengthOrPercentageOrNone": impl_style_coord,
+        "LengthOrNone": impl_style_coord,
         "Number": impl_simple,
         "Opacity": impl_simple,
         "CSSColor": impl_color,
     }
 
     def longhand_method(longhand):
         args = dict(ident=longhand.ident, gecko_ffi_name=longhand.gecko_ffi_name,
                     need_clone=longhand.need_clone)
@@ -1048,17 +1047,17 @@ fn static_assert() {
         }
     }
 
 </%self:impl_trait>
 
 <% skip_box_longhands= """display overflow-y vertical-align
                           -moz-binding page-break-before page-break-after
                           scroll-snap-points-x scroll-snap-points-y transform
-                          scroll-snap-type-y""" %>
+                          scroll-snap-type-y perspective-origin transform-origin""" %>
 <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
 
     // We manually-implement the |display| property until we get general
     // infrastructure for preffing certain values.
     <% display_keyword = Keyword("display", "inline block inline-block table inline-table table-row-group " +
                                             "table-header-group table-footer-group table-row table-column-group " +
                                             "table-column table-cell table-caption list-item flex none " +
                                             "inline-flex grid inline-grid ruby ruby-base ruby-base-container " +
@@ -1320,16 +1319,50 @@ fn static_assert() {
     pub fn copy_transform_from(&mut self, other: &Self) {
         unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); }
     }
 
     <% scroll_snap_type_keyword = Keyword("scroll-snap-type", "none mandatory proximity") %>
 
     ${impl_keyword('scroll_snap_type_y', 'mScrollSnapTypeY', scroll_snap_type_keyword, need_clone=False)}
 
+    pub fn set_perspective_origin(&mut self, v: longhands::perspective_origin::computed_value::T) {
+        self.gecko.mPerspectiveOrigin[0].set(v.horizontal);
+        self.gecko.mPerspectiveOrigin[1].set(v.vertical);
+    }
+
+    pub fn copy_perspective_origin_from(&mut self, other: &Self) {
+        self.gecko.mPerspectiveOrigin[0].copy_from(&other.gecko.mPerspectiveOrigin[0]);
+        self.gecko.mPerspectiveOrigin[1].copy_from(&other.gecko.mPerspectiveOrigin[1]);
+    }
+
+    pub fn set_transform_origin(&mut self, v: longhands::transform_origin::computed_value::T) {
+        self.gecko.mTransformOrigin[0].set(v.horizontal);
+        self.gecko.mTransformOrigin[1].set(v.vertical);
+        self.gecko.mTransformOrigin[2].set(v.depth);
+    }
+
+    pub fn copy_transform_origin_from(&mut self, other: &Self) {
+        self.gecko.mTransformOrigin[0].copy_from(&other.gecko.mTransformOrigin[0]);
+        self.gecko.mTransformOrigin[1].copy_from(&other.gecko.mTransformOrigin[1]);
+        self.gecko.mTransformOrigin[2].copy_from(&other.gecko.mTransformOrigin[2]);
+    }
+
+    pub fn clone_transform_origin(&self) -> longhands::transform_origin::computed_value::T {
+        use properties::longhands::transform_origin::computed_value::T;
+        use values::computed::LengthOrPercentage;
+        T {
+            horizontal: LengthOrPercentage::from_gecko_style_coord(&self.gecko.mTransformOrigin[0])
+                .expect("clone for LengthOrPercentage failed"),
+            vertical: LengthOrPercentage::from_gecko_style_coord(&self.gecko.mTransformOrigin[1])
+                .expect("clone for LengthOrPercentage failed"),
+            depth: Au::from_gecko_style_coord(&self.gecko.mTransformOrigin[2])
+                .expect("clone for Length failed"),
+        }
+    }
 </%self:impl_trait>
 
 <%def name="simple_image_array_property(name, shorthand, field_name)">
     <%
         image_layers_field = "mImage" if shorthand == "background" else "mMask"
     %>
     pub fn copy_${shorthand}_${name}_from(&mut self, other: &Self) {
         use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -1521,16 +1521,238 @@
 
 // CSS Basic User Interface Module Level 3
 // http://dev.w3.org/csswg/css-ui/
 ${helpers.single_keyword("resize",
                          "none both horizontal vertical",
                          products="gecko",
                          animatable=False)}
 
+
+// https://drafts.csswg.org/css-transforms/#perspective
+${helpers.predefined_type("perspective",
+                          "LengthOrNone",
+                          "Either::Second(None_)",
+                          gecko_ffi_name="mChildPerspective",
+                          animatable=True)}
+
+// FIXME: This prop should be animatable
+// https://drafts.csswg.org/css-transforms/#perspective-origin-property
+<%helpers:longhand name="perspective-origin" animatable="False">
+    use std::fmt;
+    use style_traits::ToCss;
+    use values::HasViewportPercentage;
+    use values::specified::{LengthOrPercentage, Percentage};
+
+    pub mod computed_value {
+        use values::computed::LengthOrPercentage;
+
+        #[derive(Clone, Copy, Debug, PartialEq)]
+        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+        pub struct T {
+            pub horizontal: LengthOrPercentage,
+            pub vertical: LengthOrPercentage,
+        }
+    }
+
+    impl ToCss for computed_value::T {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            try!(self.horizontal.to_css(dest));
+            try!(dest.write_str(" "));
+            self.vertical.to_css(dest)
+        }
+    }
+
+    impl HasViewportPercentage for SpecifiedValue {
+        fn has_viewport_percentage(&self) -> bool {
+            self.horizontal.has_viewport_percentage() || self.vertical.has_viewport_percentage()
+        }
+    }
+
+    #[derive(Clone, Copy, Debug, PartialEq)]
+    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+    pub struct SpecifiedValue {
+        horizontal: LengthOrPercentage,
+        vertical: LengthOrPercentage,
+    }
+
+    impl ToCss for SpecifiedValue {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            try!(self.horizontal.to_css(dest));
+            try!(dest.write_str(" "));
+            self.vertical.to_css(dest)
+        }
+    }
+
+    #[inline]
+    pub fn get_initial_value() -> computed_value::T {
+        computed_value::T {
+            horizontal: computed::LengthOrPercentage::Percentage(0.5),
+            vertical: computed::LengthOrPercentage::Percentage(0.5),
+        }
+    }
+
+    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
+        let result = try!(super::parse_origin(context, input));
+        match result.depth {
+            Some(_) => Err(()),
+            None => Ok(SpecifiedValue {
+                horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
+                vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
+            })
+        }
+    }
+
+    impl ToComputedValue for SpecifiedValue {
+        type ComputedValue = computed_value::T;
+
+        #[inline]
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
+            computed_value::T {
+                horizontal: self.horizontal.to_computed_value(context),
+                vertical: self.vertical.to_computed_value(context),
+            }
+        }
+
+        #[inline]
+        fn from_computed_value(computed: &computed_value::T) -> Self {
+            SpecifiedValue {
+                horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
+                vertical: ToComputedValue::from_computed_value(&computed.vertical),
+            }
+        }
+    }
+</%helpers:longhand>
+
+// https://drafts.csswg.org/css-transforms/#backface-visibility-property
+${helpers.single_keyword("backface-visibility",
+                         "visible hidden",
+                         animatable=False)}
+
+// https://drafts.csswg.org/css-transforms/#transform-box
+${helpers.single_keyword("transform-box",
+                         "border-box fill-box view-box",
+                         products="gecko",
+                         animatable=False)}
+
+// `auto` keyword is not supported in gecko yet.
+// https://drafts.csswg.org/css-transforms/#transform-style-property
+${helpers.single_keyword("transform-style",
+                         "auto flat preserve-3d" if product == "servo" else
+                         "flat preserve-3d",
+                         animatable=False)}
+
+// https://drafts.csswg.org/css-transforms/#transform-origin-property
+<%helpers:longhand name="transform-origin" animatable="True">
+    use app_units::Au;
+    use std::fmt;
+    use style_traits::ToCss;
+    use values::HasViewportPercentage;
+    use values::specified::{Length, LengthOrPercentage, Percentage};
+
+    pub mod computed_value {
+        use properties::animated_properties::Interpolate;
+        use values::computed::{Length, LengthOrPercentage};
+
+        #[derive(Clone, Copy, Debug, PartialEq)]
+        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+        pub struct T {
+            pub horizontal: LengthOrPercentage,
+            pub vertical: LengthOrPercentage,
+            pub depth: Length,
+        }
+
+        impl Interpolate for T {
+            fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
+                Ok(T {
+                    horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
+                    vertical: try!(self.vertical.interpolate(&other.vertical, time)),
+                    depth: try!(self.depth.interpolate(&other.depth, time)),
+                })
+            }
+        }
+    }
+
+    impl HasViewportPercentage for SpecifiedValue {
+        fn has_viewport_percentage(&self) -> bool {
+            self.horizontal.has_viewport_percentage() ||
+            self.vertical.has_viewport_percentage() ||
+            self.depth.has_viewport_percentage()
+        }
+    }
+
+    #[derive(Clone, Copy, Debug, PartialEq)]
+    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+    pub struct SpecifiedValue {
+        horizontal: LengthOrPercentage,
+        vertical: LengthOrPercentage,
+        depth: Length,
+    }
+
+    impl ToCss for computed_value::T {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            try!(self.horizontal.to_css(dest));
+            try!(dest.write_str(" "));
+            try!(self.vertical.to_css(dest));
+            try!(dest.write_str(" "));
+            self.depth.to_css(dest)
+        }
+    }
+
+    impl ToCss for SpecifiedValue {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            try!(self.horizontal.to_css(dest));
+            try!(dest.write_str(" "));
+            try!(self.vertical.to_css(dest));
+            try!(dest.write_str(" "));
+            self.depth.to_css(dest)
+        }
+    }
+
+    #[inline]
+    pub fn get_initial_value() -> computed_value::T {
+        computed_value::T {
+            horizontal: computed::LengthOrPercentage::Percentage(0.5),
+            vertical: computed::LengthOrPercentage::Percentage(0.5),
+            depth: Au(0),
+        }
+    }
+
+    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
+        let result = try!(super::parse_origin(context, input));
+        Ok(SpecifiedValue {
+            horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
+            vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
+            depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
+        })
+    }
+
+    impl ToComputedValue for SpecifiedValue {
+        type ComputedValue = computed_value::T;
+
+        #[inline]
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
+            computed_value::T {
+                horizontal: self.horizontal.to_computed_value(context),
+                vertical: self.vertical.to_computed_value(context),
+                depth: self.depth.to_computed_value(context),
+            }
+        }
+
+        #[inline]
+        fn from_computed_value(computed: &computed_value::T) -> Self {
+            SpecifiedValue {
+                horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
+                vertical: ToComputedValue::from_computed_value(&computed.vertical),
+                depth: ToComputedValue::from_computed_value(&computed.depth),
+            }
+        }
+    }
+</%helpers:longhand>
+
 // Non-standard
 ${helpers.single_keyword("-moz-appearance",
                          """none button button-arrow-down button-arrow-next button-arrow-previous button-arrow-up
                             button-bevel button-focus caret checkbox checkbox-container checkbox-label checkmenuitem
                             dualbutton groupbox listbox listitem menuarrow menubar menucheckbox menuimage menuitem
                             menuitemtext menulist menulist-button menulist-text menulist-textfield menupopup menuradio
                             menuseparator meterbar meterchunk progressbar progressbar-vertical progresschunk
                             progresschunk-vertical radio radio-container radio-label radiomenuitem range range-thumb
--- a/servo/components/style/properties/longhand/effects.mako.rs
+++ b/servo/components/style/properties/longhand/effects.mako.rs
@@ -685,226 +685,13 @@ pub fn parse_origin(context: &ParserCont
             vertical: vertical,
             depth: depth,
         })
     } else {
         Err(())
     }
 }
 
-${helpers.single_keyword("backface-visibility",
-                         "visible hidden",
-                         animatable=False)}
-
-${helpers.single_keyword("transform-box",
-                         "border-box fill-box view-box",
-                         products="gecko",
-                         animatable=False)}
-
-${helpers.single_keyword("transform-style",
-                         "auto flat preserve-3d",
-                         animatable=False)}
-
-<%helpers:longhand name="transform-origin" products="servo" animatable="True">
-    use app_units::Au;
-    use std::fmt;
-    use style_traits::ToCss;
-    use values::HasViewportPercentage;
-    use values::specified::{Length, LengthOrPercentage, Percentage};
-
-    pub mod computed_value {
-        use properties::animated_properties::Interpolate;
-        use values::computed::{Length, LengthOrPercentage};
-
-        #[derive(Clone, Copy, Debug, PartialEq)]
-        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-        pub struct T {
-            pub horizontal: LengthOrPercentage,
-            pub vertical: LengthOrPercentage,
-            pub depth: Length,
-        }
-
-        impl Interpolate for T {
-            fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
-                Ok(T {
-                    horizontal: try!(self.horizontal.interpolate(&other.horizontal, time)),
-                    vertical: try!(self.vertical.interpolate(&other.vertical, time)),
-                    depth: try!(self.depth.interpolate(&other.depth, time)),
-                })
-            }
-        }
-    }
-
-    impl HasViewportPercentage for SpecifiedValue {
-        fn has_viewport_percentage(&self) -> bool {
-            self.horizontal.has_viewport_percentage() ||
-            self.vertical.has_viewport_percentage() ||
-            self.depth.has_viewport_percentage()
-        }
-    }
-
-    #[derive(Clone, Copy, Debug, PartialEq)]
-    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-    pub struct SpecifiedValue {
-        horizontal: LengthOrPercentage,
-        vertical: LengthOrPercentage,
-        depth: Length,
-    }
-
-    impl ToCss for computed_value::T {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            try!(self.horizontal.to_css(dest));
-            try!(dest.write_str(" "));
-            try!(self.vertical.to_css(dest));
-            try!(dest.write_str(" "));
-            self.depth.to_css(dest)
-        }
-    }
-
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            try!(self.horizontal.to_css(dest));
-            try!(dest.write_str(" "));
-            try!(self.vertical.to_css(dest));
-            try!(dest.write_str(" "));
-            self.depth.to_css(dest)
-        }
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T {
-            horizontal: computed::LengthOrPercentage::Percentage(0.5),
-            vertical: computed::LengthOrPercentage::Percentage(0.5),
-            depth: Au(0),
-        }
-    }
-
-    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
-        let result = try!(super::parse_origin(context, input));
-        Ok(SpecifiedValue {
-            horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
-            vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
-            depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
-        })
-    }
-
-    impl ToComputedValue for SpecifiedValue {
-        type ComputedValue = computed_value::T;
-
-        #[inline]
-        fn to_computed_value(&self, context: &Context) -> computed_value::T {
-            computed_value::T {
-                horizontal: self.horizontal.to_computed_value(context),
-                vertical: self.vertical.to_computed_value(context),
-                depth: self.depth.to_computed_value(context),
-            }
-        }
-
-        #[inline]
-        fn from_computed_value(computed: &computed_value::T) -> Self {
-            SpecifiedValue {
-                horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
-                vertical: ToComputedValue::from_computed_value(&computed.vertical),
-                depth: ToComputedValue::from_computed_value(&computed.depth),
-            }
-        }
-    }
-</%helpers:longhand>
-
-${helpers.predefined_type("perspective",
-                          "LengthOrNone",
-                          "Either::Second(None_)",
-                          products="servo",
-                          animatable=True)}
-
-// FIXME: This prop should be animatable
-<%helpers:longhand name="perspective-origin" products="servo" animatable="False">
-    use std::fmt;
-    use style_traits::ToCss;
-    use values::HasViewportPercentage;
-    use values::specified::{LengthOrPercentage, Percentage};
-
-    pub mod computed_value {
-        use values::computed::LengthOrPercentage;
-
-        #[derive(Clone, Copy, Debug, PartialEq)]
-        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-        pub struct T {
-            pub horizontal: LengthOrPercentage,
-            pub vertical: LengthOrPercentage,
-        }
-    }
-
-    impl ToCss for computed_value::T {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            try!(self.horizontal.to_css(dest));
-            try!(dest.write_str(" "));
-            self.vertical.to_css(dest)
-        }
-    }
-
-    impl HasViewportPercentage for SpecifiedValue {
-        fn has_viewport_percentage(&self) -> bool {
-            self.horizontal.has_viewport_percentage() || self.vertical.has_viewport_percentage()
-        }
-    }
-
-    #[derive(Clone, Copy, Debug, PartialEq)]
-    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-    pub struct SpecifiedValue {
-        horizontal: LengthOrPercentage,
-        vertical: LengthOrPercentage,
-    }
-
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            try!(self.horizontal.to_css(dest));
-            try!(dest.write_str(" "));
-            self.vertical.to_css(dest)
-        }
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T {
-            horizontal: computed::LengthOrPercentage::Percentage(0.5),
-            vertical: computed::LengthOrPercentage::Percentage(0.5),
-        }
-    }
-
-    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
-        let result = try!(super::parse_origin(context, input));
-        match result.depth {
-            Some(_) => Err(()),
-            None => Ok(SpecifiedValue {
-                horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
-                vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
-            })
-        }
-    }
-
-    impl ToComputedValue for SpecifiedValue {
-        type ComputedValue = computed_value::T;
-
-        #[inline]
-        fn to_computed_value(&self, context: &Context) -> computed_value::T {
-            computed_value::T {
-                horizontal: self.horizontal.to_computed_value(context),
-                vertical: self.vertical.to_computed_value(context),
-            }
-        }
-
-        #[inline]
-        fn from_computed_value(computed: &computed_value::T) -> Self {
-            SpecifiedValue {
-                horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
-                vertical: ToComputedValue::from_computed_value(&computed.vertical),
-            }
-        }
-    }
-</%helpers:longhand>
-
 ${helpers.single_keyword("mix-blend-mode",
                          """normal multiply screen overlay darken lighten color-dodge
                             color-burn hard-light soft-light difference exclusion hue
                             saturation color luminosity""", gecko_constant_prefix="NS_STYLE_BLEND",
                          animatable=False)}
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -1338,27 +1338,27 @@ impl ComputedValues {
         // TODO(gw): Add clip-path, isolation, mask-image, mask-border-source when supported.
         if effects.opacity < 1.0 ||
            !effects.filter.is_empty() ||
            effects.clip.0.is_some() {
            effects.mix_blend_mode != mix_blend_mode::T::normal ||
             return transform_style::T::flat;
         }
 
-        if effects.transform_style == transform_style::T::auto {
+        if box_.transform_style == transform_style::T::auto {
             if box_.transform.0.is_some() {
                 return transform_style::T::flat;
             }
-            if let Either::First(ref _length) = effects.perspective {
+            if let Either::First(ref _length) = box_.perspective {
                 return transform_style::T::flat;
             }
         }
 
         // Return the computed value if not overridden by the above exceptions
-        effects.transform_style
+        box_.transform_style
     }
 
     pub fn transform_requires_layer(&self) -> bool {
         // Check if the transform matrix is 2D or 3D
         if let Some(ref transform_list) = self.get_box().transform.0 {
             for transform in transform_list {
                 match *transform {
                     computed_values::transform::ComputedOperation::Perspective(..) => {
--- a/servo/components/style/servo/restyle_damage.rs
+++ b/servo/components/style/servo/restyle_damage.rs
@@ -222,18 +222,18 @@ fn compute_damage(old: &ServoComputedVal
         get_position.flex_grow,
         get_position.flex_shrink,
         get_position.align_self
     ]) || add_if_not_equal!(old, new, damage,
                             [REPAINT, REPOSITION, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW], [
         get_position.top, get_position.left,
         get_position.right, get_position.bottom,
         get_effects.opacity,
-        get_box.transform, get_effects.transform_style, get_effects.transform_origin,
-        get_effects.perspective, get_effects.perspective_origin
+        get_box.transform, get_box.transform_style, get_box.transform_origin,
+        get_box.perspective, get_box.perspective_origin
     ]) || add_if_not_equal!(old, new, damage,
                             [REPAINT], [
         get_color.color, get_background.background_color,
         get_background.background_image, get_background.background_position_x,
         get_background.background_position_y, get_background.background_repeat,
         get_background.background_attachment, get_background.background_clip,
         get_background.background_origin, get_background.background_size,
         get_border.border_top_color, get_border.border_right_color,