Bug 1371115 - Part 3: implements nsStyleSides type properties animatable. r?hiro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Wed, 28 Jun 2017 10:23:38 +0900
changeset 601111 8285e6415e561402adf006a162e92ecf5300d9cd
parent 601110 c49a6fe42eb323eb904f5c6f050f389464d33e82
child 601112 d45b6c4d74df17c4c16bec30ec20525045e7c238
push id65962
push userbmo:dakatsuka@mozilla.com
push dateWed, 28 Jun 2017 01:27:06 +0000
reviewershiro
bugs1371115
milestone56.0a1
Bug 1371115 - Part 3: implements nsStyleSides type properties animatable. r?hiro In this patch, implements following properties: * border-image-outset * border-image-slice * border-image-width MozReview-Commit-ID: K4w1zqX6Zkd
servo/components/style/gecko_macros.rs
servo/components/style/lib.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/border.mako.rs
new file mode 100644
--- /dev/null
+++ b/servo/components/style/gecko_macros.rs
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Various macro helpers that depend on Gecko.
+
+/// This macro implemets generic Rect for style coord such LengthOrNumber to converts from/to Servo to/from Gecko.
+macro_rules! impl_rect_conversions {
+    ($data_type: ident) => {
+        impl ::values::generics::rect::Rect<$data_type> {
+            pub fn to_gecko_rect(&self, sides: &mut ::gecko_bindings::structs::nsStyleSides) {
+                use gecko::values::GeckoStyleCoordConvertible;
+
+                self.0.to_gecko_style_coord(&mut sides.data_at_mut(0));
+                self.1.to_gecko_style_coord(&mut sides.data_at_mut(1));
+                self.2.to_gecko_style_coord(&mut sides.data_at_mut(2));
+                self.3.to_gecko_style_coord(&mut sides.data_at_mut(3));
+            }
+
+            pub fn from_gecko_rect(sides: &::gecko_bindings::structs::nsStyleSides)
+                                   -> Option<::values::generics::rect::Rect<$data_type>> {
+                use gecko::values::GeckoStyleCoordConvertible;
+
+                Some(
+                    ::values::generics::rect::Rect::new(
+                        $data_type::from_gecko_style_coord(&sides.data_at(0)).expect("coord[${0}] has valid data"),
+                        $data_type::from_gecko_style_coord(&sides.data_at(1)).expect("coord[${1}] has valid data"),
+                        $data_type::from_gecko_style_coord(&sides.data_at(2)).expect("coord[${2}] has valid data"),
+                        $data_type::from_gecko_style_coord(&sides.data_at(3)).expect("coord[${3}] has valid data")
+                    )
+                )
+            }
+        }
+    }
+}
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -84,16 +84,17 @@ extern crate style_derive;
 extern crate style_traits;
 extern crate time;
 extern crate unicode_bidi;
 #[allow(unused_extern_crates)]
 extern crate unicode_segmentation;
 
 #[macro_use]
 mod macros;
+#[cfg(feature = "gecko")] #[macro_use] mod gecko_macros;
 
 pub mod animation;
 pub mod applicable_declarations;
 #[allow(missing_docs)] // TODO.
 #[cfg(feature = "servo")] pub mod attr;
 pub mod bezier;
 pub mod bloom;
 pub mod cache;
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -573,16 +573,45 @@ def set_gecko_property(ffi_name, expr):
         pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
             use properties::longhands::${ident}::computed_value::T;
             T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name})
                 .expect("clone for ${ident} failed")
         }
     % endif
 </%def>
 
