1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Mozilla SMIL module.
16 : *
17 : * The Initial Developer of the Original Code is Brian Birtles.
18 : * Portions created by the Initial Developer are Copyright (C) 2008
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Brian Birtles <birtles@gmail.com>
23 : * Daniel Holbert <dholbert@mozilla.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef NS_SMILANIMATIONCONTROLLER_H_
40 : #define NS_SMILANIMATIONCONTROLLER_H_
41 :
42 : #include "nsAutoPtr.h"
43 : #include "nsCOMPtr.h"
44 : #include "nsTArray.h"
45 : #include "nsITimer.h"
46 : #include "nsTHashtable.h"
47 : #include "nsHashKeys.h"
48 : #include "nsSMILTimeContainer.h"
49 : #include "nsSMILCompositorTable.h"
50 : #include "nsSMILMilestone.h"
51 : #include "nsRefreshDriver.h"
52 :
53 : struct nsSMILTargetIdentifier;
54 : class nsISMILAnimationElement;
55 : class nsIDocument;
56 :
57 : //----------------------------------------------------------------------
58 : // nsSMILAnimationController
59 : //
60 : // The animation controller maintains the animation timer and determines the
61 : // sample times and sample rate for all SMIL animations in a document. There is
62 : // at most one animation controller per nsDocument so that frame-rate tuning can
63 : // be performed at a document-level.
64 : //
65 : // The animation controller can contain many child time containers (timed
66 : // document root objects) which may correspond to SVG document fragments within
67 : // a compound document. These time containers can be paused individually or
68 : // here, at the document level.
69 : //
70 : class nsSMILAnimationController : public nsSMILTimeContainer,
71 : public nsARefreshObserver
72 : {
73 : public:
74 : nsSMILAnimationController(nsIDocument* aDoc);
75 : ~nsSMILAnimationController();
76 :
77 : // Clears mDocument pointer. (Called by our nsIDocument when it's going away)
78 : void Disconnect();
79 :
80 : // nsSMILContainer
81 : virtual void Pause(PRUint32 aType);
82 : virtual void Resume(PRUint32 aType);
83 : virtual nsSMILTime GetParentTime() const;
84 :
85 : // nsARefreshObserver
86 : NS_IMETHOD_(nsrefcnt) AddRef();
87 : NS_IMETHOD_(nsrefcnt) Release();
88 :
89 : virtual void WillRefresh(mozilla::TimeStamp aTime);
90 :
91 : // Methods for registering and enumerating animation elements
92 : void RegisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
93 : void UnregisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
94 :
95 : // Methods for resampling all animations
96 : // (A resample performs the same operations as a sample but doesn't advance
97 : // the current time and doesn't check if the container is paused)
98 : // This will flush pending style changes for the document.
99 0 : void Resample() { DoSample(false); }
100 :
101 0 : void SetResampleNeeded()
102 : {
103 0 : if (!mRunningSample) {
104 0 : if (!mResampleNeeded) {
105 0 : FlagDocumentNeedsFlush();
106 : }
107 0 : mResampleNeeded = true;
108 : }
109 0 : }
110 :
111 : // This will flush pending style changes for the document.
112 0 : void FlushResampleRequests()
113 : {
114 0 : if (!mResampleNeeded)
115 0 : return;
116 :
117 0 : Resample();
118 : }
119 :
120 : // Methods for handling page transitions
121 : void OnPageShow();
122 : void OnPageHide();
123 :
124 : // Methods for supporting cycle-collection
125 : void Traverse(nsCycleCollectionTraversalCallback* aCallback);
126 : void Unlink();
127 :
128 : // Methods for relaying the availability of the refresh driver
129 : void NotifyRefreshDriverCreated(nsRefreshDriver* aRefreshDriver);
130 : void NotifyRefreshDriverDestroying(nsRefreshDriver* aRefreshDriver);
131 :
132 : // Helper to check if we have any animation elements at all
133 0 : bool HasRegisteredAnimations()
134 0 : { return mAnimationElementTable.Count() != 0; }
135 :
136 : protected:
137 : // Typedefs
138 : typedef nsPtrHashKey<nsSMILTimeContainer> TimeContainerPtrKey;
139 : typedef nsTHashtable<TimeContainerPtrKey> TimeContainerHashtable;
140 : typedef nsPtrHashKey<nsISMILAnimationElement> AnimationElementPtrKey;
141 : typedef nsTHashtable<AnimationElementPtrKey> AnimationElementHashtable;
142 :
143 : struct SampleTimeContainerParams
144 : {
145 : TimeContainerHashtable* mActiveContainers;
146 : bool mSkipUnchangedContainers;
147 : };
148 :
149 : struct SampleAnimationParams
150 : {
151 : TimeContainerHashtable* mActiveContainers;
152 : nsSMILCompositorTable* mCompositorTable;
153 : };
154 :
155 : struct GetMilestoneElementsParams
156 : {
157 : nsTArray<nsRefPtr<nsISMILAnimationElement> > mElements;
158 : nsSMILMilestone mMilestone;
159 : };
160 :
161 : // Cycle-collection implementation helpers
162 : PR_STATIC_CALLBACK(PLDHashOperator) CompositorTableEntryTraverse(
163 : nsSMILCompositor* aCompositor, void* aArg);
164 :
165 : // Returns mDocument's refresh driver, if it's got one.
166 : nsRefreshDriver* GetRefreshDriver();
167 :
168 : // Methods for controlling whether we're sampling
169 : void StartSampling(nsRefreshDriver* aRefreshDriver);
170 : void StopSampling(nsRefreshDriver* aRefreshDriver);
171 :
172 : // Wrapper for StartSampling that defers if no animations are registered.
173 : void MaybeStartSampling(nsRefreshDriver* aRefreshDriver);
174 :
175 : // Sample-related callbacks and implementation helpers
176 : virtual void DoSample();
177 : void DoSample(bool aSkipUnchangedContainers);
178 :
179 : void RewindElements();
180 : PR_STATIC_CALLBACK(PLDHashOperator) RewindNeeded(
181 : TimeContainerPtrKey* aKey, void* aData);
182 : PR_STATIC_CALLBACK(PLDHashOperator) RewindAnimation(
183 : AnimationElementPtrKey* aKey, void* aData);
184 : PR_STATIC_CALLBACK(PLDHashOperator) ClearRewindNeeded(
185 : TimeContainerPtrKey* aKey, void* aData);
186 :
187 : void DoMilestoneSamples();
188 : PR_STATIC_CALLBACK(PLDHashOperator) GetNextMilestone(
189 : TimeContainerPtrKey* aKey, void* aData);
190 : PR_STATIC_CALLBACK(PLDHashOperator) GetMilestoneElements(
191 : TimeContainerPtrKey* aKey, void* aData);
192 :
193 : PR_STATIC_CALLBACK(PLDHashOperator) SampleTimeContainer(
194 : TimeContainerPtrKey* aKey, void* aData);
195 : PR_STATIC_CALLBACK(PLDHashOperator) SampleAnimation(
196 : AnimationElementPtrKey* aKey, void* aData);
197 : static void SampleTimedElement(nsISMILAnimationElement* aElement,
198 : TimeContainerHashtable* aActiveContainers);
199 : static void AddAnimationToCompositorTable(
200 : nsISMILAnimationElement* aElement, nsSMILCompositorTable* aCompositorTable);
201 : static bool GetTargetIdentifierForAnimation(
202 : nsISMILAnimationElement* aAnimElem, nsSMILTargetIdentifier& aResult);
203 :
204 : // Methods for adding/removing time containers
205 : virtual nsresult AddChild(nsSMILTimeContainer& aChild);
206 : virtual void RemoveChild(nsSMILTimeContainer& aChild);
207 :
208 : void FlagDocumentNeedsFlush();
209 :
210 : // Members
211 : nsAutoRefCnt mRefCnt;
212 : NS_DECL_OWNINGTHREAD
213 :
214 : AnimationElementHashtable mAnimationElementTable;
215 : TimeContainerHashtable mChildContainerTable;
216 : mozilla::TimeStamp mCurrentSampleTime;
217 : mozilla::TimeStamp mStartTime;
218 :
219 : // Average time between samples from the refresh driver. This is used to
220 : // detect large unexpected gaps between samples such as can occur when the
221 : // computer sleeps. The nature of the SMIL model means that catching up these
222 : // large gaps can be expensive as, for example, many events may need to be
223 : // dispatched for the intervening time when no samples were received.
224 : //
225 : // In such cases, we ignore the intervening gap and continue sampling from
226 : // when we were expecting the next sample to arrive.
227 : //
228 : // Note that we only do this for SMIL and not CSS transitions (which doesn't
229 : // have so much work to do to catch up) nor scripted animations (which expect
230 : // animation time to follow real time).
231 : //
232 : // This behaviour does not affect pausing (since we're not *expecting* any
233 : // samples then) nor seeking (where the SMIL model behaves somewhat
234 : // differently such as not dispatching events).
235 : nsSMILTime mAvgTimeBetweenSamples;
236 :
237 : bool mResampleNeeded;
238 : // If we're told to start sampling but there are no animation elements we just
239 : // record the time, set the following flag, and then wait until we have an
240 : // animation element. Then we'll reset this flag and actually start sampling.
241 : bool mDeferredStartSampling;
242 : bool mRunningSample;
243 :
244 : // Store raw ptr to mDocument. It owns the controller, so controller
245 : // shouldn't outlive it
246 : nsIDocument* mDocument;
247 :
248 : // Contains compositors used in our last sample. We keep this around
249 : // so we can detect when an element/attribute used to be animated,
250 : // but isn't anymore for some reason. (e.g. if its <animate> element is
251 : // removed or retargeted)
252 : nsAutoPtr<nsSMILCompositorTable> mLastCompositorTable;
253 : };
254 :
255 : #endif // NS_SMILANIMATIONCONTROLLER_H_
|