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

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

Issue 802143002: AnimationPolicy setting is applied to SVG animation. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: apply new concept Created 6 years 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
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
(...skipping 12 matching lines...) Expand all
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" 29 #include "core/animation/AnimationClock.h"
30 #include "core/animation/AnimationTimeline.h" 30 #include "core/animation/AnimationTimeline.h"
31 #include "core/dom/ElementTraversal.h" 31 #include "core/dom/ElementTraversal.h"
32 #include "core/frame/FrameView.h" 32 #include "core/frame/FrameView.h"
33 #include "core/frame/Settings.h"
33 #include "core/svg/SVGSVGElement.h" 34 #include "core/svg/SVGSVGElement.h"
34 #include "core/svg/animation/SVGSMILElement.h" 35 #include "core/svg/animation/SVGSMILElement.h"
35 36
36 namespace blink { 37 namespace blink {
37 38
38 static const double initialFrameDelay = 0.025; 39 static const double initialFrameDelay = 0.025;
40 static const double animationPolicyOnceDuration = 3.000;
39 41
40 #if !ENABLE(OILPAN) 42 #if !ENABLE(OILPAN)
41 // Every entry-point that calls updateAnimations() should instantiate a 43 // Every entry-point that calls updateAnimations() should instantiate a
42 // DiscardScope to prevent deletion of the ownerElement (and hence itself.) 44 // DiscardScope to prevent deletion of the ownerElement (and hence itself.)
43 class DiscardScope { 45 class DiscardScope {
44 public: 46 public:
45 explicit DiscardScope(SVGSVGElement& timeContainerOwner) : m_discardScopeEle ment(&timeContainerOwner) { } 47 explicit DiscardScope(SVGSVGElement& timeContainerOwner) : m_discardScopeEle ment(&timeContainerOwner) { }
46 48
47 private: 49 private:
48 RefPtr<SVGSVGElement> m_discardScopeElement; 50 RefPtr<SVGSVGElement> m_discardScopeElement;
49 }; 51 };
50 #endif 52 #endif
51 53
52 SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner) 54 SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner)
53 : m_beginTime(0) 55 : m_beginTime(0)
54 , m_pauseTime(0) 56 , m_pauseTime(0)
55 , m_resumeTime(0) 57 , m_resumeTime(0)
56 , m_accumulatedActiveTime(0) 58 , m_accumulatedActiveTime(0)
57 , m_presetStartTime(0) 59 , m_presetStartTime(0)
58 , m_frameSchedulingState(Idle) 60 , m_frameSchedulingState(Idle)
59 , m_documentOrderIndexesDirty(false) 61 , m_documentOrderIndexesDirty(false)
62 , m_animationState(NormalState)
60 , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired) 63 , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired)
64 , m_animationPolicyOnceTimer(this, &SMILTimeContainer::animationPolicyOnceTi merFired)
61 , m_ownerSVGElement(owner) 65 , m_ownerSVGElement(owner)
62 #if ENABLE(ASSERT) 66 #if ENABLE(ASSERT)
63 , m_preventScheduledAnimationsChanges(false) 67 , m_preventScheduledAnimationsChanges(false)
64 #endif 68 #endif
65 { 69 {
66 } 70 }
67 71
68 SMILTimeContainer::~SMILTimeContainer() 72 SMILTimeContainer::~SMILTimeContainer()
69 { 73 {
70 cancelAnimationFrame(); 74 cancelAnimationFrame();
75 cancelAnimationPolicyTimer();
71 ASSERT(!m_wakeupTimer.isActive()); 76 ASSERT(!m_wakeupTimer.isActive());
72 #if ENABLE(ASSERT) 77 #if ENABLE(ASSERT)
73 ASSERT(!m_preventScheduledAnimationsChanges); 78 ASSERT(!m_preventScheduledAnimationsChanges);
74 #endif 79 #endif
75 } 80 }
76 81
77 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName) 82 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
78 { 83 {
79 ASSERT(animation->timeContainer() == this); 84 ASSERT(animation->timeContainer() == this);
80 ASSERT(target); 85 ASSERT(target);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 return 0; 150 return 0;
146 151
147 if (isPaused()) 152 if (isPaused())
148 return m_accumulatedActiveTime; 153 return m_accumulatedActiveTime;
149 154
150 return currentTime() + m_accumulatedActiveTime - lastResumeTime(); 155 return currentTime() + m_accumulatedActiveTime - lastResumeTime();
151 } 156 }
152 157
153 bool SMILTimeContainer::isPaused() const 158 bool SMILTimeContainer::isPaused() const
154 { 159 {
160 if (ImageAnimationPolicyNoAnimation == getAnimationPolicy())
fs 2014/12/22 16:23:14 I'd prefer if we could reuse existing state as muc
je_julie(Not used) 2014/12/24 03:50:51 Done.
161 return true;
155 return m_pauseTime; 162 return m_pauseTime;
156 } 163 }
157 164
165 bool SMILTimeContainer::isFrozen() const
166 {
167 return m_animationState == FrozenState;
168 }
169
158 bool SMILTimeContainer::isStarted() const 170 bool SMILTimeContainer::isStarted() const
159 { 171 {
160 return m_beginTime; 172 return m_beginTime;
161 } 173 }
162 174
175 ImageAnimationPolicy SMILTimeContainer::getAnimationPolicy() const
176 {
177 Settings* settings = document().settings();
178 if (!settings)
179 return ImageAnimationPolicyAllowed;
180
181 ImageAnimationPolicy animationPolicy = settings->imageAnimationPolicy();
fs 2014/12/22 16:23:14 Nit: Return this directly.
je_julie(Not used) 2014/12/24 03:50:51 done.
182 return animationPolicy;
183 }
184
185 void SMILTimeContainer::freezeTimeline()
186 {
187 pause(true);
fs 2014/12/22 16:23:14 Could we structure this do a state-transition befo
je_julie(Not used) 2014/12/24 03:50:51 I removed it with improved concept.
188 }
189
190 void SMILTimeContainer::cancelAnimationPolicyTimer()
191 {
192 if (m_animationPolicyOnceTimer.isActive())
193 m_animationPolicyOnceTimer.stop();
194 }
195
196 void SMILTimeContainer::startAnimationPolicyTimer()
197 {
198 m_animationState &= ~FrozenState;
199 m_animationPolicyOnceTimer.startOneShot(animationPolicyOnceDuration, FROM_HE RE);
200 }
201
163 void SMILTimeContainer::begin() 202 void SMILTimeContainer::begin()
164 { 203 {
165 RELEASE_ASSERT(!m_beginTime); 204 RELEASE_ASSERT(!m_beginTime);
205
206 ImageAnimationPolicy animationPolicy = getAnimationPolicy();
207 if (animationPolicy == ImageAnimationPolicyNoAnimation)
208 return freezeTimeline();
fs 2014/12/22 16:23:15 This looks like a very complicated way to return d
je_julie(Not used) 2014/12/24 03:50:51 I removed it with improved concept.
209
210 // Repeating behavior is not well-defined for SMIL/SVG animations
211 // We define "once" as "play for animationPolicyOnceDuration seconds" here i nstead.
212 if (animationPolicy == ImageAnimationPolicyAnimateOnce)
213 startAnimationPolicyTimer();
fs 2014/12/22 16:23:14 Shouldn't this interact with pause in some way? (S
je_julie(Not used) 2014/12/24 03:50:51 I updated code with paused condition.
214
166 double now = currentTime(); 215 double now = currentTime();
167 216
168 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began. 217 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
169 // In this case pass on 'seekToTime=true' to updateAnimations(). 218 // In this case pass on 'seekToTime=true' to updateAnimations().
170 m_beginTime = now - m_presetStartTime; 219 m_beginTime = now - m_presetStartTime;
171 #if !ENABLE(OILPAN) 220 #if !ENABLE(OILPAN)
172 DiscardScope discardScope(m_ownerSVGElement); 221 DiscardScope discardScope(m_ownerSVGElement);
173 #endif 222 #endif
174 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_ presetStartTime ? true : false); 223 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_ presetStartTime ? true : false);
175 m_presetStartTime = 0; 224 m_presetStartTime = 0;
176 225
177 if (m_pauseTime) { 226 if (m_pauseTime) {
178 m_pauseTime = now; 227 m_pauseTime = now;
179 // If updateAnimations() caused new syncbase instance to be generated, 228 // If updateAnimations() caused new syncbase instance to be generated,
180 // we don't want to cancel those. Excepting that, no frame should've 229 // we don't want to cancel those. Excepting that, no frame should've
181 // been scheduled at this point. 230 // been scheduled at this point.
182 ASSERT(m_frameSchedulingState == Idle || m_frameSchedulingState == Synch ronizeAnimations); 231 ASSERT(m_frameSchedulingState == Idle || m_frameSchedulingState == Synch ronizeAnimations);
183 } else if (!hasPendingSynchronization()) { 232 } else if (!hasPendingSynchronization()) {
184 ASSERT(isTimelineRunning()); 233 ASSERT(isTimelineRunning());
185 // If the timeline is running, and there's pending animation updates, 234 // If the timeline is running, and there's pending animation updates,
186 // always perform the first update after the timeline was started using 235 // always perform the first update after the timeline was started using
187 // the wake-up mechanism. 236 // the wake-up mechanism.
188 if (earliestFireTime.isFinite()) { 237 if (earliestFireTime.isFinite()) {
189 SMILTime delay = earliestFireTime - elapsed(); 238 SMILTime delay = earliestFireTime - elapsed();
190 scheduleWakeUp(std::max(initialFrameDelay, delay.value()), Synchroni zeAnimations); 239 scheduleWakeUp(std::max(initialFrameDelay, delay.value()), Synchroni zeAnimations);
191 } 240 }
192 } 241 }
193 } 242 }
194 243
195 void SMILTimeContainer::pause() 244 void SMILTimeContainer::pause(bool freeze)
196 { 245 {
197 ASSERT(!isPaused()); 246 if (ImageAnimationPolicyNoAnimation == getAnimationPolicy())
247 return;
248
249 ASSERT(!isPaused() || isFrozen());
250
251 if (freeze)
252 m_animationState |= FrozenState;
253 else
254 m_animationState |= PausedState;
198 m_pauseTime = currentTime(); 255 m_pauseTime = currentTime();
199 256
200 if (m_beginTime) { 257 if (m_beginTime) {
201 m_accumulatedActiveTime += m_pauseTime - lastResumeTime(); 258 m_accumulatedActiveTime += m_pauseTime - lastResumeTime();
202 cancelAnimationFrame(); 259 cancelAnimationFrame();
203 } 260 }
204 m_resumeTime = 0; 261 m_resumeTime = 0;
262
263 // Cancel the animation policy timer.
264 cancelAnimationPolicyTimer();
205 } 265 }
206 266
207 void SMILTimeContainer::resume() 267 void SMILTimeContainer::resume()
208 { 268 {
269 if (ImageAnimationPolicyNoAnimation == getAnimationPolicy())
270 return;
271
209 ASSERT(isPaused()); 272 ASSERT(isPaused());
273
274 m_animationState &= ~PausedState;
210 m_resumeTime = currentTime(); 275 m_resumeTime = currentTime();
211 276
212 m_pauseTime = 0; 277 m_pauseTime = 0;
213 scheduleWakeUp(0, SynchronizeAnimations); 278 scheduleWakeUp(0, SynchronizeAnimations);
279
280 // Start the animation policy timer.
281 startAnimationPolicyTimer();
214 } 282 }
215 283
216 void SMILTimeContainer::setElapsed(SMILTime time) 284 void SMILTimeContainer::setElapsed(SMILTime time)
217 { 285 {
286 // If imageAnimationPolicy is 'once' or 'none',
287 // none: setElapsed is not allowed.
288 // once: paused state - setElapsed.
289 // unpaused state - start animation policy timer and setElapsed.
290 ImageAnimationPolicy animationPolicy = getAnimationPolicy();
291 if (animationPolicy == ImageAnimationPolicyNoAnimation)
292 return;
293 if (animationPolicy == ImageAnimationPolicyAnimateOnce) {
294 if (!(m_animationState & PausedState)) {
295 if (m_animationState & FrozenState)
296 resume();
297 startAnimationPolicyTimer();
298 }
299 }
300
218 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible. 301 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible.
219 if (!m_beginTime) { 302 if (!m_beginTime) {
220 m_presetStartTime = time.value(); 303 m_presetStartTime = time.value();
221 return; 304 return;
222 } 305 }
223 306
224 cancelAnimationFrame(); 307 cancelAnimationFrame();
225 308
226 double now = currentTime(); 309 double now = currentTime();
227 m_beginTime = now - time.value(); 310 m_beginTime = now - time.value();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 if (m_frameSchedulingState == FutureAnimationFrame) { 371 if (m_frameSchedulingState == FutureAnimationFrame) {
289 ASSERT(isTimelineRunning()); 372 ASSERT(isTimelineRunning());
290 m_frameSchedulingState = Idle; 373 m_frameSchedulingState = Idle;
291 serviceOnNextFrame(); 374 serviceOnNextFrame();
292 } else { 375 } else {
293 m_frameSchedulingState = Idle; 376 m_frameSchedulingState = Idle;
294 updateAnimationsAndScheduleFrameIfNeeded(elapsed()); 377 updateAnimationsAndScheduleFrameIfNeeded(elapsed());
295 } 378 }
296 } 379 }
297 380
381 void SMILTimeContainer::animationPolicyOnceTimerFired(Timer<SMILTimeContainer>*)
382 {
383 freezeTimeline();
384 }
385
298 void SMILTimeContainer::updateDocumentOrderIndexes() 386 void SMILTimeContainer::updateDocumentOrderIndexes()
299 { 387 {
300 unsigned timingElementCount = 0; 388 unsigned timingElementCount = 0;
301 for (SVGSMILElement& element : Traversal<SVGSMILElement>::descendantsOf(m_ow nerSVGElement)) 389 for (SVGSMILElement& element : Traversal<SVGSMILElement>::descendantsOf(m_ow nerSVGElement))
302 element.setDocumentOrderIndex(timingElementCount++); 390 element.setDocumentOrderIndex(timingElementCount++);
303 m_documentOrderIndexesDirty = false; 391 m_documentOrderIndexesDirty = false;
304 } 392 }
305 393
306 struct PriorityCompare { 394 struct PriorityCompare {
307 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {} 395 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {}
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 } 553 }
466 554
467 void SMILTimeContainer::trace(Visitor* visitor) 555 void SMILTimeContainer::trace(Visitor* visitor)
468 { 556 {
469 #if ENABLE(OILPAN) 557 #if ENABLE(OILPAN)
470 visitor->trace(m_scheduledAnimations); 558 visitor->trace(m_scheduledAnimations);
471 #endif 559 #endif
472 } 560 }
473 561
474 } 562 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698