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