Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef NS_SMILANIMATIONCONTROLLER_H_
8 : #define NS_SMILANIMATIONCONTROLLER_H_
9 :
10 : #include "mozilla/Attributes.h"
11 : #include "nsAutoPtr.h"
12 : #include "nsCOMPtr.h"
13 : #include "nsTArray.h"
14 : #include "nsITimer.h"
15 : #include "nsTHashtable.h"
16 : #include "nsHashKeys.h"
17 : #include "nsSMILTimeContainer.h"
18 : #include "nsSMILCompositorTable.h"
19 : #include "nsSMILMilestone.h"
20 : #include "nsRefreshDriver.h"
21 :
22 : struct nsSMILTargetIdentifier;
23 : class nsIDocument;
24 :
25 : namespace mozilla {
26 : class RestyleTracker;
27 : namespace dom {
28 : class Element;
29 : class SVGAnimationElement;
30 : } // namespace dom
31 : } // namespace mozilla
32 :
33 : //----------------------------------------------------------------------
34 : // nsSMILAnimationController
35 : //
36 : // The animation controller maintains the animation timer and determines the
37 : // sample times and sample rate for all SMIL animations in a document. There is
38 : // at most one animation controller per nsDocument so that frame-rate tuning can
39 : // be performed at a document-level.
40 : //
41 : // The animation controller can contain many child time containers (timed
42 : // document root objects) which may correspond to SVG document fragments within
43 : // a compound document. These time containers can be paused individually or
44 : // here, at the document level.
45 : //
46 : class nsSMILAnimationController final : public nsSMILTimeContainer,
47 : public nsARefreshObserver
48 : {
49 : public:
50 : explicit nsSMILAnimationController(nsIDocument* aDoc);
51 :
52 : // Clears mDocument pointer. (Called by our nsIDocument when it's going away)
53 : void Disconnect();
54 :
55 : // nsSMILContainer
56 : virtual void Pause(uint32_t aType) override;
57 : virtual void Resume(uint32_t aType) override;
58 : virtual nsSMILTime GetParentTime() const override;
59 :
60 : // nsARefreshObserver
61 : NS_IMETHOD_(MozExternalRefCountType) AddRef() override;
62 : NS_IMETHOD_(MozExternalRefCountType) Release() override;
63 :
64 : virtual void WillRefresh(mozilla::TimeStamp aTime) override;
65 :
66 : // Methods for registering and enumerating animation elements
67 : void RegisterAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
68 : void UnregisterAnimationElement(mozilla::dom::SVGAnimationElement* aAnimationElement);
69 :
70 : // Methods for resampling all animations
71 : // (A resample performs the same operations as a sample but doesn't advance
72 : // the current time and doesn't check if the container is paused)
73 : // This will flush pending style changes for the document.
74 57 : void Resample() { DoSample(false); }
75 :
76 57 : void SetResampleNeeded()
77 : {
78 57 : if (!mRunningSample && !mResampleNeeded) {
79 57 : FlagDocumentNeedsFlush();
80 57 : mResampleNeeded = true;
81 : }
82 57 : }
83 :
84 : // This will flush pending style changes for the document.
85 178 : void FlushResampleRequests()
86 : {
87 178 : if (!mResampleNeeded)
88 121 : return;
89 :
90 57 : Resample();
91 : }
92 :
93 : // Methods for handling page transitions
94 : void OnPageShow();
95 : void OnPageHide();
96 :
97 : // Methods for supporting cycle-collection
98 : void Traverse(nsCycleCollectionTraversalCallback* aCallback);
99 : void Unlink();
100 :
101 : // Methods for relaying the availability of the refresh driver
102 : void NotifyRefreshDriverCreated(nsRefreshDriver* aRefreshDriver);
103 : void NotifyRefreshDriverDestroying(nsRefreshDriver* aRefreshDriver);
104 :
105 : // Helper to check if we have any animation elements at all
106 21 : bool HasRegisteredAnimations() const
107 : {
108 21 : return mAnimationElementTable.Count() != 0;
109 : }
110 :
111 : void AddStyleUpdatesTo(mozilla::RestyleTracker& aTracker);
112 30 : bool MightHavePendingStyleUpdates() const
113 : {
114 30 : return mMightHavePendingStyleUpdates;
115 : }
116 :
117 : bool PreTraverse();
118 : bool PreTraverseInSubtree(mozilla::dom::Element* aRoot);
119 :
120 : protected:
121 : ~nsSMILAnimationController();
122 :
123 : // Typedefs
124 : typedef nsPtrHashKey<nsSMILTimeContainer> TimeContainerPtrKey;
125 : typedef nsTHashtable<TimeContainerPtrKey> TimeContainerHashtable;
126 : typedef nsPtrHashKey<mozilla::dom::SVGAnimationElement> AnimationElementPtrKey;
127 : typedef nsTHashtable<AnimationElementPtrKey> AnimationElementHashtable;
128 :
129 : // Returns mDocument's refresh driver, if it's got one.
130 : nsRefreshDriver* GetRefreshDriver();
131 :
132 : // Methods for controlling whether we're sampling
133 : void StartSampling(nsRefreshDriver* aRefreshDriver);
134 : void StopSampling(nsRefreshDriver* aRefreshDriver);
135 :
136 : // Wrapper for StartSampling that defers if no animations are registered.
137 : void MaybeStartSampling(nsRefreshDriver* aRefreshDriver);
138 :
139 : // Sample-related callbacks and implementation helpers
140 : virtual void DoSample() override;
141 : void DoSample(bool aSkipUnchangedContainers);
142 :
143 : void RewindElements();
144 :
145 : void DoMilestoneSamples();
146 :
147 : static void SampleTimedElement(mozilla::dom::SVGAnimationElement* aElement,
148 : TimeContainerHashtable* aActiveContainers);
149 :
150 : static void AddAnimationToCompositorTable(
151 : mozilla::dom::SVGAnimationElement* aElement,
152 : nsSMILCompositorTable* aCompositorTable,
153 : bool& aStyleFlushNeeded);
154 :
155 : static bool GetTargetIdentifierForAnimation(
156 : mozilla::dom::SVGAnimationElement* aAnimElem, nsSMILTargetIdentifier& aResult);
157 :
158 : // Methods for adding/removing time containers
159 : virtual nsresult AddChild(nsSMILTimeContainer& aChild) override;
160 : virtual void RemoveChild(nsSMILTimeContainer& aChild) override;
161 :
162 : void FlagDocumentNeedsFlush();
163 :
164 : // Members
165 : nsAutoRefCnt mRefCnt;
166 : NS_DECL_OWNINGTHREAD
167 :
168 : AnimationElementHashtable mAnimationElementTable;
169 : TimeContainerHashtable mChildContainerTable;
170 : mozilla::TimeStamp mCurrentSampleTime;
171 : mozilla::TimeStamp mStartTime;
172 :
173 : // Average time between samples from the refresh driver. This is used to
174 : // detect large unexpected gaps between samples such as can occur when the
175 : // computer sleeps. The nature of the SMIL model means that catching up these
176 : // large gaps can be expensive as, for example, many events may need to be
177 : // dispatched for the intervening time when no samples were received.
178 : //
179 : // In such cases, we ignore the intervening gap and continue sampling from
180 : // when we were expecting the next sample to arrive.
181 : //
182 : // Note that we only do this for SMIL and not CSS transitions (which doesn't
183 : // have so much work to do to catch up) nor scripted animations (which expect
184 : // animation time to follow real time).
185 : //
186 : // This behaviour does not affect pausing (since we're not *expecting* any
187 : // samples then) nor seeking (where the SMIL model behaves somewhat
188 : // differently such as not dispatching events).
189 : nsSMILTime mAvgTimeBetweenSamples;
190 :
191 : bool mResampleNeeded;
192 : // If we're told to start sampling but there are no animation elements we just
193 : // record the time, set the following flag, and then wait until we have an
194 : // animation element. Then we'll reset this flag and actually start sampling.
195 : bool mDeferredStartSampling;
196 : bool mRunningSample;
197 :
198 : // Are we registered with our document's refresh driver?
199 : bool mRegisteredWithRefreshDriver;
200 :
201 : // Have we updated animated values without adding them to the restyle tracker?
202 : bool mMightHavePendingStyleUpdates;
203 :
204 : // Store raw ptr to mDocument. It owns the controller, so controller
205 : // shouldn't outlive it
206 : nsIDocument* mDocument;
207 :
208 : // Contains compositors used in our last sample. We keep this around
209 : // so we can detect when an element/attribute used to be animated,
210 : // but isn't anymore for some reason. (e.g. if its <animate> element is
211 : // removed or retargeted)
212 : nsAutoPtr<nsSMILCompositorTable> mLastCompositorTable;
213 : };
214 :
215 : #endif // NS_SMILANIMATIONCONTROLLER_H_
|