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) 2009
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Brian Birtles <birtles@gmail.com>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef NS_SMILTIMECONTAINER_H_
39 : #define NS_SMILTIMECONTAINER_H_
40 :
41 : #include "nscore.h"
42 : #include "nsSMILTypes.h"
43 : #include "nsTPriorityQueue.h"
44 : #include "nsAutoPtr.h"
45 : #include "nsISMILAnimationElement.h"
46 : #include "nsSMILMilestone.h"
47 :
48 : class nsSMILTimeValue;
49 :
50 : //----------------------------------------------------------------------
51 : // nsSMILTimeContainer
52 : //
53 : // Common base class for a time base that can be paused, resumed, and sampled.
54 : //
55 : class nsSMILTimeContainer
56 : {
57 : public:
58 : nsSMILTimeContainer();
59 : virtual ~nsSMILTimeContainer();
60 :
61 : /*
62 : * Pause request types.
63 : */
64 : enum {
65 : PAUSE_BEGIN = 1, // Paused because timeline has yet to begin.
66 : PAUSE_SCRIPT = 2, // Paused by script.
67 : PAUSE_PAGEHIDE = 4, // Paused because our doc is hidden.
68 : PAUSE_USERPREF = 8, // Paused because animations are disabled in prefs.
69 : PAUSE_IMAGE = 16 // Paused becuase we're in an image that's suspended.
70 : };
71 :
72 : /*
73 : * Cause the time container to record its begin time.
74 : */
75 : void Begin();
76 :
77 : /*
78 : * Pause this time container
79 : *
80 : * @param aType The source of the pause request. Successive calls to Pause
81 : * with the same aType will be ignored. The container will remain paused until
82 : * each call to Pause of a given aType has been matched by at least one call
83 : * to Resume with the same aType.
84 : */
85 : virtual void Pause(PRUint32 aType);
86 :
87 : /*
88 : * Resume this time container
89 : *
90 : * param @aType The source of the resume request. Clears the pause flag for
91 : * this particular type of pause request. When all pause flags have been
92 : * cleared the time container will be resumed.
93 : */
94 : virtual void Resume(PRUint32 aType);
95 :
96 : /**
97 : * Returns true if this time container is paused by the specified type.
98 : * Note that the time container may also be paused by other types; this method
99 : * does not test if aType is the exclusive pause source.
100 : *
101 : * @param @aType The pause source to test for.
102 : * @return true if this container is paused by aType.
103 : */
104 0 : bool IsPausedByType(PRUint32 aType) const { return mPauseState & aType; }
105 :
106 : /**
107 : * Returns true if this time container is paused.
108 : * Generally you should test for a specific type of pausing using
109 : * IsPausedByType.
110 : *
111 : * @return true if this container is paused, false otherwise.
112 : */
113 : bool IsPaused() const { return mPauseState != 0; }
114 :
115 : /*
116 : * Return the time elapsed since this time container's begin time (expressed
117 : * in parent time) minus any accumulated offset from pausing.
118 : */
119 : nsSMILTime GetCurrentTime() const;
120 :
121 : /*
122 : * Seek the document timeline to the specified time.
123 : *
124 : * @param aSeekTo The time to seek to, expressed in this time container's time
125 : * base (i.e. the same units as GetCurrentTime).
126 : */
127 : void SetCurrentTime(nsSMILTime aSeekTo);
128 :
129 : /*
130 : * Return the current time for the parent time container if any.
131 : */
132 : virtual nsSMILTime GetParentTime() const;
133 :
134 : /*
135 : * Convert container time to parent time.
136 : *
137 : * @param aContainerTime The container time to convert.
138 : * @return The equivalent parent time or indefinite if the container is
139 : * paused and the time is in the future.
140 : */
141 : nsSMILTimeValue ContainerToParentTime(nsSMILTime aContainerTime) const;
142 :
143 : /*
144 : * Convert from parent time to container time.
145 : *
146 : * @param aParentTime The parent time to convert.
147 : * @return The equivalent container time or indefinite if the container is
148 : * paused and aParentTime is after the time when the pause began.
149 : */
150 : nsSMILTimeValue ParentToContainerTime(nsSMILTime aParentTime) const;
151 :
152 : /*
153 : * If the container is paused, causes the pause time to be updated to the
154 : * current parent time. This should be called before updating
155 : * cross-container dependencies that will call ContainerToParentTime in order
156 : * to provide more intuitive results.
157 : */
158 : void SyncPauseTime();
159 :
160 : /*
161 : * Updates the current time of this time container and calls DoSample to
162 : * perform any sample-operations.
163 : */
164 : void Sample();
165 :
166 : /*
167 : * Return if this time container should be sampled or can be skipped.
168 : *
169 : * This is most useful as an optimisation for skipping time containers that
170 : * don't require a sample.
171 : */
172 : bool NeedsSample() const { return !mPauseState || mNeedsPauseSample; }
173 :
174 : /*
175 : * Indicates if the elements of this time container need to be rewound.
176 : * This occurs during a backwards seek.
177 : */
178 : bool NeedsRewind() const { return mNeedsRewind; }
179 : void ClearNeedsRewind() { mNeedsRewind = false; }
180 :
181 : /*
182 : * Indicates the time container is currently processing a SetCurrentTime
183 : * request and appropriate seek behaviour should be applied by child elements
184 : * (e.g. not firing time events).
185 : */
186 0 : bool IsSeeking() const { return mIsSeeking; }
187 : void MarkSeekFinished() { mIsSeeking = false; }
188 :
189 : /*
190 : * Sets the parent time container.
191 : *
192 : * The callee still retains ownership of the time container.
193 : */
194 : nsresult SetParent(nsSMILTimeContainer* aParent);
195 :
196 : /*
197 : * Registers an element for a sample at the given time.
198 : *
199 : * @param aMilestone The milestone to register in container time.
200 : * @param aElement The timebase element that needs a sample at
201 : * aMilestone.
202 : * @return true if the element was successfully added, false otherwise.
203 : */
204 : bool AddMilestone(const nsSMILMilestone& aMilestone,
205 : nsISMILAnimationElement& aElement);
206 :
207 : /*
208 : * Resets the list of milestones.
209 : */
210 : void ClearMilestones();
211 :
212 : /*
213 : * Returns the next significant transition from amongst the registered
214 : * milestones.
215 : *
216 : * @param[out] aNextMilestone The next milestone with time in parent time.
217 : *
218 : * @return true if there exists another milestone, false otherwise in
219 : * which case aNextMilestone will be unmodified.
220 : */
221 : bool GetNextMilestoneInParentTime(nsSMILMilestone& aNextMilestone) const;
222 :
223 : typedef nsTArray<nsRefPtr<nsISMILAnimationElement> > AnimElemArray;
224 :
225 : /*
226 : * Removes and returns the timebase elements from the start of the list of
227 : * timebase elements that match the given time.
228 : *
229 : * @param aMilestone The milestone time to match in parent time. This
230 : * must be <= GetNextMilestoneInParentTime.
231 : * @param[out] aMatchedElements The array to which matching elements will be
232 : * appended.
233 : * @return true if one or more elements match, false otherwise.
234 : */
235 : bool PopMilestoneElementsAtMilestone(const nsSMILMilestone& aMilestone,
236 : AnimElemArray& aMatchedElements);
237 :
238 : // Cycle-collection support
239 : void Traverse(nsCycleCollectionTraversalCallback* aCallback);
240 : void Unlink();
241 :
242 : protected:
243 : /*
244 : * Per-sample operations to be performed whenever Sample() is called and
245 : * NeedsSample() is true. Called after updating mCurrentTime;
246 : */
247 : virtual void DoSample() { }
248 :
249 : /*
250 : * Adding and removing child containers is not implemented in the base class
251 : * because not all subclasses need this.
252 : */
253 :
254 : /*
255 : * Adds a child time container.
256 : */
257 : virtual nsresult AddChild(nsSMILTimeContainer& aChild)
258 : {
259 : return NS_ERROR_FAILURE;
260 : }
261 :
262 : /*
263 : * Removes a child time container.
264 : */
265 : virtual void RemoveChild(nsSMILTimeContainer& aChild) { }
266 :
267 : /*
268 : * Implementation helper to update the current time.
269 : */
270 : void UpdateCurrentTime();
271 :
272 : /*
273 : * Implementation helper to notify timed elements with dependencies that the
274 : * container time has changed with respect to the document time.
275 : */
276 : void NotifyTimeChange();
277 :
278 : // The parent time container, if any
279 : nsSMILTimeContainer* mParent;
280 :
281 : // The current time established at the last call to Sample()
282 : nsSMILTime mCurrentTime;
283 :
284 : // The number of milliseconds for which the container has been paused
285 : // (excluding the current pause interval if the container is currently
286 : // paused).
287 : //
288 : // Current time = parent time - mParentOffset
289 : //
290 : nsSMILTime mParentOffset;
291 :
292 : // The timestamp in parent time when the container was paused
293 : nsSMILTime mPauseStart;
294 :
295 : // Whether or not a pause sample is required
296 : bool mNeedsPauseSample;
297 :
298 : bool mNeedsRewind; // Backwards seek performed
299 : bool mIsSeeking; // Currently in the middle of a seek operation
300 :
301 : // A bitfield of the pause state for all pause requests
302 : PRUint32 mPauseState;
303 :
304 : struct MilestoneEntry
305 : {
306 : MilestoneEntry(nsSMILMilestone aMilestone,
307 : nsISMILAnimationElement& aElement)
308 : : mMilestone(aMilestone), mTimebase(&aElement)
309 : { }
310 :
311 : bool operator<(const MilestoneEntry& aOther) const
312 : {
313 : return mMilestone < aOther.mMilestone;
314 : }
315 :
316 : nsSMILMilestone mMilestone; // In container time.
317 : nsRefPtr<nsISMILAnimationElement> mTimebase;
318 : };
319 :
320 : // Queue of elements with registered milestones. Used to update the model with
321 : // significant transitions that occur between two samples. Since timed element
322 : // re-register their milestones when they're sampled this is reset once we've
323 : // taken care of the milestones before the current sample time but before we
324 : // actually do the full sample.
325 : nsTPriorityQueue<MilestoneEntry> mMilestoneEntries;
326 : };
327 :
328 : #endif // NS_SMILTIMECONTAINER_H_
|