Bug 1305325 - Part 4: Update base values for each property. r?birtles draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Fri, 21 Oct 2016 05:46:25 +0900
changeset 427788 247254df784d59d81cbf1e7d456bd04774de7fd2
parent 427787 44db51bbe77a99c064b179de3bfedf9a552dd6c2
child 427789 00c822cc2175e7f3135256bd30fe6f5e135f75bf
push id33113
push userbmo:hiikezoe@mozilla-japan.org
push dateThu, 20 Oct 2016 21:36:11 +0000
reviewersbirtles
bugs1305325
milestone52.0a1
Bug 1305325 - Part 4: Update base values for each property. r?birtles Now EffectSet has a hashtable to store non-animating base value for each property as StyleAnimationValue. StyleAnimationValue is convinient to be used in KeyframeEffectReadOnly::ComposeStyle(). The hashtable is updated in UpdateCascadeResults(). The reason why we don't update the hashtable in UpdateProperties() is; 1) We have to update it even if there is no animation properties changes because changing non-animating style value does not cause any animation property changes. If we do it in Updateproperties() it's apparently less effective. 2) There is the case that we have no EffectSet in UpdateProperties(), e.g. creating an animation. What happens on Element.animate(); i) KeyframeEffect constructor i-1) UpdateProperties() ii) Animation constructor with the effect ii-1) KeyframeEffectReadOnly::SetAnimation() ii-2) The effect is added in EffectSet MozReview-Commit-ID: FPzyX9fxxx3
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
dom/animation/EffectSet.h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -724,38 +724,48 @@ EffectCompositor::UpdateCascadeResults(E
   std::bitset<LayerAnimationInfo::kRecords>
     prevCompositorPropertiesForAnimationsLevel =
       compositorPropertiesInSet(propertiesForAnimationsLevel);
 
   propertiesWithImportantRules.Empty();
   propertiesForAnimationsLevel.Empty();
 
   bool hasCompositorPropertiesForTransition = false;
+  nsCSSPropertyIDSet animatedProperties;
 
   for (const KeyframeEffectReadOnly* effect : sortedEffectList) {
     MOZ_ASSERT(effect->GetAnimation(),
                "Effects on a target element should have an Animation");
     CascadeLevel cascadeLevel = effect->GetAnimation()->CascadeLevel();
 
     for (const AnimationProperty& prop : effect->Properties()) {
+      animatedProperties.AddProperty(prop.mProperty);
+
       if (overriddenProperties.HasProperty(prop.mProperty)) {
         propertiesWithImportantRules.AddProperty(prop.mProperty);
       }
       if (cascadeLevel == EffectCompositor::CascadeLevel::Animations) {
         propertiesForAnimationsLevel.AddProperty(prop.mProperty);
       }
 
       if (nsCSSProps::PropHasFlags(prop.mProperty,
                                    CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR) &&
           cascadeLevel == EffectCompositor::CascadeLevel::Transitions) {
         hasCompositorPropertiesForTransition = true;
       }
     }
   }
 
+  if (aStyleContext) {
+    UpdateBaseStyleSet(aEffectSet,
+                       aElement,
+                       aStyleContext,
+                       animatedProperties);
+  }
+
   aEffectSet.MarkCascadeUpdated();
 
   nsPresContext* presContext = GetPresContext(aElement);
   if (!presContext) {
     return;
   }
 
   // If properties for compositor are newly overridden by !important rules, or
@@ -804,16 +814,58 @@ EffectCompositor::SetPerformanceWarning(
     return;
   }
 
   for (KeyframeEffectReadOnly* effect : *effects) {
     effect->SetPerformanceWarning(aProperty, aWarning);
   }
 }
 
