Bug 1245748 - Add GetAnimationPropertiesFromKeyframes; r=heycam draft
authorBrian Birtles <birtles@gmail.com>
Tue, 22 Mar 2016 16:34:14 +0900
changeset 344235 9c6c222e099090457dfd71661bfbc9715401e91c
parent 344234 4e8faf1740a5f145cd565c23223758639320ba23
child 344236 0511514f862d927bc59b3436798aca16796f8763
push id13778
push userbbirtles@mozilla.com
push dateThu, 24 Mar 2016 03:27:42 +0000
reviewersheycam
bugs1245748
milestone48.0a1
Bug 1245748 - Add GetAnimationPropertiesFromKeyframes; r=heycam MozReview-Commit-ID: GUnogloqViS
dom/animation/KeyframeUtils.cpp
dom/animation/KeyframeUtils.h
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -531,16 +531,97 @@ KeyframeUtils::GetKeyframesFromObject(JS
   if (RequiresAdditiveAnimation(keyframes, doc)) {
     aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
     keyframes.Clear();
   }
 
   return keyframes;
 }
 
+/* static */ nsTArray<AnimationProperty>
+KeyframeUtils::GetAnimationPropertiesFromKeyframes(
+    nsStyleContext* aStyleContext,
+    dom::Element* aElement,
+    CSSPseudoElementType aPseudoType,
+    const nsTArray<Keyframe>& aFrames)
+{
+  nsTArray<KeyframeValueEntry> entries;
+
+  for (const Keyframe& frame : aFrames) {
+    nsCSSPropertySet propertiesOnThisKeyframe;
+    for (const PropertyValuePair& pair :
+           PropertyPriorityIterator(frame.mPropertyValues)) {
+      // We currently store invalid longhand values on keyframes as a token
+      // stream so if we see one of them, just keep moving.
+      if (!nsCSSProps::IsShorthand(pair.mProperty) &&
+          pair.mValue.GetUnit() == eCSSUnit_TokenStream) {
+        continue;
+      }
+
+      // Expand each value into the set of longhands and produce
+      // a KeyframeValueEntry for each value.
+      nsTArray<PropertyStyleAnimationValuePair> values;
+
+      // For shorthands, we store the string as a token stream so we need to
+      // extract that first.
+      if (nsCSSProps::IsShorthand(pair.mProperty)) {
+        nsCSSValueTokenStream* tokenStream = pair.mValue.GetTokenStreamValue();
+        if (!StyleAnimationValue::ComputeValues(pair.mProperty,
+              nsCSSProps::eEnabledForAllContent, aElement, aStyleContext,
+              tokenStream->mTokenStream, /* aUseSVGMode */ false, values)) {
+          continue;
+        }
+      } else {
+        if (!StyleAnimationValue::ComputeValues(pair.mProperty,
+              nsCSSProps::eEnabledForAllContent, aElement, aStyleContext,
+              pair.mValue, /* aUseSVGMode */ false, values)) {
+          continue;
+        }
+        MOZ_ASSERT(values.Length() == 1,
+                   "Longhand properties should produce a single"
+                   " StyleAnimationValue");
+
+        // 'visibility' requires special handling that is unique to CSS
+        // Transitions/CSS Animations/Web Animations (i.e. not SMIL) so we
+        // apply that here.
+        //
+        // Bug 1259285 - Move this code to StyleAnimationValue
+        if (pair.mProperty == eCSSProperty_visibility) {
+          MOZ_ASSERT(values[0].mValue.GetUnit() ==
+                      StyleAnimationValue::eUnit_Enumerated,
+                    "unexpected unit");
+          values[0].mValue.SetIntValue(values[0].mValue.GetIntValue(),
+                                       StyleAnimationValue::eUnit_Visibility);
+        }
+      }
+
+      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();
+        entry->mOffset = frame.mComputedOffset;
+        entry->mProperty = value.mProperty;
+        entry->mValue = value.mValue;
+        entry->mTimingFunction = frame.mTimingFunction;
+
+        propertiesOnThisKeyframe.AddProperty(value.mProperty);
+      }
+    }
+  }
+
+  nsTArray<AnimationProperty> result;
+  BuildSegmentsFromValueEntries(entries, result);
+
+  return result;
+}
+
 
 // ------------------------------------------------------------------
 //
 // Internal helpers
 //
 // ------------------------------------------------------------------
 
 /**
--- a/dom/animation/KeyframeUtils.h
+++ b/dom/animation/KeyframeUtils.h
@@ -64,13 +64,31 @@ public:
    * @return The set of processed keyframes. If an error occurs, aRv will be
    *   filled-in with the appropriate error code and an empty array will be
    *   returned.
    */
   static nsTArray<Keyframe>
   GetKeyframesFromObject(JSContext* aCx,
                          JS::Handle<JSObject*> aFrames,
                          ErrorResult& aRv);
+
+  /**
+   * 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.
+   *
+   * @param aStyleContext The style context to use when computing values.
+   * @param aFrames The input keyframes.
+   * @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);
 };
 
 } // namespace mozilla
 
 #endif // mozilla_KeyframeUtils_h