Bug 1335942 - Part 4: Support transform in SetAnimatable. draft
authorBoris Chiou <boris.chiou@gmail.com>
Sun, 05 Feb 2017 19:23:18 +0800
changeset 479847 7eb6697f2d0443373a519200562e489ce676d152
parent 479846 517f76fa934dce99fcc251bd27d2bf4340f44ae1
child 479848 7b9ab4e8fcd766b0d4af91793bf24e1e2c3d36db
push id44386
push userbmo:boris.chiou@gmail.com
push dateTue, 07 Feb 2017 12:37:56 +0000
bugs1335942
milestone54.0a1
Bug 1335942 - Part 4: Support transform in SetAnimatable. MozReview-Commit-ID: 97aTuUNa1RT
layout/painting/nsDisplayList.cpp
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
servo/components/style/build_gecko.rs
servo/components/style/gecko_bindings/bindings.rs
servo/components/style/properties/gecko.mako.rs
servo/ports/geckolib/glue.rs
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -121,17 +121,17 @@ AnimatedGeometryRoot::operator new(size_
 }
 
 static inline CSSAngle
 MakeCSSAngle(const nsCSSValue& aValue)
 {
   return CSSAngle(aValue.GetAngleValue(), aValue.GetUnit());
 }
 
-static void AddTransformFunctions(nsCSSValueList* aList,
+static void AddTransformFunctions(const nsCSSValueList* aList,
                                   nsStyleContext* aContext,
                                   nsPresContext* aPresContext,
                                   TransformReferenceBox& aRefBox,
                                   InfallibleTArray<TransformFunction>& aFunctions)
 {
   if (aList->mValue.GetUnit() == eCSSUnit_None) {
     return;
   }
@@ -363,16 +363,30 @@ static void AddTransformFunctions(nsCSSV
         break;
       }
       default:
         NS_ERROR("Function not handled yet!");
     }
   }
 }
 
+static void
+AddTransformFunctions(const nsCSSValueSharedList* aList,
+                      const nsIFrame* aFrame,
+                      layers::Animatable& aAnimatable)
+{
+  MOZ_ASSERT(aList->mHead);
+  TransformReferenceBox refBox(aFrame);
+  AddTransformFunctions(aList->mHead,
+                        aFrame->StyleContext(),
+                        aFrame->PresContext(),
+                        refBox,
+                        aAnimatable.get_ArrayOfTransformFunction());
+}
+
 static TimingFunction
 ToTimingFunction(const Maybe<ComputedTimingFunction>& aCTF)
 {
   if (aCTF.isNothing()) {
     return TimingFunction(null_t());
   }
 
   if (aCTF->HasSpline()) {
@@ -400,26 +414,25 @@ SetAnimatable(nsCSSPropertyID aProperty,
   }
 
   switch (aProperty) {
     case eCSSProperty_opacity:
       aAnimatable = aAnimationValue.GetOpacity();
       break;
     case eCSSProperty_transform: {
       aAnimatable = InfallibleTArray<TransformFunction>();
-      TransformReferenceBox refBox(aFrame);
-      // TODO: Get transform from RawServoAnimationValue.
-      nsCSSValueSharedList* list =
-        aAnimationValue.mGecko.GetCSSValueSharedListValue();
-      MOZ_ASSERT(list, "Invalid transform list");
-      AddTransformFunctions(list->mHead,
-                            aFrame->StyleContext(),
-                            aFrame->PresContext(),
-                            refBox,
-                            aAnimatable.get_ArrayOfTransformFunction());
+      if (aAnimationValue.mServo) {
+        RefPtr<nsCSSValueSharedList> list;
+        Servo_AnimationValues_GetTransform(aAnimationValue.mServo, &list);
+        AddTransformFunctions(list, aFrame, aAnimatable);
+      } else {
+        nsCSSValueSharedList* list =
+          aAnimationValue.mGecko.GetCSSValueSharedListValue();
+        AddTransformFunctions(list, aFrame, aAnimatable);
+      }
       break;
     }
     default:
       MOZ_ASSERT_UNREACHABLE("Unsupported property");
   }
 }
 
 static void
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -124,16 +124,19 @@ SERVO_BINDING_FUNC(Servo_AnimationValues
                    RawServoAnimationValueBorrowed from,
                    RawServoAnimationValueBorrowed to,
                    double progress)
 SERVO_BINDING_FUNC(Servo_AnimationValues_Uncompute,
                    RawServoDeclarationBlockStrong,
                    RawServoAnimationValueBorrowedListBorrowed value)
 SERVO_BINDING_FUNC(Servo_AnimationValues_GetOpacity, float,
                    RawServoAnimationValueBorrowed value)
+SERVO_BINDING_FUNC(Servo_AnimationValues_GetTransform, void,
+                   RawServoAnimationValueBorrowed value,
+                   RefPtr<nsCSSValueSharedList>* list)
 
 // Style attribute
 SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
                    const nsACString* data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,
                    RawServoDeclarationBlockStrong)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Clone, RawServoDeclarationBlockStrong,
                    RawServoDeclarationBlockBorrowed declarations)
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -28,16 +28,17 @@ class StyleChildrenIterator;
 struct Keyframe;
 struct PropertyStyleAnimationValuePair;
 } // namespace mozilla
 
 class nsCSSValue;
 class nsIDocument;
 class nsINode;
 class nsPresContext;
