OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |