Bug 1330190 - Part 2: Add a new function named ResolveStyleWithoutAnimation. r?heycam draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Mon, 16 Jan 2017 16:57:13 +0900
changeset 461300 5c4eda1e2d1808131a20cb934f043afbd35bcd98
parent 461299 8bf9fa9f398067081df6c39bbc139dd024182ffe
child 461301 3c5bcedb5c876c3e329466c70f945238f5180ca4
push id41639
push userhikezoe@mozilla.com
push dateMon, 16 Jan 2017 11:20:00 +0000
reviewersheycam
bugs1330190
milestone53.0a1
Bug 1330190 - Part 2: Add a new function named ResolveStyleWithoutAnimation. r?heycam Unlike the other one this function does not need an old nsStyleContext. This function just resolves style without all animation data in the first place. The existing ResolveStyleWithoutAnimation is renamed to ResolveStyleByRemovingAnimation. MozReview-Commit-ID: 1RmCQNw0MmW
dom/animation/EffectCompositor.cpp
layout/style/nsAnimationManager.cpp
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
layout/style/nsTransitionManager.cpp
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -905,18 +905,18 @@ EffectCompositor::GetBaseStyle(nsCSSProp
   // Check whether there is a cached style.
   result = effectSet->GetBaseStyle(aProperty);
   if (!result.IsNull()) {
     return result;
   }
 
   RefPtr<nsStyleContext> styleContextWithoutAnimation =
     aStyleContext->PresContext()->StyleSet()->AsGecko()->
-      ResolveStyleWithoutAnimation(&aElement, aStyleContext,
-                                   eRestyle_AllHintsWithAnimations);
+      ResolveStyleByRemovingAnimation(&aElement, aStyleContext,
+                                      eRestyle_AllHintsWithAnimations);
 
   DebugOnly<bool> success =
     StyleAnimationValue::ExtractComputedValue(aProperty,
                                               styleContextWithoutAnimation,
                                               result);
   MOZ_ASSERT(success, "Should be able to extract computed animation value");
   MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue");
 
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -1036,18 +1036,18 @@ CSSAnimationBuilder::GetComputedValue(ns
   nsCSSValue result;
   StyleAnimationValue computedValue;
 
   if (!mStyleWithoutAnimation) {
     MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
                "ServoStyleSet should not use nsAnimationManager for "
                "animations");
     mStyleWithoutAnimation = aPresContext->StyleSet()->AsGecko()->
-      ResolveStyleWithoutAnimation(mTarget, mStyleContext,
-                                   eRestyle_AllHintsWithAnimations);
+      ResolveStyleByRemovingAnimation(mTarget, mStyleContext,
+                                      eRestyle_AllHintsWithAnimations);
   }
 
   if (StyleAnimationValue::ExtractComputedValue(aProperty,
                                                 mStyleWithoutAnimation,
                                                 computedValue)) {
     DebugOnly<bool> uncomputeResult =
       StyleAnimationValue::UncomputeValue(aProperty, Move(computedValue),
                                           result);
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -1346,19 +1346,20 @@ nsStyleSet::ResolveStyleFor(Element* aEl
 {
   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
                                aElement->OwnerDoc());
   InitStyleScopes(treeContext, aElement);
   return ResolveStyleFor(aElement, aParentContext, treeContext);
 }
 
 already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveStyleFor(Element* aElement,
-                            nsStyleContext* aParentContext,
-                            TreeMatchContext& aTreeMatchContext)
+nsStyleSet::ResolveStyleForInternal(Element* aElement,
+                                    nsStyleContext* aParentContext,
+                                    TreeMatchContext& aTreeMatchContext,
+                                    AnimationFlag aAnimationFlag)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
   NS_ASSERTION(aElement, "aElement must not be null");
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   aTreeMatchContext.ResetForUnvisitedMatching();
   ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker,
                                 aTreeMatchContext);
@@ -1372,17 +1373,17 @@ nsStyleSet::ResolveStyleFor(Element* aEl
   if (aTreeMatchContext.HaveRelevantLink()) {
     aTreeMatchContext.ResetForVisitedMatching();
     ruleWalker.Reset();
     FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
               &ruleWalker);
     visitedRuleNode = ruleWalker.CurrentNode();
   }
 
-  uint32_t flags = eDoAnimation;
+  uint32_t flags = (aAnimationFlag == eWithAnimation) ? eDoAnimation : eNoFlags;
   if (nsCSSRuleProcessor::IsLink(aElement)) {
     flags |= eIsLink;
   }
   if (nsCSSRuleProcessor::GetContentState(aElement, aTreeMatchContext).
                             HasState(NS_EVENT_STATE_VISITED)) {
     flags |= eIsVisitedLink;
   }
   if (aTreeMatchContext.mSkippingParentDisplayBasedStyleFixup) {
@@ -1390,16 +1391,27 @@ nsStyleSet::ResolveStyleFor(Element* aEl
   }
 
   return GetContext(aParentContext, ruleNode, visitedRuleNode,
                     nullptr, CSSPseudoElementType::NotPseudo,
                     aElement, flags);
 }
 
 already_AddRefed<nsStyleContext>
+nsStyleSet::ResolveStyleFor(Element* aElement,
+                            nsStyleContext* aParentContext,
+                            TreeMatchContext& aTreeMatchContext)
+{
+  return ResolveStyleForInternal(aElement,
+                                 aParentContext,
+                                 aTreeMatchContext,
+                                 eWithAnimation);
+}
+
+already_AddRefed<nsStyleContext>
 nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
                                  const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   // FIXME: Perhaps this should be passed in, but it probably doesn't
   // matter.
@@ -1743,19 +1755,19 @@ nsStyleSet::ResolveStyleWithReplacement(
   }
 
   return GetContext(aNewParentContext, ruleNode, visitedRuleNode,
                     aOldStyleContext->GetPseudo(), pseudoType,
                     elementForAnimation, flags);
 }
 
 already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveStyleWithoutAnimation(dom::Element* aTarget,
-                                         nsStyleContext* aStyleContext,
-                                         nsRestyleHint aWhichToRemove)
+nsStyleSet::ResolveStyleByRemovingAnimation(dom::Element* aTarget,
+                                            nsStyleContext* aStyleContext,
+                                            nsRestyleHint aWhichToRemove)
 {
 #ifdef DEBUG
   CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
 #endif
   MOZ_ASSERT(pseudoType == CSSPseudoElementType::NotPseudo ||
              pseudoType == CSSPseudoElementType::before ||
              pseudoType == CSSPseudoElementType::after,
              "unexpected type for animations");
@@ -1773,16 +1785,44 @@ nsStyleSet::ResolveStyleWithoutAnimation
                                 eSkipStartingAnimations);
 
   restyleManager->SetSkipAnimationRules(oldSkipAnimationRules);
 
   return result.forget();
 }
 
 already_AddRefed<nsStyleContext>
+nsStyleSet::ResolveStyleWithoutAnimation(Element* aTarget,
+                                         nsStyleContext* aParentContext)
+{
+  RestyleManager* restyleManager = PresContext()->RestyleManager()->AsGecko();
+
+  TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
+                               aTarget->OwnerDoc());
+  InitStyleScopes(treeContext, aTarget);
+
+  bool oldSkipAnimationRules = restyleManager->SkipAnimationRules();
+  restyleManager->SetSkipAnimationRules(true);
+
+  // Here we can call ResolveStyleForInternal() instead of
+  // ResolveStyleWithReplacement() since we don't need any animation rules
+  // (CSS Animations, Transitions and script animations). That's because
+  // EffectCompositor::GetAnimationRule() skips all of animations rules if
+  // SkipAnimationRules flag is true.
+  RefPtr<nsStyleContext> result = ResolveStyleForInternal(aTarget,
+                                                          aParentContext,
+                                                          treeContext,
+                                                          eWithoutAnimation);
+
+  restyleManager->SetSkipAnimationRules(oldSkipAnimationRules);
+
+  return result.forget();
+}
+
+already_AddRefed<nsStyleContext>
 nsStyleSet::ResolveStyleForText(nsIContent* aTextNode,
                                 nsStyleContext* aParentContext)
 {
   MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
   return GetContext(aParentContext, mRuleTree, nullptr,
                     nsCSSAnonBoxes::mozText,
                     CSSPseudoElementType::AnonBox, nullptr, eNoFlags);
 }
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -176,19 +176,25 @@ class nsStyleSet final
                               nsRestyleHint aReplacements,
                               uint32_t aFlags = 0);
 
   // Resolve style by returning a style context with the specified
   // animation data removed.  It is allowable to remove all animation
   // data with eRestyle_AllHintsWithAnimations, or by using any other
   // hints that are allowed by ResolveStyleWithReplacement.
   already_AddRefed<nsStyleContext>
