Bug 1260976 - Remove the old AnimationProperty-based GetFrames; r?heycam draft
authorBrian Birtles <birtles@gmail.com>
Fri, 01 Apr 2016 09:29:31 +0900
changeset 346373 841e2b505d7d137e242f605e1deb1069484f768b
parent 346372 311e85fc2cc7df78897f2bbe3aa891daebda1b04
child 346447 e24407917b239e31560910cb91d0e4e65bfdcfed
push id14366
push userbbirtles@mozilla.com
push dateFri, 01 Apr 2016 00:30:11 +0000
reviewersheycam
bugs1260976
milestone48.0a1
Bug 1260976 - Remove the old AnimationProperty-based GetFrames; r?heycam MozReview-Commit-ID: FoEf7DymVDm
dom/animation/KeyframeEffect.cpp
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -850,91 +850,16 @@ DumpAnimationProperties(nsTArray<Animati
  * A property and StyleAnimationValue pair.
  */
 struct KeyframeValue
 {
   nsCSSProperty mProperty;
   StyleAnimationValue mValue;
 };
 
-/**
- * Represents a relative position for a value in a keyframe animation.
- */
-enum class ValuePosition
-{
-  First,  // value at 0 used for reverse filling
-  Left,   // value coming in to a given offset
-  Right,  // value coming out from a given offset
-  Last    // value at 1 used for forward filling
-};
-
-/**
- * A single value in a keyframe animation, used by GetFrames to produce a
- * minimal set of keyframe objects.
- */
-struct OrderedKeyframeValueEntry : KeyframeValue
-{
-  float mOffset;
-  const Maybe<ComputedTimingFunction>* mTimingFunction;
-  ValuePosition mPosition;
-
-  bool SameKeyframe(const OrderedKeyframeValueEntry& aOther) const
-  {
-    return mOffset == aOther.mOffset &&
-           !!mTimingFunction == !!aOther.mTimingFunction &&
-           (!mTimingFunction || *mTimingFunction == *aOther.mTimingFunction) &&
-           mPosition == aOther.mPosition;
-  }
-
-  struct ForKeyframeGenerationComparator
-  {
-    static bool Equals(const OrderedKeyframeValueEntry& aLhs,
-                       const OrderedKeyframeValueEntry& aRhs)
-    {
-      return aLhs.SameKeyframe(aRhs) &&
-             aLhs.mProperty == aRhs.mProperty;
-    }
-    static bool LessThan(const OrderedKeyframeValueEntry& aLhs,
-                         const OrderedKeyframeValueEntry& aRhs)
-    {
-      // First, sort by offset.
-      if (aLhs.mOffset != aRhs.mOffset) {
-        return aLhs.mOffset < aRhs.mOffset;
-      }
-
-      // Second, by position.
-      if (aLhs.mPosition != aRhs.mPosition) {
-        return aLhs.mPosition < aRhs.mPosition;
-      }
-
-      // Third, by easing.
-      if (aLhs.mTimingFunction) {
-        if (aRhs.mTimingFunction) {
-          int32_t order =
-            ComputedTimingFunction::Compare(*aLhs.mTimingFunction,
-                                            *aRhs.mTimingFunction);
-          if (order != 0) {
-            return order < 0;
-          }
-        } else {
-          return true;
-        }
-      } else {
-        if (aRhs.mTimingFunction) {
-          return false;
-        }
-      }
-
-      // Last, by property IDL name.
-      return nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty) <
-             nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty);
-    }
-  };
-};
-
 /* static */ already_AddRefed<KeyframeEffectReadOnly>
 KeyframeEffectReadOnly::Constructor(
     const GlobalObject& aGlobal,
     const Nullable<ElementOrCSSPseudoElement>& aTarget,
     JS::Handle<JSObject*> aFrames,
     const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
     ErrorResult& aRv)
 {
@@ -1051,32 +976,30 @@ KeyframeEffectReadOnly::GetProperties(
         propertyDetails.mValues.AppendElement(toValue, mozilla::fallible);
       }
     }
 
     aProperties.AppendElement(propertyDetails);
   }
 }
 
