Bug 1346052 - Part 3: Implement AnimationValue::FromString. draft
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 03 May 2017 11:15:27 +0800
changeset 571666 3e2acc0717322ec6d2c4f5231cd2299da9d1c0fd
parent 571665 49703a8e4b790fb0b8929bf6a02efab874767d9e
child 571667 43a8619c59ccf7d928b219a4332a95f1f59a9acf
push id56881
push userbmo:boris.chiou@gmail.com
push dateWed, 03 May 2017 03:53:29 +0000
bugs1346052
milestone55.0a1
Bug 1346052 - Part 3: Implement AnimationValue::FromString. AnimationValue::FromString compute the AnimationValue from a string. MozReview-Commit-ID: CX8wairpnfN
layout/style/ServoBindingList.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/StyleAnimationValue.cpp
layout/style/StyleAnimationValue.h
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -182,16 +182,22 @@ SERVO_BINDING_FUNC(Servo_AnimationValue_
                    RawServoAnimationValueBorrowed value,
                    RefPtr<nsCSSValueSharedList>* list)
 SERVO_BINDING_FUNC(Servo_AnimationValue_DeepEqual, bool,
                    RawServoAnimationValueBorrowed,
                    RawServoAnimationValueBorrowed)
 SERVO_BINDING_FUNC(Servo_AnimationValue_Uncompute,
                    RawServoDeclarationBlockStrong,
                    RawServoAnimationValueBorrowed value)
+SERVO_BINDING_FUNC(Servo_AnimationValue_Compute,
+                   RawServoAnimationValueStrong,
+                   RawServoDeclarationBlockBorrowed declarations,
+                   ServoComputedValuesBorrowed style,
+                   ServoComputedValuesBorrowedOrNull parent_style,
+                   RawServoStyleSetBorrowed raw_data)
 
 // Style attribute
 SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
                    const nsACString* data,
                    RawGeckoURLExtraData* extra_data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,
                    RawServoDeclarationBlockStrong)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Clone, RawServoDeclarationBlockStrong,
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -892,16 +892,27 @@ already_AddRefed<ServoComputedValues>
 ServoStyleSet::GetBaseComputedValuesForElement(Element* aElement,
                                                nsIAtom* aPseudoTag)
 {
   return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
                                                         aElement,
                                                         aPseudoTag).Consume();
 }
 
+already_AddRefed<RawServoAnimationValue>
+ServoStyleSet::ComputeAnimationValue(
+  RawServoDeclarationBlock* aDeclarations,
+  const ServoComputedValuesWithParent& aComputedValues)
+{
+  return Servo_AnimationValue_Compute(aDeclarations,
+                                      aComputedValues.mCurrentStyle,
+                                      aComputedValues.mParentStyle,
+                                      mRawSet.get()).Consume();
+}
+
 void
 ServoStyleSet::RebuildData()
 {
   ClearNonInheritingStyleContexts();
   Servo_StyleSet_RebuildData(mRawSet.get());
 }
 
 already_AddRefed<ServoComputedValues>
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -299,16 +299,20 @@ public:
    * Resolve style for a given declaration block with/without the parent style.
    * If the parent style is not specified, the document default computed values
    * is used.
    */
   already_AddRefed<ServoComputedValues>
   ResolveForDeclarations(ServoComputedValuesBorrowedOrNull aParentOrNull,
                          RawServoDeclarationBlockBorrowed aDeclarations);
 
+  already_AddRefed<RawServoAnimationValue>
+  ComputeAnimationValue(RawServoDeclarationBlock* aDeclaration,
+                        const ServoComputedValuesWithParent& aComputedValues);
+
 private:
   already_AddRefed<nsStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
                                               nsStyleContext* aParentContext,
                                               nsIAtom* aPseudoTag,
                                               CSSPseudoElementType aPseudoType,
                                               dom::Element* aElementForAnimation);
 
   already_AddRefed<nsStyleContext> GetContext(nsIContent* aContent,
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -19,21 +19,24 @@
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsIStyleRule.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsString.h"
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
 #include "nsComputedDOMStyle.h"
+#include "nsContentUtils.h"
 #include "nsCSSParser.h"
 #include "nsCSSPseudoElements.h"
 #include "mozilla/css/Declaration.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/FloatingPoint.h"
+#include "mozilla/ServoComputedValuesWithParent.h"
+#include "mozilla/KeyframeUtils.h" // KeyframeUtils::ParseProperty
 #include "mozilla/Likely.h"
 #include "mozilla/ServoBindings.h" // RawServoDeclarationBlock
 #include "gfxMatrix.h"
 #include "gfxQuaternion.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "gfx2DGlue.h"
 
@@ -5190,16 +5193,17 @@ StyleAnimationValue::operator==(const St
     case eUnit_ComplexColor:
       return *mValue.mComplexColor == *aOther.mValue.mComplexColor;
   }
 
   NS_NOTREACHED("incomplete case");
   return false;
 }
 
