Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(546)

Side by Side Diff: Source/core/svg/animation/SMILTimeContainer.cpp

Issue 188903003: Revert "Drive SVG Animations via requestAnimationFrame" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/svg/animation/SMILTimeContainer.h ('k') | Source/core/svg/graphics/SVGImage.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/svg/animation/SMILTimeContainer.h" 27 #include "core/svg/animation/SMILTimeContainer.h"
28 28
29 #include "core/animation/AnimationClock.h"
30 #include "core/animation/DocumentTimeline.h"
31 #include "core/dom/ElementTraversal.h" 29 #include "core/dom/ElementTraversal.h"
32 #include "core/frame/FrameView.h"
33 #include "core/svg/SVGSVGElement.h" 30 #include "core/svg/SVGSVGElement.h"
34 #include "core/svg/animation/SVGSMILElement.h" 31 #include "core/svg/animation/SVGSMILElement.h"
32 #include "wtf/CurrentTime.h"
35 33
36 using namespace std; 34 using namespace std;
37 35
38 namespace WebCore { 36 namespace WebCore {
39 37
38 static const double animationFrameDelay = 0.025;
39
40 SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner) 40 SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
41 : m_beginTime(0) 41 : m_beginTime(0)
42 , m_pauseTime(0) 42 , m_pauseTime(0)
43 , m_resumeTime(0) 43 , m_resumeTime(0)
44 , m_accumulatedActiveTime(0) 44 , m_accumulatedActiveTime(0)
45 , m_presetStartTime(0) 45 , m_presetStartTime(0)
46 , m_documentOrderIndexesDirty(false) 46 , m_documentOrderIndexesDirty(false)
47 , m_framePending(false) 47 , m_timer(this, &SMILTimeContainer::timerFired)
48 , m_animationClock(AnimationClock::create())
49 , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired)
50 , m_ownerSVGElement(owner) 48 , m_ownerSVGElement(owner)
51 #ifndef NDEBUG 49 #ifndef NDEBUG
52 , m_preventScheduledAnimationsChanges(false) 50 , m_preventScheduledAnimationsChanges(false)
53 #endif 51 #endif
54 { 52 {
55 } 53 }
56 54
57 SMILTimeContainer::~SMILTimeContainer() 55 SMILTimeContainer::~SMILTimeContainer()
58 { 56 {
59 cancelAnimationFrame(); 57 cancelAnimationFrame();
60 ASSERT(!m_wakeupTimer.isActive()); 58 ASSERT(!m_timer.isActive());
61 #ifndef NDEBUG 59 #ifndef NDEBUG
62 ASSERT(!m_preventScheduledAnimationsChanges); 60 ASSERT(!m_preventScheduledAnimationsChanges);
63 #endif 61 #endif
64 } 62 }
65 63
66 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName) 64 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
67 { 65 {
68 ASSERT(animation->timeContainer() == this); 66 ASSERT(animation->timeContainer() == this);
69 ASSERT(target); 67 ASSERT(target);
70 ASSERT(animation->hasValidAttributeName()); 68 ASSERT(animation->hasValidAttributeName());
(...skipping 23 matching lines...) Expand all
94 #endif 92 #endif
95 93
96 ElementAttributePair key(target, attributeName); 94 ElementAttributePair key(target, attributeName);
97 AnimationsVector* scheduled = m_scheduledAnimations.get(key); 95 AnimationsVector* scheduled = m_scheduledAnimations.get(key);
98 ASSERT(scheduled); 96 ASSERT(scheduled);
99 size_t idx = scheduled->find(animation); 97 size_t idx = scheduled->find(animation);
100 ASSERT(idx != kNotFound); 98 ASSERT(idx != kNotFound);
101 scheduled->remove(idx); 99 scheduled->remove(idx);
102 } 100 }
103 101
104 bool SMILTimeContainer::hasAnimations() const
105 {
106 return !m_scheduledAnimations.isEmpty();
107 }
108
109 void SMILTimeContainer::notifyIntervalsChanged() 102 void SMILTimeContainer::notifyIntervalsChanged()
110 { 103 {
111 // Schedule updateAnimations() to be called asynchronously so multiple inter vals 104 // Schedule updateAnimations() to be called asynchronously so multiple inter vals
112 // can change with updateAnimations() only called once at the end. 105 // can change with updateAnimations() only called once at the end.
113 scheduleAnimationFrame(); 106 scheduleAnimationFrame();
114 } 107 }
115 108
116 SMILTime SMILTimeContainer::elapsed() const 109 SMILTime SMILTimeContainer::elapsed() const
117 { 110 {
118 if (!m_beginTime) 111 if (!m_beginTime)
119 return 0; 112 return 0;
120 113
121 if (isPaused()) 114 if (isPaused())
122 return m_accumulatedActiveTime; 115 return m_accumulatedActiveTime;
123 116
124 return m_animationClock->currentTime() + m_accumulatedActiveTime - lastResum eTime(); 117 return currentTime() + m_accumulatedActiveTime - lastResumeTime();
125 } 118 }
126 119
127 bool SMILTimeContainer::isPaused() const 120 bool SMILTimeContainer::isPaused() const
128 { 121 {
129 return m_pauseTime; 122 return m_pauseTime;
130 } 123 }
131 124
132 bool SMILTimeContainer::isStarted() const 125 bool SMILTimeContainer::isStarted() const
133 { 126 {
134 return m_beginTime; 127 return m_beginTime;
135 } 128 }
136 129
137 void SMILTimeContainer::begin() 130 void SMILTimeContainer::begin()
138 { 131 {
139 ASSERT(!m_beginTime); 132 ASSERT(!m_beginTime);
140 double now = m_animationClock->currentTime(); 133 double now = currentTime();
141 134
142 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began. 135 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
143 // In this case pass on 'seekToTime=true' to updateAnimations(). 136 // In this case pass on 'seekToTime=true' to updateAnimations().
144 m_beginTime = now - m_presetStartTime; 137 m_beginTime = now - m_presetStartTime;
145 updateAnimations(SMILTime(m_presetStartTime), m_presetStartTime ? true : fal se); 138 updateAnimations(SMILTime(m_presetStartTime), m_presetStartTime ? true : fal se);
146 m_presetStartTime = 0; 139 m_presetStartTime = 0;
147 140
148 if (m_pauseTime) { 141 if (m_pauseTime) {
149 m_pauseTime = now; 142 m_pauseTime = now;
150 cancelAnimationFrame(); 143 cancelAnimationFrame();
151 } else {
152 // Latch the clock to this time (0 or the preset start time).
153 m_animationClock->updateTime(now);
154 } 144 }
155 } 145 }
156 146
157 void SMILTimeContainer::pause() 147 void SMILTimeContainer::pause()
158 { 148 {
159 ASSERT(!isPaused()); 149 ASSERT(!isPaused());
160 m_pauseTime = m_animationClock->currentTime(); 150 m_pauseTime = currentTime();
161 151
162 if (m_beginTime) { 152 if (m_beginTime) {
163 m_accumulatedActiveTime += m_pauseTime - lastResumeTime(); 153 m_accumulatedActiveTime += m_pauseTime - lastResumeTime();
164 cancelAnimationFrame(); 154 cancelAnimationFrame();
165 } 155 }
166 m_resumeTime = 0; 156 m_resumeTime = 0;
167 m_animationClock->unfreeze();
168 } 157 }
169 158
170 void SMILTimeContainer::resume() 159 void SMILTimeContainer::resume()
171 { 160 {
172 ASSERT(isPaused()); 161 ASSERT(isPaused());
173 m_resumeTime = m_animationClock->currentTime(); 162 m_resumeTime = currentTime();
174 163
175 m_pauseTime = 0; 164 m_pauseTime = 0;
176 scheduleAnimationFrame(); 165 scheduleAnimationFrame();
177 m_animationClock->unfreeze();
178 } 166 }
179 167
180 void SMILTimeContainer::setElapsed(SMILTime time) 168 void SMILTimeContainer::setElapsed(SMILTime time)
181 { 169 {
182 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible. 170 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible.
183 if (!m_beginTime) { 171 if (!m_beginTime) {
184 m_presetStartTime = time.value(); 172 m_presetStartTime = time.value();
185 return; 173 return;
186 } 174 }
187 175
188 m_animationClock->unfreeze(); 176 if (m_beginTime)
177 cancelAnimationFrame();
189 178
190 cancelAnimationFrame(); 179 double now = currentTime();
191
192 double now = m_animationClock->currentTime();
193 m_beginTime = now - time.value(); 180 m_beginTime = now - time.value();
194 m_resumeTime = 0; 181 m_resumeTime = 0;
195 if (m_pauseTime) { 182 if (m_pauseTime) {
196 m_pauseTime = now; 183 m_pauseTime = now;
197 m_accumulatedActiveTime = time.value(); 184 m_accumulatedActiveTime = time.value();
198 } else { 185 } else {
199 m_accumulatedActiveTime = 0; 186 m_accumulatedActiveTime = 0;
200 } 187 }
201 188
202 #ifndef NDEBUG 189 #ifndef NDEBUG
203 m_preventScheduledAnimationsChanges = true; 190 m_preventScheduledAnimationsChanges = true;
204 #endif 191 #endif
205 GroupedAnimationsMap::iterator end = m_scheduledAnimations.end(); 192 GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
206 for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it ! = end; ++it) { 193 for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it ! = end; ++it) {
207 AnimationsVector* scheduled = it->value.get(); 194 AnimationsVector* scheduled = it->value.get();
208 unsigned size = scheduled->size(); 195 unsigned size = scheduled->size();
209 for (unsigned n = 0; n < size; n++) 196 for (unsigned n = 0; n < size; n++)
210 scheduled->at(n)->reset(); 197 scheduled->at(n)->reset();
211 } 198 }
212 #ifndef NDEBUG 199 #ifndef NDEBUG
213 m_preventScheduledAnimationsChanges = false; 200 m_preventScheduledAnimationsChanges = false;
214 #endif 201 #endif
215 202
216 updateAnimations(time, true); 203 updateAnimations(time, true);
217 // Latch the clock to wait for this frame to be sampled by the frame interva l.
218 m_animationClock->updateTime(now);
219 } 204 }
220 205
221 bool SMILTimeContainer::isTimelineRunning() const 206 bool SMILTimeContainer::isTimelineRunning() const
222 { 207 {
223 return m_beginTime && !isPaused(); 208 return m_beginTime && !isPaused();
224 } 209 }
225 210
226 void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime) 211 void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime)
227 { 212 {
228 if (!isTimelineRunning()) 213 if (!isTimelineRunning())
229 return; 214 return;
230 215
231 if (!fireTime.isFinite()) 216 if (!fireTime.isFinite())
232 return; 217 return;
233 218
234 SMILTime delay = fireTime - elapsed(); 219 SMILTime delay = max(fireTime - elapsed(), SMILTime(animationFrameDelay));
235 if (delay.value() < DocumentTimeline::s_minimumDelay) 220 m_timer.startOneShot(delay.value());
236 serviceOnNextFrame();
237 else
238 m_wakeupTimer.startOneShot(delay.value() - DocumentTimeline::s_minimumDe lay);
239 } 221 }
240 222
241 void SMILTimeContainer::scheduleAnimationFrame() 223 void SMILTimeContainer::scheduleAnimationFrame()
242 { 224 {
243 if (!isTimelineRunning()) 225 if (!isTimelineRunning())
244 return; 226 return;
245 227
246 // Could also schedule a wakeup at +0 seconds, but that could still 228 m_timer.startOneShot(0);
247 // potentially race with the servicing of the next frame.
248 serviceOnNextFrame();
249 } 229 }
250 230
251 void SMILTimeContainer::cancelAnimationFrame() 231 void SMILTimeContainer::cancelAnimationFrame()
252 { 232 {
253 m_framePending = false; 233 m_timer.stop();
254 m_wakeupTimer.stop();
255 } 234 }
256 235
257 void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*) 236 void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
258 { 237 {
259 ASSERT(isTimelineRunning()); 238 ASSERT(isTimelineRunning());
260 serviceOnNextFrame(); 239 updateAnimations(elapsed());
261 } 240 }
262 241
263 void SMILTimeContainer::updateDocumentOrderIndexes() 242 void SMILTimeContainer::updateDocumentOrderIndexes()
264 { 243 {
265 unsigned timingElementCount = 0; 244 unsigned timingElementCount = 0;
266 for (Element* element = m_ownerSVGElement; element; element = ElementTravers al::next(*element, m_ownerSVGElement)) { 245 for (Element* element = m_ownerSVGElement; element; element = ElementTravers al::next(*element, m_ownerSVGElement)) {
267 if (isSVGSMILElement(*element)) 246 if (isSVGSMILElement(*element))
268 toSVGSMILElement(element)->setDocumentOrderIndex(timingElementCount+ +); 247 toSVGSMILElement(element)->setDocumentOrderIndex(timingElementCount+ +);
269 } 248 }
270 m_documentOrderIndexesDirty = false; 249 m_documentOrderIndexesDirty = false;
271 } 250 }
272 251
273 struct PriorityCompare { 252 struct PriorityCompare {
274 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {} 253 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {}
275 bool operator()(const RefPtr<SVGSMILElement>& a, const RefPtr<SVGSMILElement >& b) 254 bool operator()(const RefPtr<SVGSMILElement>& a, const RefPtr<SVGSMILElement >& b)
276 { 255 {
277 // FIXME: This should also consider possible timing relations between th e elements. 256 // FIXME: This should also consider possible timing relations between th e elements.
278 SMILTime aBegin = a->intervalBegin(); 257 SMILTime aBegin = a->intervalBegin();
279 SMILTime bBegin = b->intervalBegin(); 258 SMILTime bBegin = b->intervalBegin();
280 // Frozen elements need to be prioritized based on their previous interv al. 259 // Frozen elements need to be prioritized based on their previous interv al.
281 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin( ) : aBegin; 260 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin( ) : aBegin;
282 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin( ) : bBegin; 261 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin( ) : bBegin;
283 if (aBegin == bBegin) 262 if (aBegin == bBegin)
284 return a->documentOrderIndex() < b->documentOrderIndex(); 263 return a->documentOrderIndex() < b->documentOrderIndex();
285 return aBegin < bBegin; 264 return aBegin < bBegin;
286 } 265 }
287 SMILTime m_elapsed; 266 SMILTime m_elapsed;
288 }; 267 };
289 268
290 Document& SMILTimeContainer::document() const
291 {
292 ASSERT(m_ownerSVGElement);
293 return m_ownerSVGElement->document();
294 }
295
296 void SMILTimeContainer::serviceOnNextFrame()
297 {
298 if (document().view()) {
299 document().view()->scheduleAnimation();
300 m_framePending = true;
301 }
302 }
303
304 void SMILTimeContainer::serviceAnimations(double monotonicAnimationStartTime)
305 {
306 if (!m_framePending)
307 return;
308
309 m_framePending = false;
310 // If the clock is frozen at this point, it means the timeline has been
311 // started, but the first animation frame hasn't yet been serviced. If so,
312 // then just keep the clock frozen for this update.
313 if (!m_animationClock->isFrozen())
314 m_animationClock->updateTime(monotonicAnimationStartTime);
315 updateAnimations(elapsed());
316 m_animationClock->unfreeze();
317 }
318
319 void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) 269 void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
320 { 270 {
321 SMILTime earliestFireTime = SMILTime::unresolved(); 271 SMILTime earliestFireTime = SMILTime::unresolved();
322 272
323 #ifndef NDEBUG 273 #ifndef NDEBUG
324 // This boolean will catch any attempts to schedule/unschedule scheduledAnim ations during this critical section. 274 // This boolean will catch any attempts to schedule/unschedule scheduledAnim ations during this critical section.
325 // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply. 275 // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply.
326 m_preventScheduledAnimationsChanges = true; 276 m_preventScheduledAnimationsChanges = true;
327 #endif 277 #endif
328 278
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 351
402 if (animDiscard->inDocument()) { 352 if (animDiscard->inDocument()) {
403 animDiscard->remove(IGNORE_EXCEPTION); 353 animDiscard->remove(IGNORE_EXCEPTION);
404 ASSERT(!animDiscard->inDocument()); 354 ASSERT(!animDiscard->inDocument());
405 } 355 }
406 } 356 }
407 } 357 }
408 } 358 }
409 359
410 } 360 }
OLDNEW
« no previous file with comments | « Source/core/svg/animation/SMILTimeContainer.h ('k') | Source/core/svg/graphics/SVGImage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698