+<%def name="impl_style_sides(ident)">
+    <% gecko_ffi_name = "m" + to_camel_case(ident) %>
+
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+        v.to_gecko_rect(&mut self.gecko.${gecko_ffi_name});
+    }
+
+    <%self:copy_sides_style_coord ident="${ident}"></%self:copy_sides_style_coord>
+
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+        longhands::${ident}::computed_value::T::from_gecko_rect(&self.gecko.${gecko_ffi_name})
+            .expect("clone for ${ident} failed")
+    }
+</%def>
+
+<%def name="copy_sides_style_coord(ident)">
+    <% gecko_ffi_name = "m" + to_camel_case(ident) %>
+    #[allow(non_snake_case)]
+    pub fn copy_${ident}_from(&mut self, other: &Self) {
+        % for side in SIDES:
+            self.gecko.${gecko_ffi_name}.data_at_mut(${side.index})
+                .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${side.index}));
+        % endfor
+        ${ caller.body() }
+    }
+</%def>
+
 <%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index, need_clone)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         v.0.width.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}));
         v.0.height.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
     }
     #[allow(non_snake_case)]
     pub fn copy_${ident}_from(&mut self, other: &Self) {
@@ -1011,28 +1040,17 @@ fn static_assert() {
 
     pub fn copy_border_image_source_from(&mut self, other: &Self) {
         unsafe {
             Gecko_CopyImageValueFrom(&mut self.gecko.mBorderImageSource,
                                      &other.gecko.mBorderImageSource);
         }
     }
 
-    pub fn set_border_image_outset(&mut self, v: longhands::border_image_outset::computed_value::T) {
-        % for side in SIDES:
-        v.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageOutset.data_at_mut(${side.index}));
-        % endfor
-    }
-
-    pub fn copy_border_image_outset_from(&mut self, other: &Self) {
-        % for side in SIDES:
-            self.gecko.mBorderImageOutset.data_at_mut(${side.index})
-                .copy_from(&other.gecko.mBorderImageOutset.data_at(${side.index}));
-        % endfor
-    }
+    <% impl_style_sides("border_image_outset") %>
 
     <%
     border_image_repeat_keywords = ["Stretch", "Repeat", "Round", "Space"]
     %>
 
     pub fn set_border_image_repeat(&mut self, v: longhands::border_image_repeat::computed_value::T) {
         use properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
         use gecko_bindings::structs;
@@ -1063,62 +1081,46 @@ fn static_assert() {
             structs::NS_STYLE_BORDER_IMAGE_REPEAT_${keyword.upper()} => RepeatKeyword::${keyword},
             % endfor
             x => panic!("Found unexpected value in mBorderImageRepeat${side}: {:?}", x),
         };
         % endfor
         longhands::border_image_repeat::computed_value::T(servo_h, servo_v)
     }
 
-    pub fn set_border_image_width(&mut self, v: longhands::border_image_width::computed_value::T) {
-        use values::generics::border::BorderImageSideWidth;
-
-        % for side in SIDES:
-        match v.${side.index} {
-            BorderImageSideWidth::Auto => {
-                self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Auto)
-            },
-            BorderImageSideWidth::Length(l) => {
-                l.to_gecko_style_coord(&mut self.gecko.mBorderImageWidth.data_at_mut(${side.index}))
-            },
-            BorderImageSideWidth::Number(n) => {
-                self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Factor(n))
-            },
-        }
-        % endfor
-    }
-
-    pub fn copy_border_image_width_from(&mut self, other: &Self) {
-        % for side in SIDES:
-            self.gecko.mBorderImageWidth.data_at_mut(${side.index})
-                .copy_from(&other.gecko.mBorderImageWidth.data_at(${side.index}));
-        % endfor
-    }
+    <% impl_style_sides("border_image_width") %>
 
     pub fn set_border_image_slice(&mut self, v: longhands::border_image_slice::computed_value::T) {
         use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, NS_STYLE_BORDER_IMAGE_SLICE_FILL};
 
-        % for side in SIDES:
-        v.offsets.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageSlice.data_at_mut(${side.index}));
-        % endfor
+        v.offsets.to_gecko_rect(&mut self.gecko.mBorderImageSlice);
 
         let fill = if v.fill {
             NS_STYLE_BORDER_IMAGE_SLICE_FILL
         } else {
             NS_STYLE_BORDER_IMAGE_SLICE_NOFILL
         };
         self.gecko.mBorderImageFill = fill as u8;
     }
 
-    pub fn copy_border_image_slice_from(&mut self, other: &Self) {
-        for i in 0..4 {
-            self.gecko.mBorderImageSlice.data_at_mut(i)
-                .copy_from(&other.gecko.mBorderImageSlice.data_at(i));
+    <%self:copy_sides_style_coord ident="border_image_slice">
+        self.gecko.mBorderImageFill = other.gecko.mBorderImageFill;
+    </%self:copy_sides_style_coord>
+
+    pub fn clone_border_image_slice(&self) -> longhands::border_image_slice::computed_value::T {
+        use gecko_bindings::structs::NS_STYLE_BORDER_IMAGE_SLICE_FILL;
+        use values::computed::{BorderImageSlice, NumberOrPercentage};
+        type NumberOrPercentageRect = ::values::generics::rect::Rect<NumberOrPercentage>;
+
+        BorderImageSlice {
+            offsets:
+                NumberOrPercentageRect::from_gecko_rect(&self.gecko.mBorderImageSlice)
+                    .expect("mBorderImageSlice[${side.index}] has valid data"),
+            fill: self.gecko.mBorderImageFill as u32 == NS_STYLE_BORDER_IMAGE_SLICE_FILL
         }
-        self.gecko.mBorderImageFill = other.gecko.mBorderImageFill;
     }
 </%self:impl_trait>
 
 <% skip_margin_longhands = " ".join(["margin-%s" % x.ident for x in SIDES]) %>
 <%self:impl_trait style_struct_name="Margin"
                   skip_longhands="${skip_margin_longhands}">
 
     % for side in SIDES:
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -204,17 +204,17 @@
     has_uncacheable_values=False,
     boxed="True")}
 
 ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
     parse_method="parse_non_negative",
     initial_value="computed::LengthOrNumber::zero().into()",
     initial_specified_value="specified::LengthOrNumber::zero().into()",
     spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
