| 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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 } | 121 } |
| 122 | 122 |
| 123 bool SMILTimeContainer::hasPendingSynchronization() const { | 123 bool SMILTimeContainer::hasPendingSynchronization() const { |
| 124 return m_frameSchedulingState == SynchronizeAnimations && | 124 return m_frameSchedulingState == SynchronizeAnimations && |
| 125 m_wakeupTimer.isActive() && !m_wakeupTimer.nextFireInterval(); | 125 m_wakeupTimer.isActive() && !m_wakeupTimer.nextFireInterval(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 void SMILTimeContainer::notifyIntervalsChanged() { | 128 void SMILTimeContainer::notifyIntervalsChanged() { |
| 129 if (!isStarted()) | 129 if (!isStarted()) |
| 130 return; | 130 return; |
| 131 // Schedule updateAnimations() to be called asynchronously so multiple interva
ls | 131 // Schedule updateAnimations() to be called asynchronously so multiple |
| 132 // can change with updateAnimations() only called once at the end. | 132 // intervals can change with updateAnimations() only called once at the end. |
| 133 if (hasPendingSynchronization()) | 133 if (hasPendingSynchronization()) |
| 134 return; | 134 return; |
| 135 cancelAnimationFrame(); | 135 cancelAnimationFrame(); |
| 136 scheduleWakeUp(0, SynchronizeAnimations); | 136 scheduleWakeUp(0, SynchronizeAnimations); |
| 137 } | 137 } |
| 138 | 138 |
| 139 double SMILTimeContainer::elapsed() const { | 139 double SMILTimeContainer::elapsed() const { |
| 140 if (!isStarted()) | 140 if (!isStarted()) |
| 141 return 0; | 141 return 0; |
| 142 | 142 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 166 | 166 |
| 167 void SMILTimeContainer::start() { | 167 void SMILTimeContainer::start() { |
| 168 RELEASE_ASSERT(!isStarted()); | 168 RELEASE_ASSERT(!isStarted()); |
| 169 | 169 |
| 170 if (!document().isActive()) | 170 if (!document().isActive()) |
| 171 return; | 171 return; |
| 172 | 172 |
| 173 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) | 173 if (!handleAnimationPolicy(RestartOnceTimerIfNotPaused)) |
| 174 return; | 174 return; |
| 175 | 175 |
| 176 // Sample the document timeline to get a time reference for the "presentation
time". | 176 // Sample the document timeline to get a time reference for the "presentation |
| 177 // time". |
| 177 synchronizeToDocumentTimeline(); | 178 synchronizeToDocumentTimeline(); |
| 178 m_started = true; | 179 m_started = true; |
| 179 | 180 |
| 180 // If the "presentation time" is non-zero, the timeline was modified via | 181 // If the "presentation time" is non-zero, the timeline was modified via |
| 181 // setElapsed() before the document began. | 182 // setElapsed() before the document began. In this case pass on |
| 182 // In this case pass on 'seekToTime=true' to updateAnimations() to issue a see
k. | 183 // 'seekToTime=true' to updateAnimations() to issue a seek. |
| 183 SMILTime earliestFireTime = | 184 SMILTime earliestFireTime = |
| 184 updateAnimations(m_presentationTime, m_presentationTime ? true : false); | 185 updateAnimations(m_presentationTime, m_presentationTime ? true : false); |
| 185 if (!canScheduleFrame(earliestFireTime)) | 186 if (!canScheduleFrame(earliestFireTime)) |
| 186 return; | 187 return; |
| 187 // If the timeline is running, and there are pending animation updates, | 188 // If the timeline is running, and there are pending animation updates, |
| 188 // always perform the first update after the timeline was started using | 189 // always perform the first update after the timeline was started using |
| 189 // the wake-up mechanism. | 190 // the wake-up mechanism. |
| 190 double delayTime = earliestFireTime.value() - m_presentationTime; | 191 double delayTime = earliestFireTime.value() - m_presentationTime; |
| 191 scheduleWakeUp(std::max(initialFrameDelay, delayTime), SynchronizeAnimations); | 192 scheduleWakeUp(std::max(initialFrameDelay, delayTime), SynchronizeAnimations); |
| 192 } | 193 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 for (SVGSMILElement& element : | 353 for (SVGSMILElement& element : |
| 353 Traversal<SVGSMILElement>::descendantsOf(ownerSVGElement())) | 354 Traversal<SVGSMILElement>::descendantsOf(ownerSVGElement())) |
| 354 element.setDocumentOrderIndex(timingElementCount++); | 355 element.setDocumentOrderIndex(timingElementCount++); |
| 355 m_documentOrderIndexesDirty = false; | 356 m_documentOrderIndexesDirty = false; |
| 356 } | 357 } |
| 357 | 358 |
| 358 struct PriorityCompare { | 359 struct PriorityCompare { |
| 359 PriorityCompare(double elapsed) : m_elapsed(elapsed) {} | 360 PriorityCompare(double elapsed) : m_elapsed(elapsed) {} |
| 360 bool operator()(const Member<SVGSMILElement>& a, | 361 bool operator()(const Member<SVGSMILElement>& a, |
| 361 const Member<SVGSMILElement>& b) { | 362 const Member<SVGSMILElement>& b) { |
| 362 // FIXME: This should also consider possible timing relations between the el
ements. | 363 // FIXME: This should also consider possible timing relations between the |
| 364 // elements. |
| 363 SMILTime aBegin = a->intervalBegin(); | 365 SMILTime aBegin = a->intervalBegin(); |
| 364 SMILTime bBegin = b->intervalBegin(); | 366 SMILTime bBegin = b->intervalBegin(); |
| 365 // Frozen elements need to be prioritized based on their previous interval. | 367 // Frozen elements need to be prioritized based on their previous interval. |
| 366 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin() | 368 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin() |
| 367 : aBegin; | 369 : aBegin; |
| 368 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin() | 370 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin() |
| 369 : bBegin; | 371 : bBegin; |
| 370 if (aBegin == bBegin) | 372 if (aBegin == bBegin) |
| 371 return a->documentOrderIndex() < b->documentOrderIndex(); | 373 return a->documentOrderIndex() < b->documentOrderIndex(); |
| 372 return aBegin < bBegin; | 374 return aBegin < bBegin; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 return; | 420 return; |
| 419 double delayTime = earliestFireTime.value() - elapsed; | 421 double delayTime = earliestFireTime.value() - elapsed; |
| 420 scheduleAnimationFrame(delayTime); | 422 scheduleAnimationFrame(delayTime); |
| 421 } | 423 } |
| 422 | 424 |
| 423 SMILTime SMILTimeContainer::updateAnimations(double elapsed, bool seekToTime) { | 425 SMILTime SMILTimeContainer::updateAnimations(double elapsed, bool seekToTime) { |
| 424 ASSERT(document().isActive()); | 426 ASSERT(document().isActive()); |
| 425 SMILTime earliestFireTime = SMILTime::unresolved(); | 427 SMILTime earliestFireTime = SMILTime::unresolved(); |
| 426 | 428 |
| 427 #if ENABLE(ASSERT) | 429 #if ENABLE(ASSERT) |
| 428 // This boolean will catch any attempts to schedule/unschedule scheduledAnimat
ions during this critical section. | 430 // This boolean will catch any attempts to schedule/unschedule |
| 429 // Similarly, any elements removed will unschedule themselves, so this will ca
tch modification of animationsToApply. | 431 // scheduledAnimations during this critical section. Similarly, any elements |
| 432 // removed will unschedule themselves, so this will catch modification of |
| 433 // animationsToApply. |
| 430 m_preventScheduledAnimationsChanges = true; | 434 m_preventScheduledAnimationsChanges = true; |
| 431 #endif | 435 #endif |
| 432 | 436 |
| 433 if (m_documentOrderIndexesDirty) | 437 if (m_documentOrderIndexesDirty) |
| 434 updateDocumentOrderIndexes(); | 438 updateDocumentOrderIndexes(); |
| 435 | 439 |
| 436 HeapHashSet<ElementAttributePair> invalidKeys; | 440 HeapHashSet<ElementAttributePair> invalidKeys; |
| 437 using AnimationsVector = HeapVector<Member<SVGSMILElement>>; | 441 using AnimationsVector = HeapVector<Member<SVGSMILElement>>; |
| 438 AnimationsVector animationsToApply; | 442 AnimationsVector animationsToApply; |
| 439 AnimationsVector scheduledAnimationsInSameGroup; | 443 AnimationsVector scheduledAnimationsInSameGroup; |
| 440 for (const auto& entry : m_scheduledAnimations) { | 444 for (const auto& entry : m_scheduledAnimations) { |
| 441 if (!entry.key.first || entry.value->isEmpty()) { | 445 if (!entry.key.first || entry.value->isEmpty()) { |
| 442 invalidKeys.add(entry.key); | 446 invalidKeys.add(entry.key); |
| 443 continue; | 447 continue; |
| 444 } | 448 } |
| 445 | 449 |
| 446 // Sort according to priority. Elements with later begin time have higher pr
iority. | 450 // Sort according to priority. Elements with later begin time have higher |
| 447 // In case of a tie, document order decides. | 451 // priority. In case of a tie, document order decides. |
| 448 // FIXME: This should also consider timing relationships between the element
s. Dependents | 452 // FIXME: This should also consider timing relationships between the |
| 449 // have higher priority. | 453 // elements. Dependents have higher priority. |
| 450 copyToVector(*entry.value, scheduledAnimationsInSameGroup); | 454 copyToVector(*entry.value, scheduledAnimationsInSameGroup); |
| 451 std::sort(scheduledAnimationsInSameGroup.begin(), | 455 std::sort(scheduledAnimationsInSameGroup.begin(), |
| 452 scheduledAnimationsInSameGroup.end(), PriorityCompare(elapsed)); | 456 scheduledAnimationsInSameGroup.end(), PriorityCompare(elapsed)); |
| 453 | 457 |
| 454 AnimationsVector sandwich; | 458 AnimationsVector sandwich; |
| 455 for (const auto& itAnimation : scheduledAnimationsInSameGroup) { | 459 for (const auto& itAnimation : scheduledAnimationsInSameGroup) { |
| 456 SVGSMILElement* animation = itAnimation.get(); | 460 SVGSMILElement* animation = itAnimation.get(); |
| 457 ASSERT(animation->timeContainer() == this); | 461 ASSERT(animation->timeContainer() == this); |
| 458 ASSERT(animation->targetElement()); | 462 ASSERT(animation->targetElement()); |
| 459 ASSERT(animation->hasValidAttributeName()); | 463 ASSERT(animation->hasValidAttributeName()); |
| 460 ASSERT(animation->hasValidAttributeType()); | 464 ASSERT(animation->hasValidAttributeType()); |
| 461 | 465 |
| 462 // This will calculate the contribution from the animation and update timi
ng. | 466 // This will calculate the contribution from the animation and update |
| 467 // timing. |
| 463 if (animation->progress(elapsed, seekToTime)) { | 468 if (animation->progress(elapsed, seekToTime)) { |
| 464 sandwich.append(animation); | 469 sandwich.append(animation); |
| 465 } else { | 470 } else { |
| 466 animation->clearAnimatedType(); | 471 animation->clearAnimatedType(); |
| 467 } | 472 } |
| 468 | 473 |
| 469 SMILTime nextFireTime = animation->nextProgressTime(); | 474 SMILTime nextFireTime = animation->nextProgressTime(); |
| 470 if (nextFireTime.isFinite()) | 475 if (nextFireTime.isFinite()) |
| 471 earliestFireTime = std::min(nextFireTime, earliestFireTime); | 476 earliestFireTime = std::min(nextFireTime, earliestFireTime); |
| 472 } | 477 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 void SMILTimeContainer::advanceFrameForTesting() { | 535 void SMILTimeContainer::advanceFrameForTesting() { |
| 531 setElapsed(elapsed() + initialFrameDelay); | 536 setElapsed(elapsed() + initialFrameDelay); |
| 532 } | 537 } |
| 533 | 538 |
| 534 DEFINE_TRACE(SMILTimeContainer) { | 539 DEFINE_TRACE(SMILTimeContainer) { |
| 535 visitor->trace(m_scheduledAnimations); | 540 visitor->trace(m_scheduledAnimations); |
| 536 visitor->trace(m_ownerSVGElement); | 541 visitor->trace(m_ownerSVGElement); |
| 537 } | 542 } |
| 538 | 543 |
| 539 } // namespace blink | 544 } // namespace blink |
| OLD | NEW |