+/* static */ void
+EffectCompositor::UpdateBaseStyleSet(
+  EffectSet& aEffectSet,
+  Element* aElement,
+  nsStyleContext* aStyleContext,
+  const nsCSSPropertyIDSet& aTargetProperties)
+{
+  if (!aStyleContext->PresContext()->StyleSet()->IsGecko()) {
+    // FIXME: Bug 1311257: Get the base value for the servo backend.
+    return;
+  }
+
+  EffectSet::BaseStyleValueSet& baseStyleValues =
+    aEffectSet.GetBaseStyleValues();
+  baseStyleValues.Clear();
+
+  RefPtr<nsStyleContext> styleContextWithoutAnimation =
+    aStyleContext->PresContext()->StyleSet()->AsGecko()->
+      ResolveStyleWithoutAnimation(aElement, aStyleContext,
+                                   eRestyle_AllHintsWithAnimations);
+
+  // Iterate over all |aTargetProperties| and resolve style for the property.
+  for (size_t iHigh = 0; iHigh < nsCSSPropertyIDSet::kChunkCount; ++iHigh) {
+    if (!aTargetProperties.HasPropertyInChunk(iHigh)) {
+      continue;
+    }
+    for (size_t iLow = 0; iLow < nsCSSPropertyIDSet::kBitsInChunk; ++iLow) {
+      if (!aTargetProperties.HasPropertyAt(iHigh, iLow)) {
+        continue;
+      }
+      nsCSSPropertyID property = nsCSSPropertyIDSet::CSSPropertyAt(iHigh, iLow);
+      StyleAnimationValue baseValue;
+      DebugOnly<bool> result =
+        StyleAnimationValue::ExtractComputedValue(property,
+                                                  styleContextWithoutAnimation,
+                                                  baseValue);
+      MOZ_ASSERT(result, "could not extract computed value");
+      baseStyleValues.Put(property, Move(baseValue));
+    }
+  }
+}
+
 // ---------------------------------------------------------
 //
 // Nested class: AnimationStyleRuleProcessor
 //
 // ---------------------------------------------------------
 
 NS_IMPL_ISUPPORTS(EffectCompositor::AnimationStyleRuleProcessor,
                   nsIStyleRuleProcessor)
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -210,16 +210,22 @@ public:
 
   // Associates a performance warning with effects on |aFrame| that animates
   // |aProperty|.
   static void SetPerformanceWarning(
     const nsIFrame* aFrame,
     nsCSSPropertyID aProperty,
     const AnimationPerformanceWarning& aWarning);
 
+  // Update base style value set on |aElement| for |aTargetProperties| with
+  // |aStyleContext|.
+  static void UpdateBaseStyleSet(EffectSet& aEffectSet,
+                                 dom::Element* aElement,
+                                 nsStyleContext* aStyleContext,
+                                 const nsCSSPropertyIDSet& aTargetProperties);
 private:
   ~EffectCompositor() = default;
 
   // Rebuilds the animation rule corresponding to |aCascadeLevel| on the
   // EffectSet associated with the specified (pseudo-)element.
   static void ComposeAnimationRule(dom::Element* aElement,
                                    CSSPseudoElementType aPseudoType,
                                    CascadeLevel aCascadeLevel,
--- a/dom/animation/EffectSet.h
+++ b/dom/animation/EffectSet.h
@@ -194,16 +194,29 @@ public:
   {
     return mPropertiesWithImportantRules;
   }
   nsCSSPropertyIDSet& PropertiesForAnimationsLevel()
   {
     return mPropertiesForAnimationsLevel;
   }
 
+  bool GetBaseStyleAnimationValue(nsCSSPropertyID aProperty,
+                                  StyleAnimationValue& aValue) const
+  {
+    return mBaseStyleValues.Get(aProperty, &aValue);
+  }
+
+  typedef nsDataHashtable<nsUint32HashKey, StyleAnimationValue>
+    BaseStyleValueSet;
+  BaseStyleValueSet& GetBaseStyleValues()
+  {
+    return mBaseStyleValues;
+  }
+
 private:
   static nsIAtom* GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType);
 
   OwningEffectSet mEffects;
 
   // These style rules contain the style data for currently animating
   // values.  They only match when styling with animation.  When we
   // style without animation, we need to not use them so that we can
@@ -242,16 +255,18 @@ private:
   // Specifies the compositor-animatable properties that are overridden by
   // !important rules.
   nsCSSPropertyIDSet mPropertiesWithImportantRules;
   // Specifies the properties for which the result will be added to the
   // animations level of the cascade and hence should be skipped when we are
   // composing the animation style for the transitions level of the cascede.
   nsCSSPropertyIDSet mPropertiesForAnimationsLevel;
 
+  BaseStyleValueSet mBaseStyleValues;
+
 #ifdef DEBUG
   // Track how many iterators are referencing this effect set when we are
   // destroyed, we can assert that nothing is still pointing to us.
   uint64_t mActiveIterators;
 
   bool mCalledPropertyDtor;
 #endif
 };