|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef NS_SMILTIMECONTAINER_H_ |
|
7 #define NS_SMILTIMECONTAINER_H_ |
|
8 |
|
9 #include "mozilla/dom/SVGAnimationElement.h" |
|
10 #include "nscore.h" |
|
11 #include "nsSMILTypes.h" |
|
12 #include "nsTPriorityQueue.h" |
|
13 #include "nsAutoPtr.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 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 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 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 bool NeedsRewind() const { return mNeedsRewind; } |
|
147 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 bool IsSeeking() const { return mIsSeeking; } |
|
155 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<nsRefPtr<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 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 virtual nsresult AddChild(nsSMILTimeContainer& aChild) |
|
226 { |
|
227 return NS_ERROR_FAILURE; |
|
228 } |
|
229 |
|
230 /* |
|
231 * Removes a child time container. |
|
232 */ |
|
233 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 // A bitfield of the pause state for all pause requests |
|
270 uint32_t mPauseState; |
|
271 |
|
272 struct MilestoneEntry |
|
273 { |
|
274 MilestoneEntry(nsSMILMilestone aMilestone, |
|
275 mozilla::dom::SVGAnimationElement& aElement) |
|
276 : mMilestone(aMilestone), mTimebase(&aElement) |
|
277 { } |
|
278 |
|
279 bool operator<(const MilestoneEntry& aOther) const |
|
280 { |
|
281 return mMilestone < aOther.mMilestone; |
|
282 } |
|
283 |
|
284 nsSMILMilestone mMilestone; // In container time. |
|
285 nsRefPtr<mozilla::dom::SVGAnimationElement> mTimebase; |
|
286 }; |
|
287 |
|
288 // Queue of elements with registered milestones. Used to update the model with |
|
289 // significant transitions that occur between two samples. Since timed element |
|
290 // re-register their milestones when they're sampled this is reset once we've |
|
291 // taken care of the milestones before the current sample time but before we |
|
292 // actually do the full sample. |
|
293 nsTPriorityQueue<MilestoneEntry> mMilestoneEntries; |
|
294 }; |
|
295 |
|
296 #endif // NS_SMILTIMECONTAINER_H_ |