Bug 1353966 - Part 3: Implement discrete type animation for border related properties. r?hiro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Fri, 19 May 2017 11:10:19 +0900
changeset 580993 acdd9e318be8eefe46bdde3448a4f29a1e30bec6
parent 580992 6599c57ca8d89601c0685c0a50267c3e080395c9
child 580994 60d77a71ef5b2fd8f0542d08a360c7bfa137dec7
push id59742
push userbmo:dakatsuka@mozilla.com
push dateFri, 19 May 2017 06:56:54 +0000
reviewershiro
bugs1353966
milestone55.0a1
Bug 1353966 - Part 3: Implement discrete type animation for border related properties. r?hiro In this patch, implement following border related properties. * border-bottom-style * border-left-style * border-right-style * border-top-style * border-image-outset * border-image-repeat * border-image-slice * border-image-source * border-image-width * box-decoration-break * -moz-float-edge * -moz-border-bottom-colors * -moz-border-left-colors * -moz-border-right-colors * -moz-border-top-colors Also, we prevent to animate the logical properties in this time. MozReview-Commit-ID: 2WiyAJnEbh4
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
servo/components/style/build_gecko.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/border.mako.rs
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1031,16 +1031,30 @@ void
 Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
                           mozilla::Side aSide)
 {
   if (aSrc->mBorderColors) {
     aDest->CopyBorderColorsFrom(aSrc->mBorderColors[aSide], aSide);
   }
 }
 
+bool
+Gecko_HasMozBorderColors(const nsStyleBorder* aBorder, mozilla::Side aSide)
+{
+  MOZ_ASSERT(aBorder);
+  return aBorder->mBorderColors[aSide] != nullptr;
+}
+
+const nsBorderColors*
+Gecko_GetMozBorderColors(const nsStyleBorder* aBorder, mozilla::Side aSide)
+{
+  MOZ_ASSERT(aBorder);
+  return aBorder->mBorderColors[aSide];
+}
+
 void
 Gecko_FontFamilyList_Clear(FontFamilyList* aList) {
   aList->Clear();
 }
 
 void
 Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName, bool aQuoted)
 {
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -245,16 +245,18 @@ bool Gecko_AtomEqualsUTF8IgnoreCase(nsIA
 
 // Border style
 void Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder);
 void Gecko_ClearMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide);
 void Gecko_AppendMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide,
                                  nscolor aColor);
 void Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
                                mozilla::Side aSide);
