Bug 1371115 - Part 3: implements nsStyleSides type properties animatable. r?hiro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 04 Jul 2017 17:20:10 +0900
changeset 603544 aaf34cc1a18b173838c0ba91026500d997bba77e
parent 603543 37f879afca2f6ad391d5e070b0426a7f1de6d5dc
child 603545 22e806ab50a9f2978837969330a12b146735f2e1
push id66823
push userbmo:dakatsuka@mozilla.com
push dateTue, 04 Jul 2017 08:33:34 +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/conversions.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/border.mako.rs
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -15,16 +15,17 @@ use gecko_bindings::bindings::{Gecko_Ini
 use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage};
 use gecko_bindings::structs::{nsresult, SheetType};
 use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
 use stylesheets::{Origin, RulesMutateError};
 use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
 use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
 use values::generics::grid::TrackSize;
 use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
+use values::generics::rect::Rect;
 use values::specified::length::Percentage;
 
 impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
     fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
         let has_percentage = other.percentage.is_some();
         nsStyleCoord_CalcValue {
             mLength: other.unclamped_length().0,
             mPercent: other.percentage.map_or(0., |p| p.0),
@@ -630,8 +631,33 @@ impl TrackSize<LengthOrPercentage> {
             },
             TrackSize::MinMax(ref min, ref max) => {
                 min.to_gecko_style_coord(gecko_min);
                 max.to_gecko_style_coord(gecko_max);
             },
         }
     }
 }
+
+impl<T> Rect<T> where T: GeckoStyleCoordConvertible {
+    /// Convert this generic Rect to given Gecko fields.
+    pub fn to_gecko_rect(&self, sides: &mut ::gecko_bindings::structs::nsStyleSides) {
+        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));
+    }
+
+    /// Convert from given Gecko data to generic Rect.
+    pub fn from_gecko_rect(sides: &::gecko_bindings::structs::nsStyleSides)
+                           -> Option<::values::generics::rect::Rect<T>> {
+        use values::generics::rect::Rect;
+
+        Some(
+            Rect::new(
+                T::from_gecko_style_coord(&sides.data_at(0)).expect("coord[0] cound not convert"),
+                T::from_gecko_style_coord(&sides.data_at(1)).expect("coord[1] cound not convert"),
+                T::from_gecko_style_coord(&sides.data_at(2)).expect("coord[2] cound not convert"),
+                T::from_gecko_style_coord(&sides.data_at(3)).expect("coord[3] cound not convert")
+            )
+        )
+    }
+}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -576,16 +576,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) {
@@ -1014,28 +1043,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;
@@ -1066,62 +1084,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}] could not convert to NumberOrPercentageRect"),
+            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,70 @@
         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")]
+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}] could not convert to Number"))
+                    },
+                    _ => {
+                        BorderImageSideWidth::Length(
+                            LengthOrPercentage::from_gecko_style_coord(&sides.data_at(${i}))
+                                .expect("sides[${i}] could not convert to LengthOrPercentager"))
+                    },
+                },
+                % endfor
+            )
+        )
+    }
+}