-    animation_value_type="none",
+    animation_value_type="discrete",
     boxed=True)}
 
 <%helpers:longhand name="border-image-repeat" animation_value_type="discrete"
                    spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
     use style_traits::ToCss;
 
     no_viewport_percentage!(SpecifiedValue);
 
@@ -268,17 +268,74 @@
         Ok(SpecifiedValue(first, second))
     }
 </%helpers:longhand>
 
 ${helpers.predefined_type("border-image-width", "BorderImageWidth",
     initial_value="computed::BorderImageSideWidth::one().into()",
     initial_specified_value="specified::BorderImageSideWidth::one().into()",
     spec="https://drafts.csswg.org/css-backgrounds/#border-image-width",
-    animation_value_type="none",
+    animation_value_type="discrete",
     boxed=True)}
 
 ${helpers.predefined_type("border-image-slice", "BorderImageSlice",
     initial_value="computed::NumberOrPercentage::Percentage(computed::Percentage(1.)).into()",
     initial_specified_value="specified::NumberOrPercentage::Percentage(specified::Percentage(1.)).into()",
     spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice",
-    animation_value_type="none",
+    animation_value_type="discrete",
     boxed=True)}
+
+#[cfg(feature = "gecko")] use values::computed::{LengthOrNumber, NumberOrPercentage};
+#[cfg(feature = "gecko")] impl_rect_conversions!(LengthOrNumber);
+#[cfg(feature = "gecko")] impl_rect_conversions!(NumberOrPercentage);
+
+#[cfg(feature = "gecko")]
+impl ::values::computed::BorderImageWidth {
+    pub fn to_gecko_rect(&self, sides: &mut ::gecko_bindings::structs::nsStyleSides) {
+        use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
+        use gecko::values::GeckoStyleCoordConvertible;
+        use values::generics::border::BorderImageSideWidth;
+
+        % for i in range(0, 4):
+        match self.${i} {
+            BorderImageSideWidth::Auto => {
+                sides.data_at_mut(${i}).set_value(CoordDataValue::Auto)
+            },
+            BorderImageSideWidth::Length(l) => {
+                l.to_gecko_style_coord(&mut sides.data_at_mut(${i}))
+            },
+            BorderImageSideWidth::Number(n) => {
+                sides.data_at_mut(${i}).set_value(CoordDataValue::Factor(n))
+            },
+        }
+        % endfor
+    }
+
+    pub fn from_gecko_rect(sides: &::gecko_bindings::structs::nsStyleSides) -> Option<::values::computed::BorderImageWidth> {
+        use gecko_bindings::structs::nsStyleUnit::{eStyleUnit_Factor, eStyleUnit_Auto};
+        use gecko_bindings::sugar::ns_style_coord::CoordData;
+        use gecko::values::GeckoStyleCoordConvertible;
+        use values::computed::{LengthOrPercentage, Number};
+        use values::generics::border::BorderImageSideWidth;
+
+        Some(
+            ::values::computed::BorderImageWidth::new(
+                % for i in range(0, 4):
+                match sides.data_at(${i}).unit() {
+                    eStyleUnit_Auto => {
+                        BorderImageSideWidth::Auto
+                    },
+                    eStyleUnit_Factor => {
+                        BorderImageSideWidth::Number(
+                            Number::from_gecko_style_coord(&sides.data_at(${i}))
+                                .expect("sides[${i}] has valid data"))
+                    },
+                    _ => {
+                        BorderImageSideWidth::Length(
+                            LengthOrPercentage::from_gecko_style_coord(&sides.data_at(${i}))
+                                .expect("sides[${i}] has valid data"))
+                    },
+                },
+                % endfor
+            )
+        )
+    }
+}