| 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 14 matching lines...) Expand all Loading... |
| 25 | 25 |
| 26 #include "core/svg/animation/SMILTimeContainer.h" | 26 #include "core/svg/animation/SMILTimeContainer.h" |
| 27 | 27 |
| 28 #include "core/animation/AnimationClock.h" | 28 #include "core/animation/AnimationClock.h" |
| 29 #include "core/animation/DocumentTimeline.h" | 29 #include "core/animation/DocumentTimeline.h" |
| 30 #include "core/dom/ElementTraversal.h" | 30 #include "core/dom/ElementTraversal.h" |
| 31 #include "core/frame/FrameView.h" | 31 #include "core/frame/FrameView.h" |
| 32 #include "core/frame/Settings.h" | 32 #include "core/frame/Settings.h" |
| 33 #include "core/frame/UseCounter.h" | 33 #include "core/frame/UseCounter.h" |
| 34 #include "core/svg/SVGSVGElement.h" | 34 #include "core/svg/SVGSVGElement.h" |
| 35 #include "core/svg/animation/SMILTime.h" |
| 35 #include "core/svg/animation/SVGSMILElement.h" | 36 #include "core/svg/animation/SVGSMILElement.h" |
| 36 #include <algorithm> | 37 #include <algorithm> |
| 37 | 38 |
| 38 namespace blink { | 39 namespace blink { |
| 39 | 40 |
| 40 static const double initialFrameDelay = 0.025; | 41 static const double initialFrameDelay = 0.025; |
| 41 static const double animationPolicyOnceDuration = 3.000; | 42 static const double animationPolicyOnceDuration = 3.000; |
| 42 | 43 |
| 43 SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner) | 44 SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner) |
| 44 : m_presentationTime(0) | 45 : m_presentationTime(0) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 if (!isStarted()) | 127 if (!isStarted()) |
| 127 return; | 128 return; |
| 128 // Schedule updateAnimations() to be called asynchronously so multiple inter
vals | 129 // Schedule updateAnimations() to be called asynchronously so multiple inter
vals |
| 129 // can change with updateAnimations() only called once at the end. | 130 // can change with updateAnimations() only called once at the end. |
| 130 if (hasPendingSynchronization()) | 131 if (hasPendingSynchronization()) |
| 131 return; | 132 return; |
| 132 cancelAnimationFrame(); | 133 cancelAnimationFrame(); |
| 133 scheduleWakeUp(0, SynchronizeAnimations); | 134 scheduleWakeUp(0, SynchronizeAnimations); |
| 134 } | 135 } |
| 135 | 136 |
| 136 SMILTime SMILTimeContainer::elapsed() const | 137 double SMILTimeContainer::elapsed() const |
| 137 { | 138 { |
| 138 if (!isStarted()) | 139 if (!isStarted()) |
| 139 return 0; | 140 return 0; |
| 140 | 141 |
| 141 if (isPaused()) | 142 if (isPaused()) |
| 142 return m_presentationTime; | 143 return m_presentationTime; |
| 143 | 144 |
| 144 return m_presentationTime + (document().timeline().currentTimeInternal() - m
_referenceTime); | 145 return m_presentationTime + (document().timeline().currentTimeInternal() - m
_referenceTime); |
| 145 } | 146 } |
| 146 | 147 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 175 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) | 176 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) |
| 176 return; | 177 return; |
| 177 | 178 |
| 178 // Sample the document timeline to get a time reference for the "presentatio
n time". | 179 // Sample the document timeline to get a time reference for the "presentatio
n time". |
| 179 synchronizeToDocumentTimeline(); | 180 synchronizeToDocumentTimeline(); |
| 180 m_started = true; | 181 m_started = true; |
| 181 | 182 |
| 182 // If the "presentation time" is non-zero, the timeline was modified via | 183 // If the "presentation time" is non-zero, the timeline was modified via |
| 183 // setElapsed() before the document began. | 184 // setElapsed() before the document began. |
| 184 // In this case pass on 'seekToTime=true' to updateAnimations() to issue a s
eek. | 185 // In this case pass on 'seekToTime=true' to updateAnimations() to issue a s
eek. |
| 185 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presentationTime), m
_presentationTime ? true : false); | 186 SMILTime earliestFireTime = updateAnimations(m_presentationTime, m_presentat
ionTime ? true : false); |
| 186 if (!canScheduleFrame(earliestFireTime)) | 187 if (!canScheduleFrame(earliestFireTime)) |
| 187 return; | 188 return; |
| 188 // If the timeline is running, and there are pending animation updates, | 189 // If the timeline is running, and there are pending animation updates, |
| 189 // always perform the first update after the timeline was started using | 190 // always perform the first update after the timeline was started using |
| 190 // the wake-up mechanism. | 191 // the wake-up mechanism. |
| 191 SMILTime delay = earliestFireTime - m_presentationTime; | 192 double delayTime = earliestFireTime.value() - m_presentationTime; |
| 192 scheduleWakeUp(std::max(initialFrameDelay, delay.value()), SynchronizeAnimat
ions); | 193 scheduleWakeUp(std::max(initialFrameDelay, delayTime), SynchronizeAnimations
); |
| 193 } | 194 } |
| 194 | 195 |
| 195 void SMILTimeContainer::pause() | 196 void SMILTimeContainer::pause() |
| 196 { | 197 { |
| 197 if (!handleAnimationPolicy(CancelOnceTimer)) | 198 if (!handleAnimationPolicy(CancelOnceTimer)) |
| 198 return; | 199 return; |
| 199 DCHECK(!isPaused()); | 200 DCHECK(!isPaused()); |
| 200 | 201 |
| 201 if (isStarted()) { | 202 if (isStarted()) { |
| 202 m_presentationTime = elapsed().value(); | 203 m_presentationTime = elapsed(); |
| 203 cancelAnimationFrame(); | 204 cancelAnimationFrame(); |
| 204 } | 205 } |
| 205 // Update the flag after sampling elapsed(). | 206 // Update the flag after sampling elapsed(). |
| 206 m_paused = true; | 207 m_paused = true; |
| 207 } | 208 } |
| 208 | 209 |
| 209 void SMILTimeContainer::resume() | 210 void SMILTimeContainer::resume() |
| 210 { | 211 { |
| 211 if (!handleAnimationPolicy(RestartOnceTimer)) | 212 if (!handleAnimationPolicy(RestartOnceTimer)) |
| 212 return; | 213 return; |
| 213 DCHECK(isPaused()); | 214 DCHECK(isPaused()); |
| 214 | 215 |
| 215 m_paused = false; | 216 m_paused = false; |
| 216 | 217 |
| 217 if (isStarted()) | 218 if (isStarted()) |
| 218 synchronizeToDocumentTimeline(); | 219 synchronizeToDocumentTimeline(); |
| 219 | 220 |
| 220 scheduleWakeUp(0, SynchronizeAnimations); | 221 scheduleWakeUp(0, SynchronizeAnimations); |
| 221 } | 222 } |
| 222 | 223 |
| 223 void SMILTimeContainer::setElapsed(SMILTime time) | 224 void SMILTimeContainer::setElapsed(double elapsed) |
| 224 { | 225 { |
| 225 m_presentationTime = time.value(); | 226 m_presentationTime = elapsed; |
| 226 | 227 |
| 227 // If the document hasn't finished loading, |m_presentationTime| will be | 228 // If the document hasn't finished loading, |m_presentationTime| will be |
| 228 // used as the start time to seek to once it's possible. | 229 // used as the start time to seek to once it's possible. |
| 229 if (!isStarted()) | 230 if (!isStarted()) |
| 230 return; | 231 return; |
| 231 | 232 |
| 232 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) | 233 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) |
| 233 return; | 234 return; |
| 234 | 235 |
| 235 cancelAnimationFrame(); | 236 cancelAnimationFrame(); |
| 236 | 237 |
| 237 if (!isPaused()) | 238 if (!isPaused()) |
| 238 synchronizeToDocumentTimeline(); | 239 synchronizeToDocumentTimeline(); |
| 239 | 240 |
| 240 #if ENABLE(ASSERT) | 241 #if ENABLE(ASSERT) |
| 241 m_preventScheduledAnimationsChanges = true; | 242 m_preventScheduledAnimationsChanges = true; |
| 242 #endif | 243 #endif |
| 243 for (const auto& entry : m_scheduledAnimations) { | 244 for (const auto& entry : m_scheduledAnimations) { |
| 244 if (!entry.key.first) | 245 if (!entry.key.first) |
| 245 continue; | 246 continue; |
| 246 | 247 |
| 247 AnimationsLinkedHashSet* scheduled = entry.value.get(); | 248 AnimationsLinkedHashSet* scheduled = entry.value.get(); |
| 248 for (SVGSMILElement* element : *scheduled) | 249 for (SVGSMILElement* element : *scheduled) |
| 249 element->reset(); | 250 element->reset(); |
| 250 } | 251 } |
| 251 #if ENABLE(ASSERT) | 252 #if ENABLE(ASSERT) |
| 252 m_preventScheduledAnimationsChanges = false; | 253 m_preventScheduledAnimationsChanges = false; |
| 253 #endif | 254 #endif |
| 254 | 255 |
| 255 updateAnimationsAndScheduleFrameIfNeeded(time, true); | 256 updateAnimationsAndScheduleFrameIfNeeded(elapsed, true); |
| 256 } | 257 } |
| 257 | 258 |
| 258 void SMILTimeContainer::scheduleAnimationFrame(double delayTime) | 259 void SMILTimeContainer::scheduleAnimationFrame(double delayTime) |
| 259 { | 260 { |
| 260 DCHECK(std::isfinite(delayTime)); | 261 DCHECK(std::isfinite(delayTime)); |
| 261 DCHECK(isTimelineRunning()); | 262 DCHECK(isTimelineRunning()); |
| 262 DCHECK(!m_wakeupTimer.isActive()); | 263 DCHECK(!m_wakeupTimer.isActive()); |
| 263 | 264 |
| 264 if (delayTime < AnimationTimeline::s_minimumDelay) { | 265 if (delayTime < AnimationTimeline::s_minimumDelay) { |
| 265 serviceOnNextFrame(); | 266 serviceOnNextFrame(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 | 355 |
| 355 void SMILTimeContainer::updateDocumentOrderIndexes() | 356 void SMILTimeContainer::updateDocumentOrderIndexes() |
| 356 { | 357 { |
| 357 unsigned timingElementCount = 0; | 358 unsigned timingElementCount = 0; |
| 358 for (SVGSMILElement& element : Traversal<SVGSMILElement>::descendantsOf(owne
rSVGElement())) | 359 for (SVGSMILElement& element : Traversal<SVGSMILElement>::descendantsOf(owne
rSVGElement())) |
| 359 element.setDocumentOrderIndex(timingElementCount++); | 360 element.setDocumentOrderIndex(timingElementCount++); |
| 360 m_documentOrderIndexesDirty = false; | 361 m_documentOrderIndexesDirty = false; |
| 361 } | 362 } |
| 362 | 363 |
| 363 struct PriorityCompare { | 364 struct PriorityCompare { |
| 364 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {} | 365 PriorityCompare(double elapsed) : m_elapsed(elapsed) {} |
| 365 bool operator()(const Member<SVGSMILElement>& a, const Member<SVGSMILElement
>& b) | 366 bool operator()(const Member<SVGSMILElement>& a, const Member<SVGSMILElement
>& b) |
| 366 { | 367 { |
| 367 // FIXME: This should also consider possible timing relations between th
e elements. | 368 // FIXME: This should also consider possible timing relations between th
e elements. |
| 368 SMILTime aBegin = a->intervalBegin(); | 369 SMILTime aBegin = a->intervalBegin(); |
| 369 SMILTime bBegin = b->intervalBegin(); | 370 SMILTime bBegin = b->intervalBegin(); |
| 370 // Frozen elements need to be prioritized based on their previous interv
al. | 371 // Frozen elements need to be prioritized based on their previous interv
al. |
| 371 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin(
) : aBegin; | 372 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin(
) : aBegin; |
| 372 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin(
) : bBegin; | 373 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin(
) : bBegin; |
| 373 if (aBegin == bBegin) | 374 if (aBegin == bBegin) |
| 374 return a->documentOrderIndex() < b->documentOrderIndex(); | 375 return a->documentOrderIndex() < b->documentOrderIndex(); |
| 375 return aBegin < bBegin; | 376 return aBegin < bBegin; |
| 376 } | 377 } |
| 377 SMILTime m_elapsed; | 378 double m_elapsed; |
| 378 }; | 379 }; |
| 379 | 380 |
| 380 SVGSVGElement& SMILTimeContainer::ownerSVGElement() const | 381 SVGSVGElement& SMILTimeContainer::ownerSVGElement() const |
| 381 { | 382 { |
| 382 return *m_ownerSVGElement; | 383 return *m_ownerSVGElement; |
| 383 } | 384 } |
| 384 | 385 |
| 385 Document& SMILTimeContainer::document() const | 386 Document& SMILTimeContainer::document() const |
| 386 { | 387 { |
| 387 return ownerSVGElement().document(); | 388 return ownerSVGElement().document(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 408 { | 409 { |
| 409 // If there's synchronization pending (most likely due to syncbases), then | 410 // If there's synchronization pending (most likely due to syncbases), then |
| 410 // let that complete first before attempting to schedule a frame. | 411 // let that complete first before attempting to schedule a frame. |
| 411 if (hasPendingSynchronization()) | 412 if (hasPendingSynchronization()) |
| 412 return false; | 413 return false; |
| 413 if (!isTimelineRunning()) | 414 if (!isTimelineRunning()) |
| 414 return false; | 415 return false; |
| 415 return earliestFireTime.isFinite(); | 416 return earliestFireTime.isFinite(); |
| 416 } | 417 } |
| 417 | 418 |
| 418 void SMILTimeContainer::updateAnimationsAndScheduleFrameIfNeeded(SMILTime elapse
d, bool seekToTime) | 419 void SMILTimeContainer::updateAnimationsAndScheduleFrameIfNeeded(double elapsed,
bool seekToTime) |
| 419 { | 420 { |
| 420 if (!document().isActive()) | 421 if (!document().isActive()) |
| 421 return; | 422 return; |
| 422 | 423 |
| 423 SMILTime earliestFireTime = updateAnimations(elapsed, seekToTime); | 424 SMILTime earliestFireTime = updateAnimations(elapsed, seekToTime); |
| 424 if (!canScheduleFrame(earliestFireTime)) | 425 if (!canScheduleFrame(earliestFireTime)) |
| 425 return; | 426 return; |
| 426 SMILTime delay = earliestFireTime - elapsed; | 427 double delayTime = earliestFireTime.value() - elapsed; |
| 427 scheduleAnimationFrame(delay.value()); | 428 scheduleAnimationFrame(delayTime); |
| 428 } | 429 } |
| 429 | 430 |
| 430 SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) | 431 SMILTime SMILTimeContainer::updateAnimations(double elapsed, bool seekToTime) |
| 431 { | 432 { |
| 432 ASSERT(document().isActive()); | 433 ASSERT(document().isActive()); |
| 433 SMILTime earliestFireTime = SMILTime::unresolved(); | 434 SMILTime earliestFireTime = SMILTime::unresolved(); |
| 434 | 435 |
| 435 #if ENABLE(ASSERT) | 436 #if ENABLE(ASSERT) |
| 436 // This boolean will catch any attempts to schedule/unschedule scheduledAnim
ations during this critical section. | 437 // This boolean will catch any attempts to schedule/unschedule scheduledAnim
ations during this critical section. |
| 437 // Similarly, any elements removed will unschedule themselves, so this will
catch modification of animationsToApply. | 438 // Similarly, any elements removed will unschedule themselves, so this will
catch modification of animationsToApply. |
| 438 m_preventScheduledAnimationsChanges = true; | 439 m_preventScheduledAnimationsChanges = true; |
| 439 #endif | 440 #endif |
| 440 | 441 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 animDiscard->remove(IGNORE_EXCEPTION); | 525 animDiscard->remove(IGNORE_EXCEPTION); |
| 525 ASSERT(!animDiscard->isConnected()); | 526 ASSERT(!animDiscard->isConnected()); |
| 526 } | 527 } |
| 527 } | 528 } |
| 528 } | 529 } |
| 529 return earliestFireTime; | 530 return earliestFireTime; |
| 530 } | 531 } |
| 531 | 532 |
| 532 void SMILTimeContainer::advanceFrameForTesting() | 533 void SMILTimeContainer::advanceFrameForTesting() |
| 533 { | 534 { |
| 534 setElapsed(elapsed().value() + initialFrameDelay); | 535 setElapsed(elapsed() + initialFrameDelay); |
| 535 } | 536 } |
| 536 | 537 |
| 537 DEFINE_TRACE(SMILTimeContainer) | 538 DEFINE_TRACE(SMILTimeContainer) |
| 538 { | 539 { |
| 539 visitor->trace(m_scheduledAnimations); | 540 visitor->trace(m_scheduledAnimations); |
| 540 visitor->trace(m_ownerSVGElement); | 541 visitor->trace(m_ownerSVGElement); |
| 541 } | 542 } |
| 542 | 543 |
| 543 } // namespace blink | 544 } // namespace blink |
| OLD | NEW |