From a7d2fa0411a5a8a571ac52114756c25d5c98b165 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Wed, 26 Apr 2017 13:00:11 +0900 Subject: [PATCH] Bug 1355348 - Add SMIL restyles in the stylo pretraverse; r=heycam MozReview-Commit-ID: mwjkKr6wsr --HG-- extra : rebase_source : 23324e128041f6d190312958dab093da382863f3 --- dom/smil/nsSMILAnimationController.cpp | 63 ++++++++++++++++++++++++++ dom/smil/nsSMILAnimationController.h | 4 ++ layout/style/ServoStyleSet.cpp | 14 ++++++ 3 files changed, 81 insertions(+) diff --git a/dom/smil/nsSMILAnimationController.cpp b/dom/smil/nsSMILAnimationController.cpp index 590b84877cfe..61ed29eb50a5 100644 --- a/dom/smil/nsSMILAnimationController.cpp +++ b/dom/smil/nsSMILAnimationController.cpp @@ -11,6 +11,8 @@ #include "mozilla/AutoRestore.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/SVGAnimationElement.h" +#include "mozilla/RestyleManagerInlines.h" +#include "nsContentUtils.h" #include "nsCSSProps.h" #include "nsIDocument.h" #include "nsIPresShell.h" @@ -723,6 +725,67 @@ nsSMILAnimationController::AddStyleUpdatesTo(RestyleTracker& aTracker) mMightHavePendingStyleUpdates = false; } +bool +nsSMILAnimationController::PreTraverse() +{ + return PreTraverseInSubtree(nullptr); +} + +bool +nsSMILAnimationController::PreTraverseInSubtree(Element* aRoot) +{ + MOZ_ASSERT(NS_IsMainThread()); + + if (!mMightHavePendingStyleUpdates) { + return false; + } + + nsIPresShell* shell = mDocument->GetShell(); + if (!shell) { + return false; + } + + nsPresContext* context = shell->GetPresContext(); + if (!context) { + return false; + } + MOZ_ASSERT(context->RestyleManager()->IsServo(), + "PreTraverse should only be called for the servo style system"); + + bool foundElementsNeedingRestyle = false; + for (auto iter = mAnimationElementTable.Iter(); !iter.Done(); iter.Next()) { + SVGAnimationElement* animElement = iter.Get()->GetKey(); + + nsSMILTargetIdentifier key; + if (!GetTargetIdentifierForAnimation(animElement, key)) { + // Something's wrong/missing about animation's target; skip this animation + continue; + } + + // Ignore restyles that aren't in the flattened tree subtree rooted at + // aRoot. + if (aRoot && + !nsContentUtils::ContentIsFlattenedTreeDescendantOf(key.mElement, + aRoot)) { + continue; + } + + context->RestyleManager()->AsServo()-> + PostRestyleEventForAnimations(key.mElement, + eRestyle_StyleAttribute_Animations); + + foundElementsNeedingRestyle = true; + } + + // Only clear the mMightHavePendingStyleUpdates flag if we definitely posted + // all restyles. + if (!aRoot) { + mMightHavePendingStyleUpdates = false; + } + + return foundElementsNeedingRestyle; +} + //---------------------------------------------------------------------- // Add/remove child time containers diff --git a/dom/smil/nsSMILAnimationController.h b/dom/smil/nsSMILAnimationController.h index 9c565b78b394..b880575966e5 100644 --- a/dom/smil/nsSMILAnimationController.h +++ b/dom/smil/nsSMILAnimationController.h @@ -25,6 +25,7 @@ class nsIDocument; namespace mozilla { class RestyleTracker; namespace dom { +class Element; class SVGAnimationElement; } // namespace dom } // namespace mozilla @@ -113,6 +114,9 @@ public: return mMightHavePendingStyleUpdates; } + bool PreTraverse(); + bool PreTraverseInSubtree(mozilla::dom::Element* aRoot); + protected: ~nsSMILAnimationController(); diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index 899477dc789b..fc2f55b3ec3f 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -21,6 +21,7 @@ #include "nsHTMLStyleSheet.h" #include "nsIDocumentInlines.h" #include "nsPrintfCString.h" +#include "nsSMILAnimationController.h" #include "nsStyleContext.h" #include "nsStyleSet.h" @@ -263,10 +264,18 @@ ServoStyleSet::PreTraverse(Element* aRoot) // Process animation stuff that we should avoid doing during the parallel // traversal. + nsSMILAnimationController* smilController = + mPresContext->Document()->GetAnimationController(); if (aRoot) { mPresContext->EffectCompositor()->PreTraverseInSubtree(aRoot); + if (smilController) { + smilController->PreTraverseInSubtree(aRoot); + } } else { mPresContext->EffectCompositor()->PreTraverse(); + if (smilController) { + smilController->PreTraverse(); + } } } @@ -295,6 +304,11 @@ ServoStyleSet::PrepareAndTraverseSubtree(RawGeckoElementBorrowed aRoot, // If there are still animation restyles needed, trigger a second traversal to // update CSS animations or transitions' styles. + // + // We don't need to do this for SMIL since SMIL only updates its animation + // values once at the begin of a tick. As a result, even if the previous + // traversal caused, for example, the font-size to change, the SMIL style + // won't be updated until the next tick anyway. EffectCompositor* compositor = mPresContext->EffectCompositor(); if (forReconstruct ? compositor->PreTraverseInSubtree(root) : compositor->PreTraverse()) {