Bug 1329878 - Implement animation addition in Servo_AnimationCompose; r?hiro draft
authorBrian Birtles <birtles@gmail.com>
Mon, 15 May 2017 11:01:27 +0900
changeset 577585 ad04b288c0ec8fd8b9fbdf1814fa9d851eda414e
parent 577584 1bd8e35533e41129f10b214f70929d2ab16f7468
child 628532 dfa2d1ec28890239a1acd523647dce62487bdf3a
push id58723
push userbbirtles@mozilla.com
push dateMon, 15 May 2017 02:05:49 +0000
reviewershiro
bugs1329878
milestone55.0a1
Bug 1329878 - Implement animation addition in Servo_AnimationCompose; r?hiro MozReview-Commit-ID: 3E7XPyKf80U
servo/ports/geckolib/glue.rs
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -54,16 +54,17 @@ use style::gecko_bindings::bindings::Raw
 use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
 use style::gecko_bindings::bindings::RawServoImportRuleBorrowed;
 use style::gecko_bindings::bindings::RawServoStyleRuleBorrowed;
 use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
 use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
 use style::gecko_bindings::bindings::nsTimingFunctionBorrowed;
 use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
 use style::gecko_bindings::structs;
+use style::gecko_bindings::structs::CompositeOperation;
 use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet};
 use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
 use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, nsCSSFontFaceRule};
 use style::gecko_bindings::structs::Loader;
 use style::gecko_bindings::structs::RawGeckoPresContextOwned;
 use style::gecko_bindings::structs::ServoElementSnapshotTable;
 use style::gecko_bindings::structs::URLExtraData;
 use style::gecko_bindings::structs::nsCSSValueSharedList;
@@ -320,51 +321,69 @@ pub extern "C" fn Servo_AnimationCompose
     use style::gecko_bindings::bindings::Gecko_AnimationGetBaseStyle;
     use style::gecko_bindings::bindings::Gecko_GetPositionInSegment;
     use style::gecko_bindings::bindings::Gecko_GetProgressFromComputedTiming;
     use style::properties::animated_properties::AnimationValueMap;
 
     let property: TransitionProperty = css_property.into();
     let value_map = AnimationValueMap::from_ffi_mut(raw_value_map);
 
+    let need_underlying_value = segment.mFromValue.mServo.mRawPtr.is_null() ||
+                                segment.mToValue.mServo.mRawPtr.is_null() ||
+                                segment.mFromComposite != CompositeOperation::Replace ||
+                                segment.mToComposite != CompositeOperation::Replace;
+
     // If either of the segment endpoints are null, get the underlying value to
     // use from the current value in the values map (set by a lower-priority
     // effect), or, if there is no current value, look up the cached base value
     // for this property.
-    let underlying_value = if segment.mFromValue.mServo.mRawPtr.is_null() ||
-                              segment.mToValue.mServo.mRawPtr.is_null() {
+    let underlying_value = if need_underlying_value {
         let previous_composed_value = value_map.get(&property).cloned();
         previous_composed_value.or_else(|| {
             let raw_base_style = unsafe { Gecko_AnimationGetBaseStyle(base_values, css_property) };
             AnimationValue::arc_from_borrowed(&raw_base_style).map(|v| v.as_ref()).cloned()
         })
     } else {
         None
     };
 
-    if (segment.mFromValue.mServo.mRawPtr.is_null() ||
-        segment.mToValue.mServo.mRawPtr.is_null()) &&
-        underlying_value.is_none() {
-        warn!("Underlying value should be valid in the case where either 'from' value or 'to' value is null");
+    if need_underlying_value && underlying_value.is_none() {
+        warn!("Underlying value should be valid when we expect to use it");
         return;
     }
 
-    // Declare for making derefenced raw pointer alive outside the if block.
+    // Temporaries used in the following if-block whose lifetimes we need to prlong.
     let raw_from_value;
+    let from_composite_result;
     let from_value = if !segment.mFromValue.mServo.mRawPtr.is_null() {
         raw_from_value = unsafe { &*segment.mFromValue.mServo.mRawPtr };
-        AnimationValue::as_arc(&raw_from_value).as_ref()
+        match segment.mFromComposite {
+            CompositeOperation::Add => {
+                let value_to_composite = AnimationValue::as_arc(&raw_from_value).as_ref();
+                from_composite_result = underlying_value.as_ref().unwrap().add(value_to_composite);
+                from_composite_result.as_ref().unwrap_or(value_to_composite)
+            }
+            _ => { AnimationValue::as_arc(&raw_from_value) }
+        }
     } else {
         underlying_value.as_ref().unwrap()
     };
 
     let raw_to_value;
+    let to_composite_result;
     let to_value = if !segment.mToValue.mServo.mRawPtr.is_null() {
         raw_to_value = unsafe { &*segment.mToValue.mServo.mRawPtr };
-        AnimationValue::as_arc(&raw_to_value).as_ref()
+        match segment.mToComposite {
+            CompositeOperation::Add => {
+                let value_to_composite = AnimationValue::as_arc(&raw_to_value).as_ref();
+                to_composite_result = underlying_value.as_ref().unwrap().add(value_to_composite);
+                to_composite_result.as_ref().unwrap_or(value_to_composite)
+            }
+            _ => { AnimationValue::as_arc(&raw_to_value) }
+        }
     } else {
         underlying_value.as_ref().unwrap()
     };
 
     let progress = unsafe { Gecko_GetProgressFromComputedTiming(computed_timing) };
     if segment.mToKey == segment.mFromKey {
         if progress < 0. {
             value_map.insert(property, from_value.clone());