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

Side by Side 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 unified diff | Download patch
OLDNEW
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 18 matching lines...) Expand all
29 #if ENABLE(SVG) 29 #if ENABLE(SVG)
30 #include "Document.h" 30 #include "Document.h"
31 #include "SVGNames.h" 31 #include "SVGNames.h"
32 #include "SVGSMILElement.h" 32 #include "SVGSMILElement.h"
33 #include "SVGSVGElement.h" 33 #include "SVGSVGElement.h"
34 #include <wtf/CurrentTime.h> 34 #include <wtf/CurrentTime.h>
35 35
36 using namespace std; 36 using namespace std;
37 37
38 namespace WebCore { 38 namespace WebCore {
39 39
40 static const double animationFrameDelay = 0.025; 40 static const double animationFrameDelay = 0.025;
41 41
42 SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner) 42 SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
43 : m_beginTime(0) 43 : m_beginTime(0)
44 , m_pauseTime(0) 44 , m_pauseTime(0)
45 , m_accumulatedPauseTime(0) 45 , m_accumulatedPauseTime(0)
46 , m_presetStartTime(0) 46 , m_presetStartTime(0)
47 , m_documentOrderIndexesDirty(false) 47 , m_documentOrderIndexesDirty(false)
48 , m_timer(this, &SMILTimeContainer::timerFired) 48 , m_timer(this, &SMILTimeContainer::timerFired)
49 , m_ownerSVGElement(owner) 49 , m_ownerSVGElement(owner)
50 #ifndef NDEBUG
51 , m_preventScheduledAnimationsChanges(false)
52 #endif
50 { 53 {
51 } 54 }
52 55
53 void SMILTimeContainer::schedule(SVGSMILElement* animation) 56 SMILTimeContainer::~SMILTimeContainer()
57 {
58 #ifndef NDEBUG
59 ASSERT(!m_preventScheduledAnimationsChanges);
60 #endif
61 deleteAllValues(m_scheduledAnimations);
62 }
63
64 void SMILTimeContainer::schedule(SVGSMILElement* animation, SVGElement* target, const QualifiedName& attributeName)
54 { 65 {
55 ASSERT(animation->timeContainer() == this); 66 ASSERT(animation->timeContainer() == this);
67 ASSERT(target);
68 ASSERT(animation->hasValidAttributeName());
69
70 #ifndef NDEBUG
71 ASSERT(!m_preventScheduledAnimationsChanges);
72 #endif
73
74 ElementAttributePair key(target, attributeName);
75 AnimationsVector* scheduled = m_scheduledAnimations.get(key);
76 if (!scheduled) {
77 scheduled = new AnimationsVector();
78 m_scheduledAnimations.set(key, scheduled);
79 }
80 ASSERT(!scheduled->contains(animation));
81 scheduled->append(animation);
82
56 SMILTime nextFireTime = animation->nextProgressTime(); 83 SMILTime nextFireTime = animation->nextProgressTime();
57 if (!nextFireTime.isFinite()) 84 if (nextFireTime.isFinite())
58 return; 85 notifyIntervalsChanged();
59 m_scheduledAnimations.add(animation);
60 startTimer(0);
61 } 86 }
62 87
63 void SMILTimeContainer::unschedule(SVGSMILElement* animation) 88 void SMILTimeContainer::unschedule(SVGSMILElement* animation, SVGElement* target , const QualifiedName& attributeName)
64 { 89 {
65 ASSERT(animation->timeContainer() == this); 90 ASSERT(animation->timeContainer() == this);
66 91
67 m_scheduledAnimations.remove(animation); 92 #ifndef NDEBUG
93 ASSERT(!m_preventScheduledAnimationsChanges);
94 #endif
95
96 ElementAttributePair key(target, attributeName);
97 AnimationsVector* scheduled = m_scheduledAnimations.get(key);
98 ASSERT(scheduled);
99 size_t idx = scheduled->find(animation);
100 ASSERT(idx != notFound);
101 scheduled->remove(idx);
102 }
103
104 void SMILTimeContainer::notifyIntervalsChanged()
105 {
106 // Schedule updateAnimations() to be called asynchronously so multiple inter vals
107 // can change with updateAnimations() only called once at the end.
108 startTimer(0);
68 } 109 }
69 110
70 SMILTime SMILTimeContainer::elapsed() const 111 SMILTime SMILTimeContainer::elapsed() const
71 { 112 {
72 if (!m_beginTime) 113 if (!m_beginTime)
73 return 0; 114 return 0;
74 return currentTime() - m_beginTime - m_accumulatedPauseTime; 115 return currentTime() - m_beginTime - m_accumulatedPauseTime;
75 } 116 }
76 117
77 bool SMILTimeContainer::isActive() const 118 bool SMILTimeContainer::isActive() const
78 { 119 {
79 return m_beginTime && !isPaused(); 120 return m_beginTime && !isPaused();
80 } 121 }
81 122
82 bool SMILTimeContainer::isPaused() const 123 bool SMILTimeContainer::isPaused() const
83 { 124 {
84 return m_pauseTime; 125 return m_pauseTime;
85 } 126 }
86 127
87 bool SMILTimeContainer::isStarted() const 128 bool SMILTimeContainer::isStarted() const
88 { 129 {
89 return m_beginTime; 130 return m_beginTime;
90 } 131 }
91 132
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 if (m_beginTime) 178 if (m_beginTime)
138 m_timer.stop(); 179 m_timer.stop();
139 180
140 double now = currentTime(); 181 double now = currentTime();
141 m_beginTime = now - time.value(); 182 m_beginTime = now - time.value();
142 183
143 m_accumulatedPauseTime = 0; 184 m_accumulatedPauseTime = 0;
144 if (m_pauseTime) 185 if (m_pauseTime)
145 m_pauseTime = now; 186 m_pauseTime = now;
146 187
147 Vector<SVGSMILElement*> toReset; 188 #ifndef NDEBUG
148 copyToVector(m_scheduledAnimations, toReset); 189 m_preventScheduledAnimationsChanges = true;
149 for (unsigned n = 0; n < toReset.size(); ++n) 190 #endif
150 toReset[n]->reset(); 191 GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
192 for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it ! = end; ++it) {
193 AnimationsVector* scheduled = it->second;
194 unsigned size = scheduled->size();
195 for (unsigned n = 0; n < size; n++)
196 scheduled->at(n)->reset();
197 }
198 #ifndef NDEBUG
199 m_preventScheduledAnimationsChanges = false;
200 #endif
151 201
152 updateAnimations(time, true); 202 updateAnimations(time, true);
153 } 203 }
154 204
155 void SMILTimeContainer::startTimer(SMILTime fireTime, SMILTime minimumDelay) 205 void SMILTimeContainer::startTimer(SMILTime fireTime, SMILTime minimumDelay)
156 { 206 {
157 if (!m_beginTime || isPaused()) 207 if (!m_beginTime || isPaused())
158 return; 208 return;
159 209
160 if (!fireTime.isFinite()) 210 if (!fireTime.isFinite())
161 return; 211 return;
162 212
163 SMILTime delay = max(fireTime - elapsed(), minimumDelay); 213 SMILTime delay = max(fireTime - elapsed(), minimumDelay);
164 m_timer.startOneShot(delay.value()); 214 m_timer.startOneShot(delay.value());
165 } 215 }
166 216
167 void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*) 217 void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
168 { 218 {
169 ASSERT(m_beginTime); 219 ASSERT(m_beginTime);
170 ASSERT(!m_pauseTime); 220 ASSERT(!m_pauseTime);
171 updateAnimations(elapsed()); 221 updateAnimations(elapsed());
172 } 222 }
(...skipping 27 matching lines...) Expand all
200 250
201 void SMILTimeContainer::sortByPriority(Vector<SVGSMILElement*>& smilElements, SM ILTime elapsed) 251 void SMILTimeContainer::sortByPriority(Vector<SVGSMILElement*>& smilElements, SM ILTime elapsed)
202 { 252 {
203 if (m_documentOrderIndexesDirty) 253 if (m_documentOrderIndexesDirty)
204 updateDocumentOrderIndexes(); 254 updateDocumentOrderIndexes();
205 std::sort(smilElements.begin(), smilElements.end(), PriorityCompare(elapsed) ); 255 std::sort(smilElements.begin(), smilElements.end(), PriorityCompare(elapsed) );
206 } 256 }
207 257
208 void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) 258 void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
209 { 259 {
210 SMILTime earliersFireTime = SMILTime::unresolved(); 260 SMILTime earliestFireTime = SMILTime::unresolved();
211 261
212 Vector<SVGSMILElement*> toAnimate; 262 #ifndef NDEBUG
213 copyToVector(m_scheduledAnimations, toAnimate); 263 // This boolean will catch any attempts to schedule/unschedule scheduledAnim ations during this critical section.
264 // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply.
265 m_preventScheduledAnimationsChanges = true;
266 #endif
214 267
215 // Sort according to priority. Elements with later begin time have higher pr iority. 268 AnimationsVector animationsToApply;
216 // In case of a tie, document order decides. 269 GroupedAnimationsMap::iterator end = m_scheduledAnimations.end();
217 // FIXME: This should also consider timing relationships between the element s. Dependents 270 for (GroupedAnimationsMap::iterator it = m_scheduledAnimations.begin(); it ! = end; ++it) {
218 // have higher priority. 271 AnimationsVector* scheduled = it->second;
219 sortByPriority(toAnimate, elapsed);
220 272
221 // Calculate animation contributions. 273 // Sort according to priority. Elements with later begin time have highe r priority.
222 typedef pair<SVGElement*, QualifiedName> ElementAttributePair; 274 // In case of a tie, document order decides.
223 typedef HashMap<ElementAttributePair, SVGSMILElement*> ResultElementMap; 275 // FIXME: This should also consider timing relationships between the ele ments. Dependents
224 ResultElementMap resultsElements; 276 // have higher priority.
225 for (unsigned n = 0; n < toAnimate.size(); ++n) { 277 sortByPriority(*scheduled, elapsed);
226 SVGSMILElement* animation = toAnimate[n];
227 ASSERT(animation->timeContainer() == this);
228 278
229 SVGElement* targetElement = animation->targetElement(); 279 SVGSMILElement* resultElement = 0;
230 if (!targetElement) 280 unsigned size = scheduled->size();
231 continue; 281 for (unsigned n = 0; n < size; n++) {
282 SVGSMILElement* animation = scheduled->at(n);
283 ASSERT(animation->timeContainer() == this);
284 ASSERT(animation->targetElement());
285 ASSERT(animation->hasValidAttributeName());
232 286
233 QualifiedName attributeName = animation->attributeName(); 287 // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair.
234 if (attributeName == anyQName()) { 288 if (!resultElement) {
235 if (animation->hasTagName(SVGNames::animateMotionTag)) 289 if (!animation->hasValidAttributeType())
236 attributeName = SVGNames::animateMotionTag; 290 continue;
237 else 291 resultElement = animation;
238 continue; 292 }
293
294 // This will calculate the contribution from the animation and add i t to the resultsElement.
295 if (!animation->progress(elapsed, resultElement, seekToTime) && resu ltElement == animation)
296 resultElement = 0;
297
298 SMILTime nextFireTime = animation->nextProgressTime();
299 if (nextFireTime.isFinite())
300 earliestFireTime = min(nextFireTime, earliestFireTime);
239 } 301 }
240 302
241 // Results are accumulated to the first animation that animates and cont ributes to a particular element/attribute pair. 303 if (resultElement)
242 ElementAttributePair key(targetElement, attributeName); 304 animationsToApply.append(resultElement);
243 SVGSMILElement* resultElement = resultsElements.get(key);
244 if (!resultElement) {
245 if (!animation->hasValidAttributeType())
246 continue;
247 resultElement = animation;
248 } else
249 ASSERT(resultElement != animation);
250
251 // This will calculate the contribution from the animation and add it to the resultsElement.
252 if (animation->progress(elapsed, resultElement, seekToTime) && resultEle ment == animation)
253 resultsElements.add(key, resultElement);
254
255 SMILTime nextFireTime = animation->nextProgressTime();
256 if (nextFireTime.isFinite())
257 earliersFireTime = min(nextFireTime, earliersFireTime);
258 } 305 }
259 306
260 unsigned resultsToApplySize = resultsElements.size(); 307 unsigned animationsToApplySize = animationsToApply.size();
261 if (!resultsToApplySize) { 308 if (!animationsToApplySize) {
262 startTimer(earliersFireTime, animationFrameDelay); 309 #ifndef NDEBUG
310 m_preventScheduledAnimationsChanges = false;
311 #endif
312 startTimer(earliestFireTime, animationFrameDelay);
263 return; 313 return;
264 } 314 }
265 315
266 // Apply results to target elements. 316 // Apply results to target elements.
267 ResultElementMap::iterator end = resultsElements.end(); 317 for (unsigned i = 0; i < animationsToApplySize; ++i)
268 for (ResultElementMap::iterator it = resultsElements.begin(); it != end; ++i t) 318 animationsToApply[i]->applyResultsToTarget();
269 it->second->applyResultsToTarget();
270 319
271 startTimer(earliersFireTime, animationFrameDelay); 320 #ifndef NDEBUG
321 m_preventScheduledAnimationsChanges = false;
322 #endif
323
324 startTimer(earliestFireTime, animationFrameDelay);
272 Document::updateStyleForAllDocuments(); 325 Document::updateStyleForAllDocuments();
273 } 326 }
274 327
275 } 328 }
276 329
277 #endif // ENABLE(SVG) 330 #endif // ENABLE(SVG)
OLDNEW
« 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