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) { |