29 #include "CSSComputedStyleDeclaration.h"
30 #include "CSSParser.h"
35 #include "SystemTime.h"
43 SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
46 , m_accumulatedPauseTime(0)
47 , m_documentOrderIndexesDirty(false)
48 , m_timer(this, &SMILTimeContainer::timerFired)
49 , m_ownerSVGElement(owner)
53 #if !ENABLE(SVG_ANIMATION)
54 void SMILTimeContainer::begin() {}
55 void SMILTimeContainer::pause() {}
56 void SMILTimeContainer::resume() {}
57 SMILTime SMILTimeContainer::elapsed()
const {
return 0; }
58 bool SMILTimeContainer::isPaused()
const {
return false; }
59 void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*) {}
62 void SMILTimeContainer::schedule(SVGSMILElement* animation)
64 ASSERT(animation->timeContainer() ==
this);
65 SMILTime nextFireTime = animation->nextProgressTime();
66 if (!nextFireTime.isFinite())
68 m_scheduledAnimations.add(animation);
72 void SMILTimeContainer::unschedule(SVGSMILElement* animation)
74 ASSERT(animation->timeContainer() ==
this);
76 m_scheduledAnimations.remove(animation);
79 SMILTime SMILTimeContainer::elapsed()
const
83 return currentTime() - m_beginTime - m_accumulatedPauseTime;
86 bool SMILTimeContainer::isActive()
const
88 return m_beginTime && !isPaused();
91 bool SMILTimeContainer::isPaused()
const
96 void SMILTimeContainer::begin()
99 m_beginTime = currentTime();
103 void SMILTimeContainer::pause()
108 m_pauseTime = currentTime();
112 void SMILTimeContainer::resume()
117 m_accumulatedPauseTime += currentTime() - m_pauseTime;
122 void SMILTimeContainer::startTimer(SMILTime fireTime, SMILTime minimumDelay)
124 if (!m_beginTime || isPaused())
127 if (!fireTime.isFinite())
130 SMILTime delay = max(fireTime - elapsed(), minimumDelay);
131 m_timer.startOneShot(delay.value());
134 void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
137 ASSERT(!m_pauseTime);
138 SMILTime elapsed = this->elapsed();
139 updateAnimations(elapsed);
142 void SMILTimeContainer::updateDocumentOrderIndexes()
144 unsigned timingElementCount = 0;
145 for (Node* node = m_ownerSVGElement; node; node = node->traverseNextNode(m_ownerSVGElement)) {
146 if (SVGSMILElement::isSMILElement(node))
147 static_cast<SVGSMILElement*>(node)->setDocumentOrderIndex(timingElementCount++);
149 m_documentOrderIndexesDirty =
false;
152 struct PriorityCompare {
153 PriorityCompare(SMILTime elapsed) : m_elapsed(elapsed) {}
154 bool operator()(SVGSMILElement* a, SVGSMILElement* b)
157 SMILTime aBegin = a->intervalBegin();
158 SMILTime bBegin = b->intervalBegin();
160 aBegin = a->isFrozen() && m_elapsed < aBegin ? a->previousIntervalBegin() : aBegin;
161 bBegin = b->isFrozen() && m_elapsed < bBegin ? b->previousIntervalBegin() : bBegin;
162 if (aBegin == bBegin)
163 return a->documentOrderIndex() < b->documentOrderIndex();
164 return aBegin < bBegin;
169 void SMILTimeContainer::sortByPriority(Vector<SVGSMILElement*>& smilElements, SMILTime elapsed)
171 if (m_documentOrderIndexesDirty)
172 updateDocumentOrderIndexes();
173 std::sort(smilElements.begin(), smilElements.end(), PriorityCompare(elapsed));
176 static bool applyOrderSortFunction(SVGSMILElement* a, SVGSMILElement* b)
183 static void sortByApplyOrder(Vector<SVGSMILElement*>& smilElements)
185 std::sort(smilElements.begin(), smilElements.end(), applyOrderSortFunction);
188 String SMILTimeContainer::baseValueFor(ElementAttributePair key)
192 BaseValueMap::iterator it = m_savedBaseValues.
find(key);
193 if (it != m_savedBaseValues.end())
196 SVGElement* target = key.first;
197 String attributeName = key.second;
199 ASSERT(!attributeName.isEmpty());
201 if (SVGAnimationElement::attributeIsCSS(attributeName)) {
202 CSSComputedStyleDeclaration computedStyle(target);
203 baseValue = computedStyle.getPropertyValue(cssPropertyID(attributeName));
205 baseValue = target->getAttribute(attributeName);
206 m_savedBaseValues.add(key, baseValue);
210 void SMILTimeContainer::updateAnimations(SMILTime elapsed)
212 SMILTime earliersFireTime = SMILTime::unresolved();
214 Vector<SVGSMILElement*> toAnimate;
215 copyToVector(m_scheduledAnimations, toAnimate);
221 sortByPriority(toAnimate, elapsed);
224 typedef HashMap<ElementAttributePair, SVGSMILElement*> ResultElementMap;
225 ResultElementMap resultsElements;
226 for (
unsigned n = 0; n < toAnimate.size(); ++n) {
227 SVGSMILElement* animation = toAnimate[n];
228 ASSERT(animation->timeContainer() ==
this);
230 SVGElement* targetElement = animation->targetElement();
233 String attributeName = animation->attributeName();
234 if (attributeName.isEmpty()) {
242 ElementAttributePair key(targetElement, attributeName);
243 SVGSMILElement* resultElement = resultsElements.get(key);
244 if (!resultElement) {
245 resultElement = animation;
246 resultElement->resetToBaseValue(baseValueFor(key));
247 resultsElements.add(key, resultElement);
251 animation->progress(elapsed, resultElement);
253 SMILTime nextFireTime = animation->nextProgressTime();
254 if (nextFireTime.isFinite())
255 earliersFireTime = min(nextFireTime, earliersFireTime);
256 else if (!animation->isContributing(elapsed)) {
257 m_scheduledAnimations.remove(animation);
258 if (m_scheduledAnimations.isEmpty())
259 m_savedBaseValues.clear();
263 Vector<SVGSMILElement*> animationsToApply;
264 ResultElementMap::iterator
end = resultsElements.end();
265 for (ResultElementMap::iterator it = resultsElements.begin(); it != end; ++it)
266 animationsToApply.append(it->second);
270 sortByApplyOrder(animationsToApply);
273 for (
unsigned n = 0; n < animationsToApply.size(); ++n)
274 animationsToApply[n]->applyResultsToTarget();
278 Document::updateDocumentsRendering();
DOM::QualifiedName animateTransformTag
static const double animationFrameDelay
int find(const QChar c, int start=0) const
DOM::QualifiedName animateMotionTag