diff --git a/dom/animation/AnimationTimeline.h b/dom/animation/AnimationTimeline.h index 7163d4350..150f8f5bc 100644 --- a/dom/animation/AnimationTimeline.h +++ b/dom/animation/AnimationTimeline.h @@ -94,6 +94,17 @@ public: */ virtual void NotifyAnimationUpdated(Animation& aAnimation); + /** + * Returns true if any CSS animations, CSS transitions or Web animations are + * currently associated with this timeline. As soon as an animation is + * applied to an element it is associated with the timeline even if it has a + * delayed start, so this includes animations that may not be active for some + * time. + */ + bool HasAnimations() const { + return !mAnimations.IsEmpty(); + } + void RemoveAnimation(Animation* aAnimation); protected: diff --git a/image/SVGDocumentWrapper.cpp b/image/SVGDocumentWrapper.cpp index 31b5c3b85..5d73e1fd2 100644 --- a/image/SVGDocumentWrapper.cpp +++ b/image/SVGDocumentWrapper.cpp @@ -5,7 +5,9 @@ #include "SVGDocumentWrapper.h" +#include "mozilla/dom/DocumentTimeline.h" #include "mozilla/dom/Element.h" +#include "nsDOMNavigationTiming.h" #include "nsICategoryManager.h" #include "nsIChannel.h" #include "nsIContentViewer.h" @@ -115,8 +117,21 @@ bool SVGDocumentWrapper::IsAnimated() { nsIDocument* doc = mViewer->GetDocument(); - return doc && doc->HasAnimationController() && - doc->GetAnimationController()->HasRegisteredAnimations(); + if (!doc) { + return false; + } + if (doc->Timeline()->HasAnimations()) { + // CSS animations (technically HasAnimations() also checks for CSS + // transitions and Web animations but since SVG-as-an-image doesn't run + // script they will never run in the document that we wrap). + return true; + } + if (doc->HasAnimationController() && + doc->GetAnimationController()->HasRegisteredAnimations()) { + // SMIL animations + return true; + } + return false; } void @@ -330,6 +345,20 @@ SVGDocumentWrapper::SetupViewer(nsIRequest* aRequest, NS_ENSURE_TRUE(viewer, NS_ERROR_UNEXPECTED); + // Create a navigation time object and pass it to the SVG document through + // the viewer. + // The timeline(DocumentTimeline, used in CSS animation) of this SVG + // document needs this navigation timing object for time computation, such + // as to calculate current time stamp based on the start time of navigation + // time object. + // + // For a root document, DocShell would do these sort of things + // automatically. Since there is no DocShell for this wrapped SVG document, + // we must set it up manually. + RefPtr timing = new nsDOMNavigationTiming(); + timing->NotifyNavigationStart(); + viewer->SetNavigationTiming(timing); + nsCOMPtr parser = do_QueryInterface(listener); NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED); diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index 0703f18c2..e7a46712f 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -524,6 +524,12 @@ VectorImage::RequestRefresh(const TimeStamp& aTime) return; } + PendingAnimationTracker* tracker = + mSVGDocumentWrapper->GetDocument()->GetPendingAnimationTracker(); + if (tracker && ShouldAnimate()) { + tracker->TriggerPendingAnimationsOnNextTick(aTime); + } + EvaluateAnimation(); mSVGDocumentWrapper->TickRefreshDriver(); diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 91d9932d5..1cf03e3b5 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1619,7 +1619,7 @@ already_AddRefed nsDisplayList::PaintRoot(nsDisplayListBuilder* aB nsIFrame* frame = aBuilder->RootReferenceFrame(); nsPresContext* presContext = frame->PresContext(); - nsIPresShell* presShell = presContext->GetPresShell(); + nsIPresShell* presShell = presContext->PresShell(); nsRootPresContext* rootPresContext = presContext->GetRootPresContext(); NotifySubDocInvalidationFunc computeInvalidFunc = @@ -1646,10 +1646,7 @@ already_AddRefed nsDisplayList::PaintRoot(nsDisplayListBuilder* aB BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this, containerParameters, nullptr); - nsIDocument* document = nullptr; - if (presShell) { - document = presShell->GetDocument(); - } + nsIDocument* document = presShell->GetDocument(); if (!root) { layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);