+bool Gecko_HasMozBorderColors(const nsStyleBorder* aBorder, mozilla::Side aSide);
+const nsBorderColors* Gecko_GetMozBorderColors(const nsStyleBorder* aBorder, mozilla::Side aSide);
 
 // Font style
 void Gecko_FontFamilyList_Clear(FontFamilyList* aList);
 void Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName, bool aQuoted);
 void Gecko_FontFamilyList_AppendGeneric(FontFamilyList* list, FontFamilyType familyType);
 void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src);
 // will not run destructors on dst, give it uninitialized memory
 // font_id is LookAndFeel::FontID
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -696,16 +696,17 @@ mod bindings {
             "ServoBundledURI",
             "ServoElementSnapshot",
             "ServoElementSnapshotTable",
             "SheetParsingMode",
             "StyleBasicShape",
             "StyleBasicShapeType",
             "StyleShapeSource",
             "StyleTransition",
+            "nsBorderColors",
             "nsCSSCounterStyleRule",
             "nsCSSFontFaceRule",
             "nsCSSKeyword",
             "nsCSSPropertyID",
             "nsCSSShadowArray",
             "nsCSSUnit",
             "nsCSSValue",
             "nsCSSValueSharedList",
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -906,16 +906,38 @@ fn static_assert() {
 
     #[allow(non_snake_case)]
     pub fn copy__moz_border_${side.ident}_colors_from(&mut self, other: &Self) {
         unsafe {
             bindings::Gecko_CopyMozBorderColors(&mut self.gecko, &other.gecko,
                                                 structs::Side::eSide${to_camel_case(side.ident)});
         }
     }
+
+    #[allow(non_snake_case)]
+    pub fn clone__moz_border_${side.ident}_colors(&self) -> longhands::_moz_border_${side.ident}_colors::computed_value::T {
+        unsafe {
+            longhands::_moz_border_${side.ident}_colors::computed_value::T(
+                match bindings::Gecko_HasMozBorderColors(&self.gecko,
+                                                         structs::Side::eSide${to_camel_case(side.ident)}) {
+                    false => None,
+                    true => {
+                        let gecko_colors =
+                            bindings::Gecko_GetMozBorderColors(&self.gecko, structs::Side::eSide${to_camel_case(side.ident)});
+                        let mut colors = Vec::new();
+                        loop {
+                            colors.push(Color::RGBA(convert_nscolor_to_rgba((*gecko_colors).mColor)));
+                            if (*gecko_colors).mNext.is_null() { break; }
+                        }
+                        Some(colors)
+                    }
+                }
+            )
+        }
+    }
     % endfor
 
     % for corner in CORNERS:
     <% impl_corner_style_coord("border_%s_radius" % corner.ident,
                                "mBorderRadius",
                                corner.x_index,
                                corner.y_index,
                                need_clone=True) %>
@@ -934,30 +956,50 @@ 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 clone_border_image_source(&self) -> longhands::border_image_source::computed_value::T {
+        use values::computed::Image;
+        use values::None_;
+
+        match Image::from_gecko_style_image(&self.gecko.mBorderImageSource) {
+            Some(image) => Either::Second(image),
+            None => Either::First(None_),
+        }
+    }
+
     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
     }
 
+    pub fn clone_border_image_outset(&self) -> longhands::border_image_outset::computed_value::T {
+        use values::computed::LengthOrNumber;
+
+        longhands::border_image_outset::computed_value::T(
+            % for side in SIDES:
+            LengthOrNumber::from_gecko_style_coord(&self.gecko.mBorderImageOutset.data_at(${side.index})).unwrap(),
+            % endfor
+        )
+    }
+
     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::{NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, NS_STYLE_BORDER_IMAGE_REPEAT_REPEAT};
         use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_REPEAT_ROUND, NS_STYLE_BORDER_IMAGE_REPEAT_SPACE};
 
         % for i, side in enumerate(["H", "V"]):
             let k = match v.${i} {
                 RepeatKeyword::Stretch => NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH,
@@ -970,16 +1012,35 @@ fn static_assert() {
         % endfor
     }
 
     pub fn copy_border_image_repeat_from(&mut self, other: &Self) {
         self.gecko.mBorderImageRepeatH = other.gecko.mBorderImageRepeatH;
         self.gecko.mBorderImageRepeatV = other.gecko.mBorderImageRepeatV;
     }
 
+    pub fn clone_border_image_repeat(&self) -> longhands::border_image_repeat::computed_value::T {
+        use properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
+        use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, NS_STYLE_BORDER_IMAGE_REPEAT_REPEAT};
+        use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_REPEAT_ROUND, NS_STYLE_BORDER_IMAGE_REPEAT_SPACE};
+
+        longhands::border_image_repeat::computed_value::T(
+            % for side in ["H", "V"]:
+            match self.gecko.mBorderImageRepeat${side} as u32 {
+                NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH => RepeatKeyword::Stretch,
+                NS_STYLE_BORDER_IMAGE_REPEAT_REPEAT => RepeatKeyword::Repeat,
+                NS_STYLE_BORDER_IMAGE_REPEAT_ROUND => RepeatKeyword::Round,
+                NS_STYLE_BORDER_IMAGE_REPEAT_SPACE => RepeatKeyword::Space,
+                x => panic!("Found unexpected value for mBorderImageRepeat$: {:?}", x),
+            }
+            ,
+            % endfor
+        )
+    }
+
     pub fn set_border_image_width(&mut self, v: longhands::border_image_width::computed_value::T) {
         use properties::longhands::border_image_width::computed_value::SingleComputedValue;
 
         % for side in SIDES:
         match v.${side.index} {
             SingleComputedValue::Auto => {
                 self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Auto)
             },
@@ -995,16 +1056,40 @@ fn static_assert() {
 
     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
     }
 
+    pub fn clone_border_image_width(&self) -> longhands::border_image_width::computed_value::T {
+        use values::computed::{LengthOrPercentage, Number};
+        use properties::longhands::border_image_width::computed_value::SingleComputedValue;
+        use gecko_bindings::structs::nsStyleUnit::{eStyleUnit_Factor, eStyleUnit_Auto};
+
+        longhands::border_image_width::computed_value::T(
+            % for side in SIDES:
+            match self.gecko.mBorderImageWidth.data_at(${side.index}).unit() {
+                eStyleUnit_Auto => {
+                    SingleComputedValue::Auto
+                },
+                eStyleUnit_Factor => {
+                    SingleComputedValue::Number(
+                        Number::from_gecko_style_coord(&self.gecko.mBorderImageWidth.data_at(${side.index})).unwrap())
+                },
+                _ => {
+                    SingleComputedValue::LengthOrPercentage(
+                        LengthOrPercentage::from_gecko_style_coord(&self.gecko.mBorderImageWidth.data_at(${side.index})).unwrap())
+                },
+            },
+            % endfor
+        )
+    }
+
     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 (i, corner) in v.corners.iter().enumerate() {
             corner.to_gecko_style_coord(&mut self.gecko.mBorderImageSlice.data_at_mut(i));
         }
 
         let fill = if v.fill {
@@ -1017,16 +1102,34 @@ fn static_assert() {
 
     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.gecko.mBorderImageFill = other.gecko.mBorderImageFill;
     }
+
+    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::NumberOrPercentage;
+
+        longhands::border_image_slice::computed_value::T {
+            corners:[
+                NumberOrPercentage::from_gecko_style_coord(&self.gecko.mBorderImageSlice.data_at(0)).unwrap(),
+                NumberOrPercentage::from_gecko_style_coord(&self.gecko.mBorderImageSlice.data_at(1)).unwrap(),
+                NumberOrPercentage::from_gecko_style_coord(&self.gecko.mBorderImageSlice.data_at(2)).unwrap(),
+                NumberOrPercentage::from_gecko_style_coord(&self.gecko.mBorderImageSlice.data_at(3)).unwrap(),
+            ],
+            fill: match self.gecko.mBorderImageFill as u32 {
+                NS_STYLE_BORDER_IMAGE_SLICE_FILL => true,
+                _ => false
+            }
+        }
+    }
 </%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:
     <% impl_split_style_coord("margin_%s" % side.ident,
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -143,17 +143,17 @@ impl TransitionProperty {
         }
     }
 
     /// Returns true if this TransitionProperty is one of the discrete animatable properties and
     /// this TransitionProperty should be a longhand property.
     pub fn is_discrete(&self) -> bool {
         match *self {
             % for prop in data.longhands:
-                % if prop.animation_value_type == "discrete":
+                % if prop.animation_value_type == "discrete" and not prop.logical:
                     TransitionProperty::${prop.camel_case} => true,
                 % endif
             % endfor
             _ => false
         }
     }
 
     /// Return animatable longhands of this shorthand TransitionProperty, except for "all".
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -24,17 +24,17 @@
                               logical=side[1],
                               allow_quirks=not side[1])}
 
     ${helpers.predefined_type("border-%s-style" % side[0], "BorderStyle",
                               "specified::BorderStyle::none",
                               need_clone=True,
                               alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
                               spec=maybe_logical_spec(side, "style"),
-                              animation_value_type="none", logical=side[1])}
+                              animation_value_type="discrete", logical=side[1])}
 
     ${helpers.predefined_type("border-%s-width" % side[0], "BorderWidth", "Au::from_px(3)",
                               computed_type="::app_units::Au",
                               alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-width"),
                               spec=maybe_logical_spec(side, "width"),
                               animation_value_type="ComputedValue",
                               logical=side[1],
                               allow_quirks=not side[1])}
