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) |
60 , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired) | 62 , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired) |
| 63 , m_animationPolicyOnceTimer(this, &SMILTimeContainer::animationPolicyTimerF
ired) |
61 , m_ownerSVGElement(owner) | 64 , m_ownerSVGElement(owner) |
62 #if ENABLE(ASSERT) | 65 #if ENABLE(ASSERT) |
63 , m_preventScheduledAnimationsChanges(false) | 66 , m_preventScheduledAnimationsChanges(false) |
64 #endif | 67 #endif |
65 { | 68 { |
66 } | 69 } |
67 | 70 |
68 SMILTimeContainer::~SMILTimeContainer() | 71 SMILTimeContainer::~SMILTimeContainer() |
69 { | 72 { |
70 cancelAnimationFrame(); | 73 cancelAnimationFrame(); |
| 74 cancelAnimationPolicyTimer(); |
71 ASSERT(!m_wakeupTimer.isActive()); | 75 ASSERT(!m_wakeupTimer.isActive()); |
72 #if ENABLE(ASSERT) | 76 #if ENABLE(ASSERT) |
73 ASSERT(!m_preventScheduledAnimationsChanges); | 77 ASSERT(!m_preventScheduledAnimationsChanges); |
74 #endif | 78 #endif |
75 } | 79 } |
76 | 80 |
77 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target,
const QualifiedName& attributeName) | 81 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target,
const QualifiedName& attributeName) |
78 { | 82 { |
79 ASSERT(animation->timeContainer() == this); | 83 ASSERT(animation->timeContainer() == this); |
80 ASSERT(target); | 84 ASSERT(target); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 return 0; | 149 return 0; |
146 | 150 |
147 if (isPaused()) | 151 if (isPaused()) |
148 return m_accumulatedActiveTime; | 152 return m_accumulatedActiveTime; |
149 | 153 |
150 return currentTime() + m_accumulatedActiveTime - lastResumeTime(); | 154 return currentTime() + m_accumulatedActiveTime - lastResumeTime(); |
151 } | 155 } |
152 | 156 |
153 bool SMILTimeContainer::isPaused() const | 157 bool SMILTimeContainer::isPaused() const |
154 { | 158 { |
155 return m_pauseTime; | 159 // If animation policy is "none", it is always paused. |
| 160 return m_pauseTime || animationPolicy() == ImageAnimationPolicyNoAnimation; |
156 } | 161 } |
157 | 162 |
158 bool SMILTimeContainer::isStarted() const | 163 bool SMILTimeContainer::isStarted() const |
159 { | 164 { |
160 return m_beginTime; | 165 return m_beginTime; |
161 } | 166 } |
162 | 167 |
163 void SMILTimeContainer::begin() | 168 void SMILTimeContainer::begin() |
164 { | 169 { |
165 RELEASE_ASSERT(!m_beginTime); | 170 RELEASE_ASSERT(!m_beginTime); |
| 171 |
| 172 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) |
| 173 return; |
| 174 |
166 double now = currentTime(); | 175 double now = currentTime(); |
167 | 176 |
168 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed()
before the document began. | 177 // 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(). | 178 // In this case pass on 'seekToTime=true' to updateAnimations(). |
170 m_beginTime = now - m_presetStartTime; | 179 m_beginTime = now - m_presetStartTime; |
171 #if !ENABLE(OILPAN) | 180 #if !ENABLE(OILPAN) |
172 DiscardScope discardScope(m_ownerSVGElement); | 181 DiscardScope discardScope(m_ownerSVGElement); |
173 #endif | 182 #endif |
174 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_
presetStartTime ? true : false); | 183 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_
presetStartTime ? true : false); |
175 m_presetStartTime = 0; | 184 m_presetStartTime = 0; |
(...skipping 11 matching lines...) Expand all Loading... |
187 // the wake-up mechanism. | 196 // the wake-up mechanism. |
188 if (earliestFireTime.isFinite()) { | 197 if (earliestFireTime.isFinite()) { |
189 SMILTime delay = earliestFireTime - elapsed(); | 198 SMILTime delay = earliestFireTime - elapsed(); |
190 scheduleWakeUp(std::max(initialFrameDelay, delay.value()), Synchroni
zeAnimations); | 199 scheduleWakeUp(std::max(initialFrameDelay, delay.value()), Synchroni
zeAnimations); |
191 } | 200 } |
192 } | 201 } |
193 } | 202 } |
194 | 203 |
195 void SMILTimeContainer::pause() | 204 void SMILTimeContainer::pause() |
196 { | 205 { |
| 206 if (!handleAnimationPolicy(CancelOnceTimer)) |
| 207 return; |
| 208 |
197 ASSERT(!isPaused()); | 209 ASSERT(!isPaused()); |
198 m_pauseTime = currentTime(); | 210 m_pauseTime = currentTime(); |
199 | 211 |
200 if (m_beginTime) { | 212 if (m_beginTime) { |
201 m_accumulatedActiveTime += m_pauseTime - lastResumeTime(); | 213 m_accumulatedActiveTime += m_pauseTime - lastResumeTime(); |
202 cancelAnimationFrame(); | 214 cancelAnimationFrame(); |
203 } | 215 } |
204 m_resumeTime = 0; | 216 m_resumeTime = 0; |
205 } | 217 } |
206 | 218 |
207 void SMILTimeContainer::resume() | 219 void SMILTimeContainer::resume() |
208 { | 220 { |
| 221 if (!handleAnimationPolicy(RestartOnceTimer)) |
| 222 return; |
| 223 |
209 ASSERT(isPaused()); | 224 ASSERT(isPaused()); |
210 m_resumeTime = currentTime(); | 225 m_resumeTime = currentTime(); |
211 | 226 |
212 m_pauseTime = 0; | 227 m_pauseTime = 0; |
213 scheduleWakeUp(0, SynchronizeAnimations); | 228 scheduleWakeUp(0, SynchronizeAnimations); |
214 } | 229 } |
215 | 230 |
216 void SMILTimeContainer::setElapsed(SMILTime time) | 231 void SMILTimeContainer::setElapsed(SMILTime time) |
217 { | 232 { |
218 // If the documment didn't begin yet, record a new start time, we'll seek to
once its possible. | 233 // If the documment didn't begin yet, record a new start time, we'll seek to
once its possible. |
219 if (!m_beginTime) { | 234 if (!m_beginTime) { |
220 m_presetStartTime = time.value(); | 235 m_presetStartTime = time.value(); |
221 return; | 236 return; |
222 } | 237 } |
223 | 238 |
| 239 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) |
| 240 return; |
| 241 |
224 cancelAnimationFrame(); | 242 cancelAnimationFrame(); |
225 | 243 |
226 double now = currentTime(); | 244 double now = currentTime(); |
227 m_beginTime = now - time.value(); | 245 m_beginTime = now - time.value(); |
228 m_resumeTime = 0; | 246 m_resumeTime = 0; |
229 if (m_pauseTime) { | 247 if (m_pauseTime) { |
230 m_pauseTime = now; | 248 m_pauseTime = now; |
231 m_accumulatedActiveTime = time.value(); | 249 m_accumulatedActiveTime = time.value(); |
232 } else { | 250 } else { |
233 m_accumulatedActiveTime = 0; | 251 m_accumulatedActiveTime = 0; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 if (m_frameSchedulingState == FutureAnimationFrame) { | 306 if (m_frameSchedulingState == FutureAnimationFrame) { |
289 ASSERT(isTimelineRunning()); | 307 ASSERT(isTimelineRunning()); |
290 m_frameSchedulingState = Idle; | 308 m_frameSchedulingState = Idle; |
291 serviceOnNextFrame(); | 309 serviceOnNextFrame(); |
292 } else { | 310 } else { |
293 m_frameSchedulingState = Idle; | 311 m_frameSchedulingState = Idle; |
294 updateAnimationsAndScheduleFrameIfNeeded(elapsed()); | 312 updateAnimationsAndScheduleFrameIfNeeded(elapsed()); |
295 } | 313 } |
296 } | 314 } |
297 | 315 |
| 316 void SMILTimeContainer::scheduleAnimationPolicyTimer() |
| 317 { |
| 318 m_animationPolicyOnceTimer.startOneShot(animationPolicyOnceDuration, FROM_HE
RE); |
| 319 } |
| 320 |
| 321 void SMILTimeContainer::cancelAnimationPolicyTimer() |
| 322 { |
| 323 if (m_animationPolicyOnceTimer.isActive()) |
| 324 m_animationPolicyOnceTimer.stop(); |
| 325 } |
| 326 |
| 327 void SMILTimeContainer::animationPolicyTimerFired(Timer<SMILTimeContainer>*) |
| 328 { |
| 329 pause(); |
| 330 } |
| 331 |
| 332 ImageAnimationPolicy SMILTimeContainer::animationPolicy() const |
| 333 { |
| 334 Settings* settings = document().settings(); |
| 335 if (!settings) |
| 336 return ImageAnimationPolicyAllowed; |
| 337 |
| 338 return settings->imageAnimationPolicy(); |
| 339 } |
| 340 |
| 341 bool SMILTimeContainer::handleAnimationPolicy(AnimationPolicyOnceAction onceActi
on) |
| 342 { |
| 343 ImageAnimationPolicy policy = animationPolicy(); |
| 344 // If the animation policy is "none", control is not allowed. |
| 345 // returns false to exit flow. |
| 346 if (policy == ImageAnimationPolicyNoAnimation) |
| 347 return false; |
| 348 // If the animation policy is "once", |
| 349 if (policy == ImageAnimationPolicyAnimateOnce) { |
| 350 switch (onceAction) { |
| 351 case RestartOnceTimerIfNotPaused: |
| 352 if (isPaused()) |
| 353 break; |
| 354 /* fall through */ |
| 355 case RestartOnceTimer: |
| 356 scheduleAnimationPolicyTimer(); |
| 357 break; |
| 358 case CancelOnceTimer: |
| 359 cancelAnimationPolicyTimer(); |
| 360 break; |
| 361 } |
| 362 } |
| 363 return true; |
| 364 } |
| 365 |
298 void SMILTimeContainer::updateDocumentOrderIndexes() | 366 void SMILTimeContainer::updateDocumentOrderIndexes() |
299 { | 367 { |
300 unsigned timingElementCount = 0; | 368 unsigned timingElementCount = 0; |
301 for (SVGSMILElement& element : Traversal<SVGSMILElement>::descendantsOf(m_ow
nerSVGElement)) | 369 for (SVGSMILElement& element : Traversal<SVGSMILElement>::descendantsOf(m_ow
nerSVGElement)) |
302 element.setDocumentOrderIndex(timingElementCount++); | 370 element.setDocumentOrderIndex(timingElementCount++); |
303 m_documentOrderIndexesDirty = false; | 371 m_documentOrderIndexesDirty = false; |
304 } | 372 } |
305 | 373 |
306 struct PriorityCompare { | 374 struct PriorityCompare { |
307 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {} | 375 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {} |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 } | 533 } |
466 | 534 |
467 void SMILTimeContainer::trace(Visitor* visitor) | 535 void SMILTimeContainer::trace(Visitor* visitor) |
468 { | 536 { |
469 #if ENABLE(OILPAN) | 537 #if ENABLE(OILPAN) |
470 visitor->trace(m_scheduledAnimations); | 538 visitor->trace(m_scheduledAnimations); |
471 #endif | 539 #endif |
472 } | 540 } |
473 | 541 |
474 } | 542 } |
OLD | NEW |