-    ResolveStyleWithoutAnimation(mozilla::dom::Element* aElement,
-                                 nsStyleContext* aStyleContext,
-                                 nsRestyleHint aWhichToRemove);
+    ResolveStyleByRemovingAnimation(mozilla::dom::Element* aElement,
+                                    nsStyleContext* aStyleContext,
+                                    nsRestyleHint aWhichToRemove);
+
+  // Similar to the above, but resolving style without all animation data in
+  // the first place.
+  already_AddRefed<nsStyleContext>
+    ResolveStyleWithoutAnimation(mozilla::dom::Element* aTarget,
+                                 nsStyleContext* aParentContext);
 
   // Get a style context for a text node (which no rules will match).
   //
   // The returned style context will have nsCSSAnonBoxes::mozText as its pseudo.
   //
   // (Perhaps mozText should go away and we shouldn't even create style
   // contexts for such content nodes, when text-combine-upright is not
   // present.  However, not doing any rule matching for them is a first step.)
@@ -521,16 +527,26 @@ private:
   GetContext(nsStyleContext* aParentContext,
              nsRuleNode* aRuleNode,
              nsRuleNode* aVisitedRuleNode,
              nsIAtom* aPseudoTag,
              mozilla::CSSPseudoElementType aPseudoType,
              mozilla::dom::Element* aElementForAnimation,
              uint32_t aFlags);
 
+  enum AnimationFlag {
+    eWithAnimation,
+    eWithoutAnimation,
+  };
+  already_AddRefed<nsStyleContext>
+  ResolveStyleForInternal(mozilla::dom::Element* aElement,
+                          nsStyleContext* aParentContext,
+                          TreeMatchContext& aTreeMatchContext,
+                          AnimationFlag aAnimationFlag);
+
   nsPresContext* PresContext() { return mRuleTree->PresContext(); }
 
   // The sheets in each array in mSheets are stored with the most significant
   // sheet last.
   // The arrays for ePresHintSheet, eStyleAttrSheet, eTransitionSheet,
   // eAnimationSheet and eSVGAttrAnimationSheet are always empty.
   // (FIXME:  We should reduce the storage needed for them.)
   mozilla::EnumeratedArray<mozilla::SheetType, mozilla::SheetType::Count,
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -553,18 +553,18 @@ nsTransitionManager::StyleContextChanged
   // not stopping or starting right now.
   RefPtr<nsStyleContext> afterChangeStyle;
   if (collection) {
     MOZ_ASSERT(mPresContext->StyleSet()->IsGecko(),
                "ServoStyleSets should not use nsTransitionManager "
                "for transitions");
     nsStyleSet* styleSet = mPresContext->StyleSet()->AsGecko();
     afterChangeStyle =
-      styleSet->ResolveStyleWithoutAnimation(aElement, newStyleContext,
-                                             eRestyle_CSSTransitions);
+      styleSet->ResolveStyleByRemovingAnimation(aElement, newStyleContext,
+                                                eRestyle_CSSTransitions);
   } else {
     afterChangeStyle = newStyleContext;
   }
 
   nsAutoAnimationMutationBatch mb(aElement->OwnerDoc());
 
   DebugOnly<bool> startedAny = false;
   // We don't have to update transitions if display:none, although we will