@@ -52,17 +52,17 @@
                               spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner,
                               boxed=True,
                               animation_value_type="ComputedValue")}
 % endfor
 
 /// -moz-border-*-colors: color, string, enum, none, inherit/initial
 /// These non-spec properties are just for Gecko (Stylo) internal use.
 % for side in PHYSICAL_SIDES:
-    <%helpers:longhand name="-moz-border-${side}-colors" animation_value_type="none"
+    <%helpers:longhand name="-moz-border-${side}-colors" animation_value_type="discrete"
                        spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-*-colors)"
                        products="gecko">
         use std::fmt;
         use style_traits::ToCss;
         use values::HasViewportPercentage;
         use values::specified::CSSColor;
         no_viewport_percentage!(SpecifiedValue);
 
@@ -175,38 +175,36 @@
                 Err(())
             }
         }
     </%helpers:longhand>
 % endfor
 
 ${helpers.single_keyword("box-decoration-break", "slice clone",
                          gecko_enum_prefix="StyleBoxDecorationBreak",
-                         gecko_inexhaustive=True,
                          spec="https://drafts.csswg.org/css-break/#propdef-box-decoration-break",
-                         products="gecko", animation_value_type="none")}
+                         products="gecko", animation_value_type="discrete")}
 
 ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
                          gecko_ffi_name="mFloatEdge",
                          gecko_enum_prefix="StyleFloatEdge",