+struct nsCSSValueSharedList;
 
 using mozilla::dom::StyleChildrenIterator;
 using mozilla::ServoElementSnapshot;
 
 typedef nsINode RawGeckoNode;
 typedef mozilla::dom::Element RawGeckoElement;
 typedef nsIDocument RawGeckoDocument;
 typedef nsPresContext RawGeckoPresContext;
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -494,16 +494,17 @@ mod bindings {
             "RawGeckoElement",
             "RawGeckoKeyframeList",
             "RawGeckoNode",
             "RawGeckoAnimationValueList",
             "RawServoAnimationValue",
             "RawServoDeclarationBlock",
             "RawGeckoPresContext",
             "RawGeckoPresContextOwned",
+            "RefPtr",
             "ThreadSafeURIHolder",
             "ThreadSafePrincipalHolder",
             "CSSPseudoClassType",
             "TraversalRootBehavior",
             "FontFamilyList",
             "FontFamilyType",
             "Keyframe",
             "ServoElementSnapshot",
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -151,16 +151,17 @@ unsafe impl Send for nsStyleXUL {}
 unsafe impl Sync for nsStyleXUL {}
 use gecko_bindings::structs::nsTimingFunction;
 use gecko_bindings::structs::nscoord;
 use gecko_bindings::structs::nsresult;
 use gecko_bindings::structs::Loader;
 use gecko_bindings::structs::ServoStyleSheet;
 use gecko_bindings::structs::EffectCompositor_CascadeLevel;
 use gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
+use gecko_bindings::structs::RefPtr;
 pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray<usize>;
 pub type ServoComputedValuesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoComputedValues>;
 pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;
 pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;
 enum ServoComputedValuesVoid { }
 pub struct ServoComputedValues(ServoComputedValuesVoid);
 pub type ServoCssRulesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoCssRules>;
 pub type ServoCssRulesBorrowed<'a> = &'a ServoCssRules;
@@ -1299,16 +1300,20 @@ extern "C" {
      -> RawServoDeclarationBlockStrong;
 }
 extern "C" {
     pub fn Servo_AnimationValues_GetOpacity(value:
                                                 RawServoAnimationValueBorrowed)
      -> f32;
 }
 extern "C" {
+    pub fn Servo_AnimationValues_GetTransform(value: RawServoAnimationValueBorrowed,
+                                              list: *mut RefPtr<nsCSSValueSharedList>);
+}
+extern "C" {
     pub fn Servo_ParseStyleAttribute(data: *const nsACString_internal)
      -> RawServoDeclarationBlockStrong;
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_CreateEmpty()
      -> RawServoDeclarationBlockStrong;
 }
 extern "C" {
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1317,51 +1317,44 @@ fn static_assert() {
             css_value_setters = {
                 "length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)",
                 "percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s)",
                 "lop" : "%s.set_lop(%s)",
                 "angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.0)",
                 "number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
             }
         %>
-        ComputedOperation::${name.title()}(${pattern}) => {
+        longhands::transform::computed_value::ComputedOperation::${name.title()}(${pattern}) => {
             bindings::Gecko_CSSValue_SetFunction(gecko_value, ${len(items) + 1});
             bindings::Gecko_CSSValue_SetKeyword(
                 bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
                 eCSSKeyword_${keyword}
             );
             % for index, item in enumerate(items):
                 ${css_value_setters[item] % (
                     "bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1),
                     item + str(index + 1)
                 )};
             % endfor
         }
     </%def>
-    pub fn set_transform(&mut self, other: longhands::transform::computed_value::T) {
+    pub fn convert_transform(input: Vec<longhands::transform::computed_value::ComputedOperation>,
+                             output: &mut structs::root::RefPtr<structs::root::nsCSSValueSharedList>) {
         use gecko_bindings::structs::nsCSSKeyword::*;
         use gecko_bindings::sugar::refptr::RefPtr;
         use properties::longhands::transform::computed_value::ComputedMatrix;
-        use properties::longhands::transform::computed_value::ComputedOperation;
 
-        let vec = if let Some(v) = other.0 {
-            v
-        } else {
-            unsafe {
-                self.gecko.mSpecifiedTransform.clear();
-            }
-            return;
-        };
+        unsafe { output.clear() };
 
         let list = unsafe {
-            RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(vec.len() as u32))
+            RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(input.len() as u32))
         };
 
         let mut cur = list.mHead;
-        let mut iter = vec.into_iter();
+        let mut iter = input.into_iter();
         while !cur.is_null() {
             let gecko_value = unsafe { &mut (*cur).mValue };
             let servo = iter.next().expect("Gecko_NewCSSValueSharedList should create a shared \
                                             value list of the same length as the transform vector");
             unsafe {
                 match servo {
                     ${transform_function_arm("matrix", "matrix3d", ["number"] * 16)}
                     ${transform_function_arm("skew", "skew", ["angle"] * 2)}
@@ -1369,17 +1362,29 @@ fn static_assert() {
                     ${transform_function_arm("scale", "scale3d", ["number"] * 3)}
                     ${transform_function_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])}
                     ${transform_function_arm("perspective", "perspective", ["length"])}
                 }
                 cur = (*cur).mNext;
             }
         }
         debug_assert!(iter.next().is_none());
-        unsafe { self.gecko.mSpecifiedTransform.set_move(list) };
+        unsafe { output.set_move(list) };
+    }
+
+    pub fn set_transform(&mut self, other: longhands::transform::computed_value::T) {
+        let vec = if let Some(v) = other.0 {
+            v
+        } else {
+            unsafe {
+                self.gecko.mSpecifiedTransform.clear();
+            }
+            return;
+        };
+        Self::convert_transform(vec, &mut self.gecko.mSpecifiedTransform);
     }
 
     pub fn copy_transform_from(&mut self, other: &Self) {
         unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); }
     }
 
     <%def name="computed_operation_arm(name, keyword, items)">
         <%
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -48,21 +48,23 @@ use style::gecko_bindings::bindings::nsT
 use style::gecko_bindings::structs;
 use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
 use style::gecko_bindings::structs::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
 use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
 use style::gecko_bindings::structs::Loader;
 use style::gecko_bindings::structs::RawGeckoPresContextOwned;
 use style::gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
 use style::gecko_bindings::structs::ServoStyleSheet;
