Bug 1244590 - Part 6: Refactor the calculation of StyleAnimationValue. draft
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 25 May 2016 17:10:53 +0800
changeset 372064 67513e7b66928878a2f4136beb6da4571c9fe241
parent 372063 1b111a0fe4e807f238e05b61602208662e9f755f
child 372065 561c82f0398271b3f8d48f9893c88774490e8ff9
child 372075 83657f344a6d7e9427d94b6193be753b0d17460e
child 372350 818256089fb3269186437ce93489e90dba894c28
child 372613 5c756c76a4c8ec9545bc3d75378acb82439ed78a
push id19429
push userbmo:boris.chiou@gmail.com
push dateFri, 27 May 2016 10:09:46 +0000
bugs1244590
milestone49.0a1
Bug 1244590 - Part 6: Refactor the calculation of StyleAnimationValue. We want to reuse the StyleAnimationValues of properties of each keyframe when applying spacing and building animation property segments, so refactor this part. MozReview-Commit-ID: 8G56C3BU3FR
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeUtils.cpp
dom/animation/KeyframeUtils.h
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -515,21 +515,23 @@ KeyframeEffectReadOnly::HasAnimationOfPr
 
 void
 KeyframeEffectReadOnly::UpdateProperties(nsStyleContext* aStyleContext)
 {
   MOZ_ASSERT(aStyleContext);
 
   nsTArray<AnimationProperty> properties;
   if (mTarget) {
+    nsTArray<ComputedKeyframeValues> computedValues =
+      KeyframeUtils::GetComputedKeyframeValues(mKeyframes, mTarget->mElement,
+                                               aStyleContext);
+
     properties =
-      KeyframeUtils::GetAnimationPropertiesFromKeyframes(aStyleContext,
-                                                         mTarget->mElement,
-                                                         mTarget->mPseudoType,
-                                                         mKeyframes);
+      KeyframeUtils::GetAnimationPropertiesFromKeyframes(mKeyframes,
+                                                         computedValues);
   }
 
   if (mProperties == properties) {
     return;
   }
 
   // Preserve the state of mWinsInCascade and mIsRunningOnCompositor flags.
   nsCSSPropertySet winningInCascadeProperties;
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -3,16 +3,17 @@
  * 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/. */
 
 #include "mozilla/KeyframeUtils.h"
 
 #include "mozilla/AnimationUtils.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Move.h"
+#include "mozilla/StyleAnimationValue.h"
 #include "mozilla/TimingParams.h"
 #include "mozilla/dom/BaseKeyframeTypesBinding.h" // For FastBaseKeyframe etc.
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/KeyframeEffect.h"
 #include "mozilla/dom/KeyframeEffectBinding.h"
 #include "jsapi.h" // For ForOfIterator etc.
 #include "nsClassHashtable.h"
 #include "nsCSSParser.h"
@@ -488,30 +489,30 @@ KeyframeUtils::ApplySpacing(nsTArray<Key
       // TODO
       MOZ_ASSERT(false, "not implement yet");
     }
 
     keyframeA = keyframeB;
   }
 }
 
-/* static */ nsTArray<AnimationProperty>
-KeyframeUtils::GetAnimationPropertiesFromKeyframes(
-    nsStyleContext* aStyleContext,
-    dom::Element* aElement,
-    CSSPseudoElementType aPseudoType,
-    const nsTArray<Keyframe>& aFrames)
+/* static */ nsTArray<ComputedKeyframeValues>
+KeyframeUtils::GetComputedKeyframeValues(const nsTArray<Keyframe>& aKeyframes,
+                                         dom::Element* aElement,
+                                         nsStyleContext* aStyleContext)
 {
   MOZ_ASSERT(aStyleContext);
   MOZ_ASSERT(aElement);
 
-  nsTArray<KeyframeValueEntry> entries;
+  const size_t len = aKeyframes.Length();
+  nsTArray<ComputedKeyframeValues> result(len);
 
-  for (const Keyframe& frame : aFrames) {
+  for (const Keyframe& frame : aKeyframes) {
     nsCSSPropertySet propertiesOnThisKeyframe;
+    ComputedKeyframeValues* computedValues = result.AppendElement();
     for (const PropertyValuePair& pair :
            PropertyPriorityIterator(frame.mPropertyValues)) {
       if (IsInvalidValuePair(pair)) {
         continue;
       }
 
       // Expand each value into the set of longhands and produce
       // a KeyframeValueEntry for each value.
@@ -538,30 +539,48 @@ KeyframeUtils::GetAnimationPropertiesFro
       }
 
       for (auto& value : values) {
         // If we already got a value for this property on the keyframe,
         // skip this one.
         if (propertiesOnThisKeyframe.HasProperty(value.mProperty)) {
           continue;
         }
-
-        KeyframeValueEntry* entry = entries.AppendElement();
-        MOZ_ASSERT(frame.mComputedOffset != Keyframe::kComputedOffsetNotSet,
-                   "Invalid computed offset");
-        entry->mOffset = frame.mComputedOffset;
-        entry->mProperty = value.mProperty;
-        entry->mValue = value.mValue;
-        entry->mTimingFunction = frame.mTimingFunction;
-
+        computedValues->AppendElement(value);
         propertiesOnThisKeyframe.AddProperty(value.mProperty);
       }
     }
   }
 
+  MOZ_ASSERT(result.Length() == aKeyframes.Length(), "Array length mismatch");
+  return result;
+}
+
+/* static */ nsTArray<AnimationProperty>
+KeyframeUtils::GetAnimationPropertiesFromKeyframes(
+  const nsTArray<Keyframe>& aKeyframes,
+  const nsTArray<ComputedKeyframeValues>& aComputedValues)
+{
+  MOZ_ASSERT(aKeyframes.Length() == aComputedValues.Length(),
+             "Array length mismatch");
+
+  nsTArray<KeyframeValueEntry> entries(aKeyframes.Length());
+
+  const size_t len = aKeyframes.Length();
+  for (size_t i = 0; i < len; ++i) {
+    const Keyframe& frame = aKeyframes[i];
+    for (auto& value : aComputedValues[i]) {
+      KeyframeValueEntry* entry = entries.AppendElement();
+      entry->mOffset = frame.mComputedOffset;
+      entry->mProperty = value.mProperty;
+      entry->mValue = value.mValue;
+      entry->mTimingFunction = frame.mTimingFunction;
+    }
+  }
+
   nsTArray<AnimationProperty> result;
   BuildSegmentsFromValueEntries(entries, result);
 
   return result;
 }
 
 /* static */ bool
 KeyframeUtils::IsAnimatableProperty(nsCSSProperty aProperty)
