#include "config.h"
#if ENABLE(SVG)
#include "SVGTimer.h"
#include <wtf/HashMap.h>
#include "SVGAnimateTransformElement.h"
#include "SVGAnimateMotionElement.h"
#include "SVGTransformList.h"
#include "SVGAnimateColorElement.h"
#include "SVGStyledTransformableElement.h"
namespace WebCore {
SVGTimer::SVGTimer(TimeScheduler* scheduler, double interval, bool singleShot)
: Timer<TimeScheduler>(scheduler, &TimeScheduler::timerFired)
, m_scheduler(scheduler)
, m_interval(interval)
, m_singleShot(singleShot)
{
}
void SVGTimer::start()
{
if (m_singleShot)
startOneShot(m_interval);
else
startRepeating(m_interval);
}
SVGTimer::TargetAnimationMap SVGTimer::animationsByElement(double elapsedSeconds)
{
TargetAnimationMap targetMap;
#if ENABLE(SVG_ANIMATION)
ExceptionCode ec = 0;
SVGNotifySet::const_iterator end = m_notifySet.end();
for (SVGNotifySet::const_iterator it = m_notifySet.begin(); it != end; ++it) {
SVGAnimationElement* animation = *it;
if (!m_enabledNotifySet.contains(animation)) {
if (!animation->isFrozen())
continue;
if (elapsedSeconds <= (animation->getStartTime() + animation->getSimpleDuration(ec)))
continue;
}
SVGElement* target = const_cast<SVGElement*>(animation->targetElement());
TargetAnimationMap::iterator i = targetMap.find(target);
if (i != targetMap.end())
i->second.append(animation);
else {
Vector<SVGAnimationElement*> list;
list.append(animation);
targetMap.set(target, list);
}
}
#endif
return targetMap;
}
void SVGTimer::applyAnimations(double elapsedSeconds, const SVGTimer::TargetAnimationMap& targetMap)
{
#if ENABLE(SVG_ANIMATION)
TargetAnimationMap::const_iterator targetIterator = targetMap.begin();
TargetAnimationMap::const_iterator tend = targetMap.end();
for (; targetIterator != tend; ++targetIterator) {
unsigned count = targetIterator->second.size();
for (unsigned i = 0; i < count; ++i) {
SVGAnimationElement* animation = targetIterator->second[i];
if (!animation->isValidAnimation())
continue;
if (!animation->updateAnimationBaseValueFromElement())
continue;
if (!animation->updateAnimatedValueForElapsedSeconds(elapsedSeconds))
continue;
animation->applyAnimatedValueToElement();
}
}
for (targetIterator = targetMap.begin(); targetIterator != tend; ++targetIterator) {
SVGElement* key = targetIterator->first;
if (key && key->isStyled())
static_cast<SVGStyledElement*>(key)->setChanged();
}
#endif
}
void SVGTimer::notifyAll()
{
#if ENABLE(SVG_ANIMATION)
if (m_enabledNotifySet.isEmpty())
return;
double elapsedSeconds = m_scheduler->elapsed() * 1000.0; TargetAnimationMap targetMap = animationsByElement(elapsedSeconds);
applyAnimations(elapsedSeconds, targetMap);
#endif
}
void SVGTimer::addNotify(SVGAnimationElement* element, bool enabled)
{
#if ENABLE(SVG_ANIMATION)
m_notifySet.add(element);
if (enabled)
m_enabledNotifySet.add(element);
else
m_enabledNotifySet.remove(element);
#endif
}
void SVGTimer::removeNotify(SVGAnimationElement *element)
{
#if ENABLE(SVG_ANIMATION)
m_enabledNotifySet.remove(element);
if (m_enabledNotifySet.isEmpty())
stop();
#endif
}
}
#endif // ENABLE(SVG)