-// TODO: This will eventually become the new GetFrames
-static void
-GetFramesFromFrames(JSContext*& aCx,
-                    const nsTArray<Keyframe>& aFrames,
-                    nsTArray<JSObject*>& aResult,
-                    ErrorResult& aRv)
+void
+KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
+                                  nsTArray<JSObject*>& aResult,
+                                  ErrorResult& aRv)
 {
   MOZ_ASSERT(aResult.IsEmpty());
   MOZ_ASSERT(!aRv.Failed());
 
-  if (!aResult.SetCapacity(aFrames.Length(), mozilla::fallible)) {
+  if (!aResult.SetCapacity(mFrames.Length(), mozilla::fallible)) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  for (const Keyframe& keyframe : aFrames) {
+  for (const Keyframe& keyframe : mFrames) {
     // Set up a dictionary object for the explicit members
     BaseComputedKeyframe keyframeDict;
     if (keyframe.mOffset) {
       keyframeDict.mOffset.SetValue(keyframe.mOffset.value());
     }
     keyframeDict.mComputedOffset.Construct(keyframe.mComputedOffset);
     if (keyframe.mTimingFunction) {
       keyframeDict.mEasing.Truncate();
@@ -1114,119 +1037,16 @@ GetFramesFromFrames(JSContext*& aCx,
         return;
       }
     }
 
     aResult.AppendElement(keyframeObject);
   }
 }
 
-void
-KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
-                                  nsTArray<JSObject*>& aResult,
-                                  ErrorResult& aRv)
-{
-  // Use the specified frames if we have any
-  if (!mFrames.IsEmpty()) {
-    GetFramesFromFrames(aCx, mFrames, aResult, aRv);
-    return;
-  }
-
-  nsTArray<OrderedKeyframeValueEntry> entries;
-
-  for (const AnimationProperty& property : mProperties) {
-    for (size_t i = 0, n = property.mSegments.Length(); i < n; i++) {
-      const AnimationPropertySegment& segment = property.mSegments[i];
-
-      // We append the mFromValue for each segment.  If the mToValue
-      // differs from the following segment's mFromValue, or if we're on
-      // the last segment, then we append the mToValue as well.
-      //
-      // Each value is annotated with whether it is a "first", "left", "right",
-      // or "last" value.  "left" and "right" values represent the value coming
-      // in to and out of a given offset, in the middle of an animation.  For
-      // most segments, the mToValue is the "left" and the following segment's
-      // mFromValue is the "right".  The "first" and "last" values are the
-      // additional values assigned to offset 0 or 1 for reverse and forward
-      // filling.  These annotations are used to ensure multiple values for a
-      // given property are sorted correctly and that we do not merge Keyframes
-      // with different values for the same offset.
-
-      OrderedKeyframeValueEntry* entry = entries.AppendElement();
-      entry->mProperty = property.mProperty;
-      entry->mValue = segment.mFromValue;
-      entry->mOffset = segment.mFromKey;
-      entry->mTimingFunction = &segment.mTimingFunction;
-      entry->mPosition =
-        segment.mFromKey == segment.mToKey && segment.mFromKey == 0.0f ?
-          ValuePosition::First :
-          ValuePosition::Right;
-
-      if (i == n - 1 ||
-          segment.mToValue != property.mSegments[i + 1].mFromValue) {
-        entry = entries.AppendElement();
-        entry->mProperty = property.mProperty;
-        entry->mValue = segment.mToValue;
-        entry->mOffset = segment.mToKey;
-        entry->mTimingFunction = segment.mToKey == 1.0f ?
-          nullptr : &segment.mTimingFunction;
-        entry->mPosition =
-          segment.mFromKey == segment.mToKey && segment.mToKey == 1.0f ?
-            ValuePosition::Last :
-            ValuePosition::Left;
-      }
-    }
-  }
-
-  entries.Sort(OrderedKeyframeValueEntry::ForKeyframeGenerationComparator());
-
-  for (size_t i = 0, n = entries.Length(); i < n; ) {
-    OrderedKeyframeValueEntry* entry = &entries[i];
-    OrderedKeyframeValueEntry* previousEntry = nullptr;
-
-    // Create a JS object with the BaseComputedKeyframe dictionary members.
-    BaseComputedKeyframe keyframeDict;
-    keyframeDict.mOffset.SetValue(entry->mOffset);
-    keyframeDict.mComputedOffset.Construct(entry->mOffset);
-    if (entry->mTimingFunction && entry->mTimingFunction->isSome()) {
-      // If null, leave easing as its default "linear".
-      keyframeDict.mEasing.Truncate();
-      entry->mTimingFunction->value().AppendToString(keyframeDict.mEasing);
-    }
-
-    JS::Rooted<JS::Value> keyframeJSValue(aCx);
-    if (!ToJSValue(aCx, keyframeDict, &keyframeJSValue)) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
-    JS::Rooted<JSObject*> keyframe(aCx, &keyframeJSValue.toObject());
-    do {
-      const char* name = nsCSSProps::PropertyIDLName(entry->mProperty);
-      nsString stringValue;
-      StyleAnimationValue::UncomputeValue(entry->mProperty,
-                                          entry->mValue,
-                                          stringValue);
-      JS::Rooted<JS::Value> value(aCx);
-      if (!ToJSValue(aCx, stringValue, &value) ||
-          !JS_DefineProperty(aCx, keyframe, name, value, JSPROP_ENUMERATE)) {
-        aRv.Throw(NS_ERROR_FAILURE);
-        return;
-      }
-      if (++i == n) {
-        break;
-      }
-      previousEntry = entry;
-      entry = &entries[i];
-    } while (entry->SameKeyframe(*previousEntry));
-
-    aResult.AppendElement(keyframe);
-  }
-}
-
 /* static */ const TimeDuration
 KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
 {
   // The amount of time we can wait between updating throttled animations
   // on the main thread that influence the overflow region.
   static const TimeDuration kOverflowRegionRefreshInterval =
     TimeDuration::FromMilliseconds(200);