+
 // AnimationValue Implementation
 
 bool
 AnimationValue::operator==(const AnimationValue& aOther) const
 {
   // It is possible to compare an empty AnimationValue with others, so both
   // mServo and mGecko could be null while comparing.
   MOZ_ASSERT(!mServo || mGecko.IsNull());
@@ -5297,8 +5301,70 @@ AnimationValue::ComputeDistance(nsCSSPro
   return StyleAnimationValue::ComputeDistance(aProperty,
                                               mGecko,
                                               aOther.mGecko,
                                               aStyleContext,
                                               distance)
          ? distance
          : 0.0;
 }
+
+/* static */ AnimationValue
+AnimationValue::FromString(nsCSSPropertyID aProperty,
+                           const nsAString& aValue,
+                           Element* aElement)
+{
+  MOZ_ASSERT(aElement);
+
+  AnimationValue result;
+
+  nsCOMPtr<nsIDocument> doc = aElement->GetComposedDoc();
+  if (!doc) {
+    return result;
+  }
+
+  nsCOMPtr<nsIPresShell> shell = doc->GetShell();
+  if (!shell) {
+    return result;
+  }
+
+  // GetStyleContext() flushes style, so we shouldn't assume that any
+  // non-owning references we have are still valid.
+  RefPtr<nsStyleContext> styleContext =
+    nsComputedDOMStyle::GetStyleContext(aElement, nullptr, shell);
+
+  if (styleContext->StyleSource().IsServoComputedValues()) {
+    nsPresContext* presContext = shell->GetPresContext();
+    if (!presContext) {
+      return result;
+    }
+
+    RefPtr<RawServoDeclarationBlock> declarations =
+      KeyframeUtils::ParseProperty(aProperty, aValue, doc);
+
+    if (!declarations) {
+      return result;
+    }
+
+    // We use the current ServoComputeValues and its parent ServoComputeValues
+    // to reconstruct the Context and then compute the AnimationValue. However,
+    // nsStyleContext::GetParentAllowServo() is going away, so if possible, we
+    // should find another way to get the parent ServoComputedValues.
+    RefPtr<nsStyleContext> parentContext = styleContext->GetParentAllowServo();
+    const ServoComputedValuesWithParent styles = {
+      styleContext->StyleSource().AsServoComputedValues(),
+      parentContext ? parentContext->StyleSource().AsServoComputedValues()
+                    : nullptr
+    };
+
+    result.mServo = presContext->StyleSet()
+                               ->AsServo()
+                               ->ComputeAnimationValue(declarations, styles);
+    return result;
+  }
+
+  if (!StyleAnimationValue::ComputeValue(aProperty, aElement, styleContext,
+                                         aValue, false /* |aUseSVGMode| */,
+                                         result.mGecko)) {
+    MOZ_ASSERT(result.IsNull());
+  }
+  return result;
+}
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -571,23 +571,38 @@ private:
 struct AnimationValue
 {
   explicit AnimationValue(const StyleAnimationValue& aValue)
     : mGecko(aValue) { }
   explicit AnimationValue(const RefPtr<RawServoAnimationValue>& aValue)
     : mServo(aValue) { }
   AnimationValue() = default;
 
-  // mGecko and mServo are mutually exclusive: only one or the other should
-  // ever be set.
-  // FIXME: After obsoleting StyleAnimationValue, we should remove mGecko, and
-  // make AnimationValue a wrapper of RawServoAnimationValue to hide these
-  // FFIs.
-  StyleAnimationValue mGecko;
-  RefPtr<RawServoAnimationValue> mServo;
+  AnimationValue(const AnimationValue& aOther)
+    : mGecko(aOther.mGecko), mServo(aOther.mServo) { }
+  AnimationValue(AnimationValue&& aOther)
+    : mGecko(Move(aOther.mGecko)), mServo(Move(aOther.mServo)) { }
+
+  AnimationValue& operator=(const AnimationValue& aOther)
+  {
+    if (this != &aOther) {
+      mGecko = aOther.mGecko;
+      mServo = aOther.mServo;
+    }
+    return *this;
+  }
+  AnimationValue& operator=(AnimationValue&& aOther)
+  {
+    MOZ_ASSERT(this != &aOther, "Do not move itself");
+    if (this != &aOther) {
+      mGecko = Move(aOther.mGecko);
+      mServo = Move(aOther.mServo);
+    }
+    return *this;
+  }
 
   bool operator==(const AnimationValue& aOther) const;
   bool operator!=(const AnimationValue& aOther) const;
 
   bool IsNull() const { return mGecko.IsNull() && !mServo; }
 
   float GetOpacity() const;
 
@@ -604,16 +619,31 @@ struct AnimationValue
                           const AnimationValue& aToValue) const;
 
   // Compute the distance between *this and aOther.
   // If |aStyleContext| is nullptr, we will return 0.0 if we have mismatched
   // transform lists.
   double ComputeDistance(nsCSSPropertyID aProperty,
                          const AnimationValue& aOther,
                          nsStyleContext* aStyleContext) const;
+
+  // Create an AnimaitonValue from a string. This method flushes style, so we
+  // should use this carefully. Now, it is only used by
+  // nsDOMWindowUtils::ComputeAnimationDistance.
+  static AnimationValue FromString(nsCSSPropertyID aProperty,
+                                   const nsAString& aValue,
+                                   dom::Element* aElement);
+
+  // mGecko and mServo are mutually exclusive: only one or the other should
+  // ever be set.
+  // FIXME: After obsoleting StyleAnimationValue, we should remove mGecko, and
+  // make AnimationValue a wrapper of RawServoAnimationValue to hide these
+  // FFIs.
+  StyleAnimationValue mGecko;
+  RefPtr<RawServoAnimationValue> mServo;
 };
 
 struct PropertyStyleAnimationValuePair
 {
   nsCSSPropertyID mProperty;
   AnimationValue mValue;
 };
 } // namespace mozilla