--- a/dom/animation/KeyframeUtils.h
+++ b/dom/animation/KeyframeUtils.h
@@ -13,25 +13,30 @@
 struct JSContext;
 class JSObject;
 
 namespace mozilla {
 struct AnimationProperty;
 enum class CSSPseudoElementType : uint8_t;
 class ErrorResult;
 struct Keyframe;
+struct PropertyStyleAnimationValuePair;
 
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 
 namespace mozilla {
 
+// Represents the set of property-value pairs on a Keyframe converted to
+// computed values.
+using ComputedKeyframeValues = nsTArray<PropertyStyleAnimationValuePair>;
+
 /**
  * Utility methods for processing keyframes.
  */
 class KeyframeUtils
 {
 public:
   /**
    * Converts a JS value representing a property-indexed keyframe or a sequence
@@ -47,44 +52,68 @@ public:
    *   returned.
    */
   static nsTArray<Keyframe>
   GetKeyframesFromObject(JSContext* aCx,
                          JS::Handle<JSObject*> aFrames,
                          ErrorResult& aRv);
 
   /**
+   * Calculate the StyleAnimationValues of properties of each keyframe.
+   * This involves expanding shorthand properties into longhand properties,
+   * removing the duplicated properties for each keyframe, and creating an
+   * array of |property:computed value| pairs for each keyframe.
+   *
+   * These computed values are used *both* when computing the final set of
+   * per-property animation values (see GetAnimationPropertiesFromKeyframes) as
+   * well when applying paced spacing. By returning these values here, we allow
+   * the result to be re-used in both operations.
+   *
+   * @param aKeyframes The input keyframes.
+   * @param aElement The context element.
+   * @param aStyleContext The style context to use when computing values.
+   * @return The set of ComputedKeyframeValues. The length will be the same as
+   *   aFrames.
+   */
+  static nsTArray<ComputedKeyframeValues>
+  GetComputedKeyframeValues(const nsTArray<Keyframe>& aKeyframes,
+                            dom::Element* aElement,
+                            nsStyleContext* aStyleContext);
+
+  /**
    * Fills in the mComputedOffset member of each keyframe in the given array
    * using the specified spacing mode.
    *
    * https://w3c.github.io/web-animations/#spacing-keyframes
    *
    * @param aKeyframes The set of keyframes to adjust.
    * @param aSpacingMode The spacing mode to apply.
    */
   static void ApplySpacing(nsTArray<Keyframe>& aKeyframes,
                            SpacingMode aSpacingMode);
 
   /**
    * Converts an array of Keyframe objects into an array of AnimationProperty
-   * objects. This involves expanding shorthand properties into longhand
-   * properties, creating an array of computed values for each longhand
-   * property and determining the offset and timing function to use for each
-   * value.
+   * objects. This involves creating an array of computed values for each
+   * longhand property and determining the offset and timing function to use
+   * for each value.
    *
-   * @param aStyleContext The style context to use when computing values.
-   * @param aFrames The input keyframes.
+   * @param aKeyframes The input keyframes.
+   * @param aComputedValues The computed keyframe values (as returned by
+   *   GetComputedKeyframeValues) used to fill in the individual
+   *   AnimationPropertySegment objects. Although these values could be
+   *   calculated from |aKeyframes|, passing them in as a separate parameter
+   *   allows the result of GetComputedKeyframeValues to be re-used both
+   *   here and in ApplySpacing.
    * @return The set of animation properties. If an error occurs, the returned
    *   array will be empty.
    */
-  static nsTArray<AnimationProperty>
-  GetAnimationPropertiesFromKeyframes(nsStyleContext* aStyleContext,
-                                      dom::Element* aElement,
-                                      CSSPseudoElementType aPseudoType,
-                                      const nsTArray<Keyframe>& aFrames);
+  static nsTArray<AnimationProperty> GetAnimationPropertiesFromKeyframes(
+    const nsTArray<Keyframe>& aKeyframes,
+    const nsTArray<ComputedKeyframeValues>& aComputedValues);
 
   /**
    * Check if the property or, for shorthands, one or more of
    * its subproperties, is animatable.
    *
    * @param aProperty The property to check.
    * @return true if |aProperty| is animatable.
    */