| Index: Source/WebCore/svg/animation/SVGSMILElement.cpp
|
| ===================================================================
|
| --- Source/WebCore/svg/animation/SVGSMILElement.cpp (revision 132107)
|
| +++ Source/WebCore/svg/animation/SVGSMILElement.cpp (working copy)
|
| @@ -140,8 +140,8 @@
|
| SVGSMILElement::~SVGSMILElement()
|
| {
|
| disconnectConditions();
|
| - if (m_timeContainer)
|
| - m_timeContainer->unschedule(this);
|
| + if (m_timeContainer && m_targetElement && hasValidAttributeName())
|
| + m_timeContainer->unschedule(this, m_targetElement, m_attributeName);
|
| if (m_targetElement)
|
| document()->accessSVGExtensions()->removeAnimationElementFromTarget(this, m_targetElement);
|
| }
|
| @@ -200,10 +200,11 @@
|
| // Verify we are not in <use> instance tree.
|
| ASSERT(!isInShadowTree());
|
|
|
| - m_attributeName = constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr));
|
| + setAttributeName(constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr)));
|
| SVGSVGElement* owner = ownerSVGElement();
|
| if (!owner)
|
| return InsertionDone;
|
| +
|
| m_timeContainer = owner->timeContainer();
|
| ASSERT(m_timeContainer);
|
| m_timeContainer->setDocumentOrderIndexesDirty();
|
| @@ -215,7 +216,11 @@
|
| if (m_isWaitingForFirstInterval)
|
| resolveFirstInterval();
|
|
|
| - reschedule();
|
| + // Force resolution of target element
|
| + if (!m_targetElement)
|
| + targetElement();
|
| + if (m_timeContainer)
|
| + m_timeContainer->notifyIntervalsChanged();
|
|
|
| return InsertionDone;
|
| }
|
| @@ -224,7 +229,8 @@
|
| {
|
| if (rootParent->inDocument()) {
|
| if (m_timeContainer) {
|
| - m_timeContainer->unschedule(this);
|
| + if (m_targetElement && hasValidAttributeName())
|
| + m_timeContainer->unschedule(this, m_targetElement, m_attributeName);
|
| m_timeContainer = 0;
|
| }
|
| // Calling disconnectConditions() may kill us if there are syncbase conditions.
|
| @@ -234,14 +240,19 @@
|
|
|
| // Clear target now, because disconnectConditions calls targetElement() which will recreate the target if we removed it sooner.
|
| if (m_targetElement)
|
| - resetTargetElement();
|
| + resetTargetElement(DoNotResolveNewTarget);
|
|
|
| - m_attributeName = anyQName();
|
| + setAttributeName(anyQName());
|
| }
|
|
|
| SVGElement::removedFrom(rootParent);
|
| }
|
| -
|
| +
|
| +bool SVGSMILElement::hasValidAttributeName()
|
| +{
|
| + return attributeName() != anyQName();
|
| +}
|
| +
|
| SMILTime SVGSMILElement::parseOffsetValue(const String& data)
|
| {
|
| bool ok;
|
| @@ -465,12 +476,13 @@
|
| else if (attrName == SVGNames::endAttr)
|
| endListChanged(elapsed());
|
| else if (attrName == SVGNames::attributeNameAttr) {
|
| - m_attributeName = constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr));
|
| + setAttributeName(constructQualifiedName(this, fastGetAttribute(SVGNames::attributeNameAttr)));
|
| if (m_targetElement) {
|
| resetTargetElement();
|
| return;
|
| }
|
| } else if (attrName.matches(XLinkNames::hrefAttr)) {
|
| + // targetElement is resolved lazily but targetElement() will handle calling targetElementWillChange().
|
| if (SVGElement* targetElement = this->targetElement())
|
| document()->accessSVGExtensions()->removeAllAnimationElementsFromTarget(targetElement);
|
| }
|
| @@ -543,10 +555,16 @@
|
| }
|
| }
|
|
|
| -void SVGSMILElement::reschedule()
|
| +void SVGSMILElement::setAttributeName(const QualifiedName& attributeName)
|
| {
|
| - if (m_timeContainer)
|
| - m_timeContainer->schedule(this);
|
| + if (m_timeContainer && m_targetElement && m_attributeName != attributeName) {
|
| + if (hasValidAttributeName())
|
| + m_timeContainer->unschedule(this, m_targetElement, m_attributeName);
|
| + m_attributeName = attributeName;
|
| + if (hasValidAttributeName())
|
| + m_timeContainer->schedule(this, m_targetElement, m_attributeName);
|
| + } else
|
| + m_attributeName = attributeName;
|
| }
|
|
|
| SVGElement* SVGSMILElement::targetElement()
|
| @@ -569,8 +587,15 @@
|
| return m_targetElement;
|
| }
|
|
|
| -void SVGSMILElement::targetElementWillChange(SVGElement* currentTarget, SVGElement*)
|
| +void SVGSMILElement::targetElementWillChange(SVGElement* currentTarget, SVGElement* newTarget)
|
| {
|
| + if (m_timeContainer && hasValidAttributeName()) {
|
| + if (currentTarget)
|
| + m_timeContainer->unschedule(this, currentTarget, m_attributeName);
|
| + if (newTarget)
|
| + m_timeContainer->schedule(this, newTarget, m_attributeName);
|
| + }
|
| +
|
| // Only clear the animated type, if we had a target before.
|
| if (currentTarget)
|
| clearAnimatedType(currentTarget);
|
| @@ -580,11 +605,16 @@
|
| endedActiveInterval();
|
| }
|
|
|
| -void SVGSMILElement::resetTargetElement()
|
| +void SVGSMILElement::resetTargetElement(ResolveTarget resolveTarget)
|
| {
|
| document()->accessSVGExtensions()->removeAnimationElementFromTarget(this, m_targetElement);
|
| targetElementWillChange(m_targetElement, 0);
|
| m_targetElement = 0;
|
| +
|
| + // Immediately resolve the new targetElement (and call targetElementWillChange if needed) instead of doing it lazily.
|
| + if (resolveTarget == ResolveNewTarget)
|
| + targetElement();
|
| +
|
| animationAttributeChanged();
|
| }
|
|
|
| @@ -823,7 +853,9 @@
|
| m_intervalEnd = end;
|
| notifyDependentsIntervalChanged(wasUnresolved ? NewInterval : ExistingInterval);
|
| m_nextProgressTime = min(m_nextProgressTime, m_intervalBegin);
|
| - reschedule();
|
| +
|
| + if (m_timeContainer)
|
| + m_timeContainer->notifyIntervalsChanged();
|
| }
|
| }
|
|
|
| @@ -871,7 +903,9 @@
|
| }
|
| }
|
| m_nextProgressTime = elapsed();
|
| - reschedule();
|
| +
|
| + if (m_timeContainer)
|
| + m_timeContainer->notifyIntervalsChanged();
|
| }
|
|
|
| void SVGSMILElement::endListChanged(SMILTime)
|
| @@ -890,7 +924,9 @@
|
| }
|
| }
|
| m_nextProgressTime = elapsed;
|
| - reschedule();
|
| +
|
| + if (m_timeContainer)
|
| + m_timeContainer->notifyIntervalsChanged();
|
| }
|
|
|
| void SVGSMILElement::checkRestart(SMILTime elapsed)
|
| @@ -1018,10 +1054,10 @@
|
| ASSERT(resultElement);
|
| ASSERT(m_timeContainer);
|
| ASSERT(m_isWaitingForFirstInterval || m_intervalBegin.isFinite());
|
| -
|
| +
|
| if (!m_conditionsConnected)
|
| connectConditions();
|
| -
|
| +
|
| if (!m_intervalBegin.isFinite()) {
|
| ASSERT(m_activeState == Inactive);
|
| m_nextProgressTime = SMILTime::unresolved();
|
| @@ -1035,7 +1071,7 @@
|
| m_nextProgressTime = m_intervalBegin;
|
| return false;
|
| }
|
| -
|
| +
|
| m_previousIntervalBegin = m_intervalBegin;
|
|
|
| if (m_isWaitingForFirstInterval) {
|
|
|