Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Unified Diff: Source/WebCore/svg/animation/SMILTimeContainer.cpp

Issue 11229037: Merge 129670 - Refactor SMILTimeContainer to maintain animation information instead of recalculatin… (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/1271/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/WebCore/svg/animation/SMILTimeContainer.h ('k') | Source/WebCore/svg/animation/SVGSMILElement.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/WebCore/svg/animation/SMILTimeContainer.cpp
===================================================================
--- Source/WebCore/svg/animation/SMILTimeContainer.cpp (revision 132107)
+++ Source/WebCore/svg/animation/SMILTimeContainer.cpp (working copy)
@@ -36,7 +36,7 @@
using namespace std;
namespace WebCore {
-
+
static const double animationFrameDelay = 0.025;
SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
@@ -47,38 +47,79 @@
, m_documentOrderIndexesDirty(false)
, m_timer(this, &SMILTimeContainer::timerFired)
, m_ownerSVGElement(owner)
+#ifndef NDEBUG
+ , m_preventScheduledAnimationsChanges(false)
+#endif
{
}
-void SMILTimeContainer::schedule(SVGSMILElement* animation)
+SMILTimeContainer::~SMILTimeContainer()
{
+#ifndef NDEBUG
+ ASSERT(!m_preventScheduledAnimationsChanges);
+#endif
+ deleteAllValues(m_scheduledAnimations);
+}
+
+void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
+{
ASSERT(animation->timeContainer() == this);
+ ASSERT(target);
+ ASSERT(animation->hasValidAttributeName());
+
+#ifndef NDEBUG
+ ASSERT(!m_preventScheduledAnimationsChanges);
+#endif
+
+ ElementAttributePair key(target, attributeName);
+ AnimationsVector* scheduled = m_scheduledAnimations.get(key);
+ if (!scheduled) {
+ scheduled = new AnimationsVector();
+ m_scheduledAnimations.set(key, scheduled);
+ }
+ ASSERT(!scheduled->contains(animation));
+ scheduled->append(animation);
+
SMILTime nextFireTime = animation->nextProgressTime();
- if (!nextFireTime.isFinite())
- return;
- m_scheduledAnimations.add(animation);
- startTimer(0);
+ if (nextFireTime.isFinite())
+ notifyIntervalsChanged();
}
-
-void SMILTimeContainer::unschedule(SVGSMILElement* animation)
+
+void SMILTimeContainer::unschedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
{
ASSERT(animation->timeContainer() == this);
- m_scheduledAnimations.remove(animation);
+#ifndef NDEBUG
+ ASSERT(!m_preventScheduledAnimationsChanges);
+#endif
+
+ ElementAttributePair key(target, attributeName);
+ AnimationsVector* scheduled = m_scheduledAnimations.get(key);
+ ASSERT(scheduled);
+ size_t idx = scheduled->find(animation);
+ ASSERT(idx != notFound);
+ scheduled->remove(idx);
}
+void SMILTimeContainer::notifyIntervalsChanged()
+{
+ // Schedule updateAnimations() to be called asynchronously so multiple intervals
+ // can change with updateAnimations() only called once at the end.
+ startTimer(0);
+}
+
SMILTime SMILTimeContainer::elapsed() const
{
if (!m_beginTime)
return 0;
return currentTime() - m_beginTime - m_accumulatedPauseTime;
}
-
+
bool SMILTimeContainer::isActive() const
{
return m_beginTime && !isPaused();
}
-
+
bool SMILTimeContainer::isPaused() const
{
return m_pauseTime;
@@ -144,10 +185,19 @@
if (m_pauseTime)
m_pauseTime = now;
- Vector<SVGSMILElement*> toReset;
- copyToVector(m_scheduledAnimations, toReset);
- for (unsigned n = 0; n < toReset.size(); ++n)
- toReset[n]->reset();
+#ifndef NDEBUG
+ m_preventScheduledAnimationsChanges = true;
+#endif
+ GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
+ for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it != end; ++it) {
+ AnimationsVector* scheduled = it->second;
+ unsigned size = scheduled->size();
+ for (unsigned n = 0; n < size; n++)
+ scheduled->at(n)->reset();
+ }
+#ifndef NDEBUG
+ m_preventScheduledAnimationsChanges = false;
+#endif
updateAnimations(time, true);
}
@@ -156,10 +206,10 @@
{
if (!m_beginTime || isPaused())
return;
-
+
if (!fireTime.isFinite())
return;
-
+
SMILTime delay = max(fireTime - elapsed(), minimumDelay);
m_timer.startOneShot(delay.value());
}
@@ -207,68 +257,71 @@
void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
{
- SMILTime earliersFireTime = SMILTime::unresolved();
+ SMILTime earliestFireTime = SMILTime::unresolved();
- Vector<SVGSMILElement*> toAnimate;
- copyToVector(m_scheduledAnimations, toAnimate);
+#ifndef NDEBUG
+ // This boolean will catch any attempts to schedule/unschedule scheduledAnimations during this critical section.
+ // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply.
+ m_preventScheduledAnimationsChanges = true;
+#endif
- // Sort according to priority. Elements with later begin time have higher priority.
- // In case of a tie, document order decides.
- // FIXME: This should also consider timing relationships between the elements. Dependents
- // have higher priority.
- sortByPriority(toAnimate, elapsed);
+ AnimationsVector animationsToApply;
+ GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
+ for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it != end; ++it) {
+ AnimationsVector* scheduled = it->second;
- // Calculate animation contributions.
- typedef pair<SVGElement*, QualifiedName> ElementAttributePair;
- typedef HashMap<ElementAttributePair, SVGSMILElement*> ResultElementMap;
- ResultElementMap resultsElements;
- for (unsigned n = 0; n < toAnimate.size(); ++n) {
- SVGSMILElement* animation = toAnimate[n];
- ASSERT(animation->timeContainer() == this);
+ // Sort according to priority. Elements with later begin time have higher priority.
+ // In case of a tie, document order decides.
+ // FIXME: This should also consider timing relationships between the elements. Dependents
+ // have higher priority.
+ sortByPriority(*scheduled, elapsed);
- SVGElement* targetElement = animation->targetElement();
- if (!targetElement)
- continue;
+ SVGSMILElement* resultElement = 0;
+ unsigned size = scheduled->size();
+ for (unsigned n = 0; n < size; n++) {
+ SVGSMILElement* animation = scheduled->at(n);
+ ASSERT(animation->timeContainer() == this);
+ ASSERT(animation->targetElement());
+ ASSERT(animation->hasValidAttributeName());
- QualifiedName attributeName = animation->attributeName();
- if (attributeName == anyQName()) {
- if (animation->hasTagName(SVGNames::animateMotionTag))
- attributeName = SVGNames::animateMotionTag;
- else
- continue;
- }
+ // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair.
+ if (!resultElement) {
+ if (!animation->hasValidAttributeType())
+ continue;
+ resultElement = animation;
+ }
- // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair.
- ElementAttributePair key(targetElement, attributeName);
- SVGSMILElement* resultElement = resultsElements.get(key);
- if (!resultElement) {
- if (!animation->hasValidAttributeType())
- continue;
- resultElement = animation;
- } else
- ASSERT(resultElement != animation);
+ // This will calculate the contribution from the animation and add it to the resultsElement.
+ if (!animation->progress(elapsed, resultElement, seekToTime) && resultElement == animation)
+ resultElement = 0;
- // This will calculate the contribution from the animation and add it to the resultsElement.
- if (animation->progress(elapsed, resultElement, seekToTime) && resultElement == animation)
- resultsElements.add(key, resultElement);
+ SMILTime nextFireTime = animation->nextProgressTime();
+ if (nextFireTime.isFinite())
+ earliestFireTime = min(nextFireTime, earliestFireTime);
+ }
- SMILTime nextFireTime = animation->nextProgressTime();
- if (nextFireTime.isFinite())
- earliersFireTime = min(nextFireTime, earliersFireTime);
+ if (resultElement)
+ animationsToApply.append(resultElement);
}
- unsigned resultsToApplySize = resultsElements.size();
- if (!resultsToApplySize) {
- startTimer(earliersFireTime, animationFrameDelay);
+ unsigned animationsToApplySize = animationsToApply.size();
+ if (!animationsToApplySize) {
+#ifndef NDEBUG
+ m_preventScheduledAnimationsChanges = false;
+#endif
+ startTimer(earliestFireTime, animationFrameDelay);
return;
}
// Apply results to target elements.
- ResultElementMap::iterator end = resultsElements.end();
- for (ResultElementMap::iterator it = resultsElements.begin(); it != end; ++it)
- it->second->applyResultsToTarget();
+ for (unsigned i = 0; i < animationsToApplySize; ++i)
+ animationsToApply[i]->applyResultsToTarget();
- startTimer(earliersFireTime, animationFrameDelay);
+#ifndef NDEBUG
+ m_preventScheduledAnimationsChanges = false;
+#endif
+
+ startTimer(earliestFireTime, animationFrameDelay);
Document::updateStyleForAllDocuments();
}
« no previous file with comments | « Source/WebCore/svg/animation/SMILTimeContainer.h ('k') | Source/WebCore/svg/animation/SVGSMILElement.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698