Chromium Code Reviews| 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 |