-                         gecko_inexhaustive=True,
                          products="gecko",
                          spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-float-edge)",
-                         animation_value_type="none")}
+                         animation_value_type="discrete")}
 
 ${helpers.predefined_type("border-image-source", "ImageLayer",
     initial_value="Either::First(None_)",
     initial_specified_value="Either::First(None_)",
     spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
     vector=False,
-    animation_value_type="none",
+    animation_value_type="discrete",
     has_uncacheable_values=False,
     boxed="True")}
 
-<%helpers:longhand name="border-image-outset" animation_value_type="none"
+<%helpers:longhand name="border-image-outset" animation_value_type="discrete"
                    spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::{LengthOrNumber, Number};
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
@@ -312,17 +310,17 @@
         if values.len() > 0 {
             Ok(SpecifiedValue(values))
         } else {
             Err(())
         }
     }
 </%helpers:longhand>
 
-<%helpers:longhand name="border-image-repeat" animation_value_type="none"
+<%helpers:longhand name="border-image-repeat" animation_value_type="discrete"
                    spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
 
     no_viewport_percentage!(SpecifiedValue);
 
     pub mod computed_value {
@@ -390,17 +388,17 @@
     pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         let first = try!(RepeatKeyword::parse(input));
         let second = input.try(RepeatKeyword::parse).ok();
 
         Ok(SpecifiedValue(first, second))
     }
 </%helpers:longhand>
 
-<%helpers:longhand name="border-image-width" animation_value_type="none"
+<%helpers:longhand name="border-image-width" animation_value_type="discrete"
                    spec="https://drafts.csswg.org/css-backgrounds/#border-image-width">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::specified::{LengthOrPercentage, Number};
 
     impl HasViewportPercentage for SpecifiedValue {
         fn has_viewport_percentage(&self) -> bool {
@@ -590,17 +588,17 @@
         if values.len() > 0 {
             Ok(SpecifiedValue(values))
         } else {
             Err(())
         }
     }
 </%helpers:longhand>
 
-<%helpers:longhand name="border-image-slice" boxed="True" animation_value_type="none"
+<%helpers:longhand name="border-image-slice" boxed="True" animation_value_type="discrete"
                    spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice">
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
     use values::computed::NumberOrPercentage as ComputedNumberOrPercentage;
     use values::specified::{NumberOrPercentage, Percentage};
 
     no_viewport_percentage!(SpecifiedValue);