+use style::gecko_bindings::structs::nsCSSValueSharedList;
 use style::gecko_bindings::structs::nsTimingFunction;
 use style::gecko_bindings::structs::nsresult;
 use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
 use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
 use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
+use style::gecko_properties::style_structs;
 use style::keyframes::KeyframesStepValue;
 use style::parallel;
 use style::parser::{ParserContext, ParserContextExtraData};
 use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
 use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock, PropertyId};
 use style::properties::{apply_declarations, parse_one_declaration};
 use style::properties::animated_properties::{AnimationValue, Interpolate, TransitionProperty};
 use style::restyle_hints::RestyleHint;
@@ -212,16 +214,28 @@ pub extern "C" fn Servo_AnimationValues_
     let value = AnimationValue::as_arc(&value);
     if let AnimationValue::Opacity(opacity) = **value {
         opacity
     } else {
         panic!("The AnimationValue should be Opacity");
     }
 }
 
+#[no_mangle]
+pub extern "C" fn Servo_AnimationValues_GetTransform(value: RawServoAnimationValueBorrowed,
+                                                     list: &mut structs::RefPtr<nsCSSValueSharedList>)
+{
+    let value = AnimationValue::as_arc(&value);
+    if let AnimationValue::Transform(ref servo_list) = **value {
+        style_structs::Box::convert_transform(servo_list.0.clone().unwrap(), list);
+    } else {
+        panic!("The AnimationValue should be transform");
+    }
+}
+
 /// Takes a ServoAnimationValues and populates it with the animation values corresponding
 /// to a given property declaration block
 #[no_mangle]
 pub extern "C" fn Servo_AnimationValues_Populate(anim: RawGeckoAnimationValueListBorrowedMut,
                                                  declarations: RawServoDeclarationBlockBorrowed,
                                                  style: ServoComputedValuesBorrowed,
                                                  parent_style: ServoComputedValuesBorrowedOrNull,
                                                  pres_context: RawGeckoPresContextBorrowed)