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

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

Issue 190963003: 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"
29 #include "core/dom/ElementTraversal.h" 31 #include "core/dom/ElementTraversal.h"
32 #include "core/frame/FrameView.h"
30 #include "core/svg/SVGSVGElement.h" 33 #include "core/svg/SVGSVGElement.h"
31 #include "core/svg/animation/SVGSMILElement.h" 34 #include "core/svg/animation/SVGSMILElement.h"
32 #include "wtf/CurrentTime.h"
33 35
34 using namespace std; 36 using namespace std;
35 37
36 namespace WebCore { 38 namespace WebCore {
37 39
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_frameSchedulingState(Idle)
46 , m_documentOrderIndexesDirty(false) 47 , m_documentOrderIndexesDirty(false)
47 , m_timer(this, &SMILTimeContainer::timerFired) 48 , m_animationClock(AnimationClock::create())
49 , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired)
48 , m_ownerSVGElement(owner) 50 , m_ownerSVGElement(owner)
49 #ifndef NDEBUG 51 #ifndef NDEBUG
50 , m_preventScheduledAnimationsChanges(false) 52 , m_preventScheduledAnimationsChanges(false)
51 #endif 53 #endif
52 { 54 {
53 } 55 }
54 56
55 SMILTimeContainer::~SMILTimeContainer() 57 SMILTimeContainer::~SMILTimeContainer()
56 { 58 {
57 cancelAnimationFrame(); 59 cancelAnimationFrame();
58 ASSERT(!m_timer.isActive()); 60 ASSERT(!m_wakeupTimer.isActive());
59 #ifndef NDEBUG 61 #ifndef NDEBUG
60 ASSERT(!m_preventScheduledAnimationsChanges); 62 ASSERT(!m_preventScheduledAnimationsChanges);
61 #endif 63 #endif
62 } 64 }
63 65
64 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName) 66 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
65 { 67 {
66 ASSERT(animation->timeContainer() == this); 68 ASSERT(animation->timeContainer() == this);
67 ASSERT(target); 69 ASSERT(target);
68 ASSERT(animation->hasValidAttributeName()); 70 ASSERT(animation->hasValidAttributeName());
(...skipping 23 matching lines...) Expand all
92 #endif 94 #endif
93 95
94 ElementAttributePair key(target, attributeName); 96 ElementAttributePair key(target, attributeName);
95 AnimationsVector* scheduled = m_scheduledAnimations.get(key); 97 AnimationsVector* scheduled = m_scheduledAnimations.get(key);
96 ASSERT(scheduled); 98 ASSERT(scheduled);
97 size_t idx = scheduled->find(animation); 99 size_t idx = scheduled->find(animation);
98 ASSERT(idx != kNotFound); 100 ASSERT(idx != kNotFound);
99 scheduled->remove(idx); 101 scheduled->remove(idx);
100 } 102 }
101 103
104 bool SMILTimeContainer::hasAnimations() const
105 {
106 return !m_scheduledAnimations.isEmpty();
107 }
108
102 void SMILTimeContainer::notifyIntervalsChanged() 109 void SMILTimeContainer::notifyIntervalsChanged()
103 { 110 {
111 if (!isStarted())
112 return;
104 // Schedule updateAnimations() to be called asynchronously so multiple inter vals 113 // Schedule updateAnimations() to be called asynchronously so multiple inter vals
105 // can change with updateAnimations() only called once at the end. 114 // can change with updateAnimations() only called once at the end.
106 scheduleAnimationFrame(); 115 if (m_frameSchedulingState == SynchronizeAnimations && m_wakeupTimer.isActiv e() && !m_wakeupTimer.nextFireInterval())
116 return;
117 cancelAnimationFrame();
118 scheduleWakeUp(0, SynchronizeAnimations);
107 } 119 }
108 120
109 SMILTime SMILTimeContainer::elapsed() const 121 SMILTime SMILTimeContainer::elapsed() const
110 { 122 {
111 if (!m_beginTime) 123 if (!m_beginTime)
112 return 0; 124 return 0;
113 125
114 if (isPaused()) 126 if (isPaused())
115 return m_accumulatedActiveTime; 127 return m_accumulatedActiveTime;
116 128
(...skipping 11 matching lines...) Expand all
128 } 140 }
129 141
130 void SMILTimeContainer::begin() 142 void SMILTimeContainer::begin()
131 { 143 {
132 ASSERT(!m_beginTime); 144 ASSERT(!m_beginTime);
133 double now = currentTime(); 145 double now = currentTime();
134 146
135 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began. 147 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
136 // In this case pass on 'seekToTime=true' to updateAnimations(). 148 // In this case pass on 'seekToTime=true' to updateAnimations().
137 m_beginTime = now - m_presetStartTime; 149 m_beginTime = now - m_presetStartTime;
138 updateAnimations(SMILTime(m_presetStartTime), m_presetStartTime ? true : fal se); 150 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_ presetStartTime ? true : false);
139 m_presetStartTime = 0; 151 m_presetStartTime = 0;
140 152
141 if (m_pauseTime) { 153 if (m_pauseTime) {
142 m_pauseTime = now; 154 m_pauseTime = now;
143 cancelAnimationFrame(); 155 cancelAnimationFrame();
156 } else {
157 ASSERT(isTimelineRunning());
158 // If the timeline is running, and there's pending animation updates,
159 // always perform the first update after the timeline was started using
160 // the wake-up mechanism.
161 if (earliestFireTime.isFinite()) {
162 scheduleWakeUp(DocumentTimeline::s_minimumDelay, SynchronizeAnimatio ns);
163 }
144 } 164 }
145 } 165 }
146 166
147 void SMILTimeContainer::pause() 167 void SMILTimeContainer::pause()
148 { 168 {
149 ASSERT(!isPaused()); 169 ASSERT(!isPaused());
150 m_pauseTime = currentTime(); 170 m_pauseTime = currentTime();
151 171
152 if (m_beginTime) { 172 if (m_beginTime) {
153 m_accumulatedActiveTime += m_pauseTime - lastResumeTime(); 173 m_accumulatedActiveTime += m_pauseTime - lastResumeTime();
154 cancelAnimationFrame(); 174 cancelAnimationFrame();
155 } 175 }
156 m_resumeTime = 0; 176 m_resumeTime = 0;
157 } 177 }
158 178
159 void SMILTimeContainer::resume() 179 void SMILTimeContainer::resume()
160 { 180 {
161 ASSERT(isPaused()); 181 ASSERT(isPaused());
162 m_resumeTime = currentTime(); 182 m_resumeTime = currentTime();
163 183
164 m_pauseTime = 0; 184 m_pauseTime = 0;
165 scheduleAnimationFrame(); 185 serviceOnNextFrame();
166 } 186 }
167 187
168 void SMILTimeContainer::setElapsed(SMILTime time) 188 void SMILTimeContainer::setElapsed(SMILTime time)
169 { 189 {
170 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible. 190 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible.
171 if (!m_beginTime) { 191 if (!m_beginTime) {
172 m_presetStartTime = time.value(); 192 m_presetStartTime = time.value();
173 return; 193 return;
174 } 194 }
175 195
176 if (m_beginTime) 196 cancelAnimationFrame();
177 cancelAnimationFrame();
178 197
179 double now = currentTime(); 198 double now = currentTime();
180 m_beginTime = now - time.value(); 199 m_beginTime = now - time.value();
181 m_resumeTime = 0; 200 m_resumeTime = 0;
182 if (m_pauseTime) { 201 if (m_pauseTime) {
183 m_pauseTime = now; 202 m_pauseTime = now;
184 m_accumulatedActiveTime = time.value(); 203 m_accumulatedActiveTime = time.value();
185 } else { 204 } else {
186 m_accumulatedActiveTime = 0; 205 m_accumulatedActiveTime = 0;
187 } 206 }
188 207
189 #ifndef NDEBUG 208 #ifndef NDEBUG
190 m_preventScheduledAnimationsChanges = true; 209 m_preventScheduledAnimationsChanges = true;
191 #endif 210 #endif
192 GroupedAnimationsMap::iterator end = m_scheduledAnimations.end(); 211 GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
193 for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it ! = end; ++it) { 212 for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it ! = end; ++it) {
194 AnimationsVector* scheduled = it->value.get(); 213 AnimationsVector* scheduled = it->value.get();
195 unsigned size = scheduled->size(); 214 unsigned size = scheduled->size();
196 for (unsigned n = 0; n < size; n++) 215 for (unsigned n = 0; n < size; n++)
197 scheduled->at(n)->reset(); 216 scheduled->at(n)->reset();
198 } 217 }
199 #ifndef NDEBUG 218 #ifndef NDEBUG
200 m_preventScheduledAnimationsChanges = false; 219 m_preventScheduledAnimationsChanges = false;
201 #endif 220 #endif
202 221
203 updateAnimations(time, true); 222 updateAnimationsAndScheduleFrameIfNeeded(time, true);
204 } 223 }
205 224
206 bool SMILTimeContainer::isTimelineRunning() const 225 bool SMILTimeContainer::isTimelineRunning() const
207 { 226 {
208 return m_beginTime && !isPaused(); 227 return m_beginTime && !isPaused();
209 } 228 }
210 229
211 void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime) 230 void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime)
212 { 231 {
213 if (!isTimelineRunning()) 232 ASSERT(isTimelineRunning() && fireTime.isFinite());
214 return;
215 233
216 if (!fireTime.isFinite()) 234 SMILTime delay = fireTime - elapsed();
217 return; 235 if (delay.value() < DocumentTimeline::s_minimumDelay) {
218 236 serviceOnNextFrame();
219 SMILTime delay = max(fireTime - elapsed(), SMILTime(animationFrameDelay)); 237 } else {
220 m_timer.startOneShot(delay.value()); 238 scheduleWakeUp(delay.value() - DocumentTimeline::s_minimumDelay, Animati onFrame);
221 } 239 }
222
223 void SMILTimeContainer::scheduleAnimationFrame()
224 {
225 if (!isTimelineRunning())
226 return;
227
228 m_timer.startOneShot(0);
229 } 240 }
230 241
231 void SMILTimeContainer::cancelAnimationFrame() 242 void SMILTimeContainer::cancelAnimationFrame()
232 { 243 {
233 m_timer.stop(); 244 m_frameSchedulingState = Idle;
245 m_wakeupTimer.stop();
234 } 246 }
235 247
236 void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*) 248 void SMILTimeContainer::scheduleWakeUp(double delayTime, FrameSchedulingState fr ameSchedulingState)
237 { 249 {
238 ASSERT(isTimelineRunning()); 250 ASSERT(frameSchedulingState != Idle);
239 updateAnimations(elapsed()); 251 m_wakeupTimer.startOneShot(delayTime);
252 m_frameSchedulingState = frameSchedulingState;
253 }
254
255 void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*)
256 {
257 if (m_frameSchedulingState == AnimationFrame) {
258 ASSERT(isTimelineRunning());
259 m_frameSchedulingState = Idle;
260 serviceOnNextFrame();
261 } else {
262 ASSERT(m_frameSchedulingState == SynchronizeAnimations);
263 m_frameSchedulingState = Idle;
264 updateAnimationsAndScheduleFrameIfNeeded(elapsed());
265 }
240 } 266 }
241 267
242 void SMILTimeContainer::updateDocumentOrderIndexes() 268 void SMILTimeContainer::updateDocumentOrderIndexes()
243 { 269 {
244 unsigned timingElementCount = 0; 270 unsigned timingElementCount = 0;
245 for (Element* element = m_ownerSVGElement; element; element = ElementTravers al::next(*element, m_ownerSVGElement)) { 271 for (Element* element = m_ownerSVGElement; element; element = ElementTravers al::next(*element, m_ownerSVGElement)) {
246 if (isSVGSMILElement(*element)) 272 if (isSVGSMILElement(*element))
247 toSVGSMILElement(element)->setDocumentOrderIndex(timingElementCount+ +); 273 toSVGSMILElement(element)->setDocumentOrderIndex(timingElementCount+ +);
248 } 274 }
249 m_documentOrderIndexesDirty = false; 275 m_documentOrderIndexesDirty = false;
250 } 276 }
251 277
252 struct PriorityCompare { 278 struct PriorityCompare {
253 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {} 279 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {}
254 bool operator()(const RefPtr<SVGSMILElement>& a, const RefPtr<SVGSMILElement >& b) 280 bool operator()(const RefPtr<SVGSMILElement>& a, const RefPtr<SVGSMILElement >& b)
255 { 281 {
256 // FIXME: This should also consider possible timing relations between th e elements. 282 // FIXME: This should also consider possible timing relations between th e elements.
257 SMILTime aBegin = a->intervalBegin(); 283 SMILTime aBegin = a->intervalBegin();
258 SMILTime bBegin = b->intervalBegin(); 284 SMILTime bBegin = b->intervalBegin();
259 // Frozen elements need to be prioritized based on their previous interv al. 285 // Frozen elements need to be prioritized based on their previous interv al.
260 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin( ) : aBegin; 286 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin( ) : aBegin;
261 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin( ) : bBegin; 287 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin( ) : bBegin;
262 if (aBegin == bBegin) 288 if (aBegin == bBegin)
263 return a->documentOrderIndex() < b->documentOrderIndex(); 289 return a->documentOrderIndex() < b->documentOrderIndex();
264 return aBegin < bBegin; 290 return aBegin < bBegin;
265 } 291 }
266 SMILTime m_elapsed; 292 SMILTime m_elapsed;
267 }; 293 };
268 294
269 void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) 295 Document& SMILTimeContainer::document() const
296 {
297 ASSERT(m_ownerSVGElement);
298 return m_ownerSVGElement->document();
299 }
300
301 AnimationClock& SMILTimeContainer::animationClock() const
302 {
303 ASSERT(m_animationClock);
304 return *m_animationClock;
305 }
306
307 double SMILTimeContainer::currentTime() const
308 {
309 return animationClock().currentTime();
310 }
311
312 void SMILTimeContainer::serviceOnNextFrame()
313 {
314 if (document().view()) {
315 document().view()->scheduleAnimation();
316 m_frameSchedulingState = AnimationFrame;
317 }
318 }
319
320 void SMILTimeContainer::serviceAnimations(double monotonicAnimationStartTime)
321 {
322 if (m_frameSchedulingState != AnimationFrame)
323 return;
324
325 m_frameSchedulingState = Idle;
326 animationClock().updateTime(monotonicAnimationStartTime);
327 updateAnimationsAndScheduleFrameIfNeeded(elapsed());
328 animationClock().unfreeze();
329 }
330
331 void SMILTimeContainer::updateAnimationsAndScheduleFrameIfNeeded(SMILTime elapse d, bool seekToTime)
332 {
333 SMILTime earliestFireTime = updateAnimations(elapsed, seekToTime);
334 if (!isTimelineRunning())
335 return;
336
337 if (!earliestFireTime.isFinite())
338 return;
339
340 scheduleAnimationFrame(earliestFireTime);
341 }
342
343 SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
270 { 344 {
271 SMILTime earliestFireTime = SMILTime::unresolved(); 345 SMILTime earliestFireTime = SMILTime::unresolved();
272 346
273 #ifndef NDEBUG 347 #ifndef NDEBUG
274 // This boolean will catch any attempts to schedule/unschedule scheduledAnim ations during this critical section. 348 // This boolean will catch any attempts to schedule/unschedule scheduledAnim ations during this critical section.
275 // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply. 349 // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply.
276 m_preventScheduledAnimationsChanges = true; 350 m_preventScheduledAnimationsChanges = true;
277 #endif 351 #endif
278 352
279 if (m_documentOrderIndexesDirty) 353 if (m_documentOrderIndexesDirty)
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 animationsToApply.append(resultElement); 393 animationsToApply.append(resultElement);
320 } 394 }
321 395
322 std::sort(animationsToApply.begin(), animationsToApply.end(), PriorityCompar e(elapsed)); 396 std::sort(animationsToApply.begin(), animationsToApply.end(), PriorityCompar e(elapsed));
323 397
324 unsigned animationsToApplySize = animationsToApply.size(); 398 unsigned animationsToApplySize = animationsToApply.size();
325 if (!animationsToApplySize) { 399 if (!animationsToApplySize) {
326 #ifndef NDEBUG 400 #ifndef NDEBUG
327 m_preventScheduledAnimationsChanges = false; 401 m_preventScheduledAnimationsChanges = false;
328 #endif 402 #endif
329 scheduleAnimationFrame(earliestFireTime); 403 return earliestFireTime;
330 return;
331 } 404 }
332 405
333 // Apply results to target elements. 406 // Apply results to target elements.
334 for (unsigned i = 0; i < animationsToApplySize; ++i) 407 for (unsigned i = 0; i < animationsToApplySize; ++i)
335 animationsToApply[i]->applyResultsToTarget(); 408 animationsToApply[i]->applyResultsToTarget();
336 409
337 #ifndef NDEBUG 410 #ifndef NDEBUG
338 m_preventScheduledAnimationsChanges = false; 411 m_preventScheduledAnimationsChanges = false;
339 #endif 412 #endif
340 413
341 scheduleAnimationFrame(earliestFireTime);
342
343 for (unsigned i = 0; i < animationsToApplySize; ++i) { 414 for (unsigned i = 0; i < animationsToApplySize; ++i) {
344 if (animationsToApply[i]->inDocument() && animationsToApply[i]->isSVGDis cardElement()) { 415 if (animationsToApply[i]->inDocument() && animationsToApply[i]->isSVGDis cardElement()) {
345 RefPtr<SVGSMILElement> animDiscard = animationsToApply[i]; 416 RefPtr<SVGSMILElement> animDiscard = animationsToApply[i];
346 RefPtr<SVGElement> targetElement = animDiscard->targetElement(); 417 RefPtr<SVGElement> targetElement = animDiscard->targetElement();
347 if (targetElement && targetElement->inDocument()) { 418 if (targetElement && targetElement->inDocument()) {
348 targetElement->remove(IGNORE_EXCEPTION); 419 targetElement->remove(IGNORE_EXCEPTION);
349 ASSERT(!targetElement->inDocument()); 420 ASSERT(!targetElement->inDocument());
350 } 421 }
351 422
352 if (animDiscard->inDocument()) { 423 if (animDiscard->inDocument()) {
353 animDiscard->remove(IGNORE_EXCEPTION); 424 animDiscard->remove(IGNORE_EXCEPTION);
354 ASSERT(!animDiscard->inDocument()); 425 ASSERT(!animDiscard->inDocument());
355 } 426 }
356 } 427 }
357 } 428 }
429 return earliestFireTime;
358 } 430 }
359 431
360 } 432 }
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