Diff
Copied: branches/chromium/963/LayoutTests/svg/animations/svglength-animation-retarget-crash-expected.txt (from rev 108134, trunk/LayoutTests/svg/animations/svglength-animation-retarget-crash-expected.txt) (0 => 109358)
--- branches/chromium/963/LayoutTests/svg/animations/svglength-animation-retarget-crash-expected.txt (rev 0)
+++ branches/chromium/963/LayoutTests/svg/animations/svglength-animation-retarget-crash-expected.txt 2012-03-01 18:05:41 UTC (rev 109358)
@@ -0,0 +1,5 @@
+This test verifies that SVG animation targets can change during the animation.
+
+TEST PASSED
+
+
Copied: branches/chromium/963/LayoutTests/svg/animations/svglength-animation-retarget-crash.html (from rev 108134, trunk/LayoutTests/svg/animations/svglength-animation-retarget-crash.html) (0 => 109358)
--- branches/chromium/963/LayoutTests/svg/animations/svglength-animation-retarget-crash.html (rev 0)
+++ branches/chromium/963/LayoutTests/svg/animations/svglength-animation-retarget-crash.html 2012-03-01 18:05:41 UTC (rev 109358)
@@ -0,0 +1,25 @@
+<p>This test verifies that SVG animation targets can change during the animation.</p>
+<p id="result"></p>
+<svg id="svg">
+ <text id="text"></text>
+ <animate xlink:href="" id="a" attributeName="y" begin="0.0" from="0" to="1" dur="1s" repeatCount="indefinite">
+</svg>
+<script>
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText()
+ layoutTestController.waitUntilDone()
+}
+
+setTimeout(function() {
+ text = document.getElementById('text')
+ text.id = 'not_text'
+ svg = document.getElementById('svg')
+ svg.id = 'text'
+ svg.appendChild(document.getElementById('a').cloneNode())
+ setTimeout(function() {
+ document.getElementById("result").innerText = "TEST PASSED"
+ if (window.layoutTestController)
+ layoutTestController.notifyDone()
+ }, 0)
+}, 0)
+</script>
Modified: branches/chromium/963/Source/WebCore/svg/SVGAnimateElement.cpp (109357 => 109358)
--- branches/chromium/963/Source/WebCore/svg/SVGAnimateElement.cpp 2012-03-01 17:53:00 UTC (rev 109357)
+++ branches/chromium/963/Source/WebCore/svg/SVGAnimateElement.cpp 2012-03-01 18:05:41 UTC (rev 109358)
@@ -109,7 +109,7 @@
if (!targetElement)
return false;
- return determineAnimatedPropertyType(targetElement) != AnimatedUnknown;
+ return m_animatedPropertyType != AnimatedUnknown;
}
AnimatedPropertyType SVGAnimateElement::determineAnimatedPropertyType(SVGElement* targetElement) const
@@ -159,12 +159,20 @@
void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
{
ASSERT(resultElement);
+ SVGElement* targetElement = this->targetElement();
+ if (!targetElement)
+ return;
+
+ ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(targetElement));
+
ASSERT(percentage >= 0 && percentage <= 1);
ASSERT(m_animatedPropertyType != AnimatedEnumeration);
ASSERT(m_animatedPropertyType != AnimatedTransformList);
ASSERT(m_animatedPropertyType != AnimatedUnknown);
ASSERT(m_animator);
+ ASSERT(m_animator->type() == m_animatedPropertyType);
ASSERT(m_fromType);
+ ASSERT(m_fromType->type() == m_animatedPropertyType);
ASSERT(m_toType);
SVGAnimateElement* resultAnimationElement = static_cast<SVGAnimateElement*>(resultElement);
@@ -177,10 +185,6 @@
if (hasTagName(SVGNames::setTag))
percentage = 1;
- SVGElement* targetElement = this->targetElement();
- if (!targetElement)
- return;
-
// Target element might have changed.
m_animator->setContextElement(targetElement);
m_animator->calculateAnimatedValue(percentage, repeat, m_fromType, m_toType, resultAnimationElement->m_animatedType);
@@ -192,9 +196,8 @@
if (!targetElement)
return false;
- m_animatedPropertyType = determineAnimatedPropertyType(targetElement);
-
ensureAnimator()->calculateFromAndToValues(m_fromType, m_toType, fromString, toString);
+ ASSERT(m_animatedPropertyType == m_animator->type());
return true;
}
@@ -205,22 +208,19 @@
return false;
ASSERT(!hasTagName(SVGNames::setTag));
- m_animatedPropertyType = determineAnimatedPropertyType(targetElement);
ensureAnimator()->calculateFromAndByValues(m_fromType, m_toType, fromString, byString);
+ ASSERT(m_animatedPropertyType == m_animator->type());
return true;
}
void SVGAnimateElement::resetToBaseValue(const String& baseString)
{
- SVGElement* targetElement = this->targetElement();
- ASSERT(targetElement);
- m_animatedPropertyType = determineAnimatedPropertyType(targetElement);
-
if (!m_animatedType)
m_animatedType = ensureAnimator()->constructFromString(baseString);
else
m_animatedType->setValueAsString(attributeName(), baseString);
+ ASSERT(m_animatedPropertyType == m_animator->type());
}
void SVGAnimateElement::applyResultsToTarget()
@@ -239,15 +239,24 @@
SVGElement* targetElement = this->targetElement();
if (!targetElement)
return -1;
- m_animatedPropertyType = determineAnimatedPropertyType(targetElement);
-
+
return ensureAnimator()->calculateDistance(fromString, toString);
}
+void SVGAnimateElement::targetElementDidChange(SVGElement* targetElement)
+{
+ m_animatedType.clear();
+ m_fromType.clear();
+ m_toType.clear();
+ m_animator.clear();
+ m_animatedPropertyType = targetElement ? determineAnimatedPropertyType(targetElement) : AnimatedString;
+}
+
SVGAnimatedTypeAnimator* SVGAnimateElement::ensureAnimator()
{
if (!m_animator)
m_animator = SVGAnimatorFactory::create(this, targetElement(), m_animatedPropertyType);
+ ASSERT(m_animatedPropertyType == m_animator->type());
return m_animator.get();
}
Modified: branches/chromium/963/Source/WebCore/svg/SVGAnimateElement.h (109357 => 109358)
--- branches/chromium/963/Source/WebCore/svg/SVGAnimateElement.h 2012-03-01 17:53:00 UTC (rev 109357)
+++ branches/chromium/963/Source/WebCore/svg/SVGAnimateElement.h 2012-03-01 18:05:41 UTC (rev 109358)
@@ -45,7 +45,7 @@
static PassRefPtr<SVGAnimateElement> create(const QualifiedName&, Document*);
virtual ~SVGAnimateElement();
-
+
static void adjustForCurrentColor(SVGElement* targetElement, Color&);
void adjustForInheritance(SVGElement* targetElement, const QualifiedName&, String& value);
@@ -65,6 +65,8 @@
virtual void applyResultsToTarget();
virtual float calculateDistance(const String& fromString, const String& toString);
+ virtual void targetElementDidChange(SVGElement* targetElement) OVERRIDE;
+
private:
SVGAnimatedTypeAnimator* ensureAnimator();
Modified: branches/chromium/963/Source/WebCore/svg/SVGAnimatedTypeAnimator.h (109357 => 109358)
--- branches/chromium/963/Source/WebCore/svg/SVGAnimatedTypeAnimator.h 2012-03-01 17:53:00 UTC (rev 109357)
+++ branches/chromium/963/Source/WebCore/svg/SVGAnimatedTypeAnimator.h 2012-03-01 18:05:41 UTC (rev 109358)
@@ -41,7 +41,9 @@
virtual float calculateDistance(const String& fromString, const String& toString) = 0;
void setContextElement(SVGElement* contextElement) { m_contextElement = contextElement; }
-
+
+ AnimatedPropertyType type() const { return m_type; }
+
protected:
SVGAnimatedTypeAnimator(AnimatedPropertyType type, SVGAnimationElement* animationElement, SVGElement* contextElement)
: m_type(type)
Modified: branches/chromium/963/Source/WebCore/svg/animation/SVGSMILElement.cpp (109357 => 109358)
--- branches/chromium/963/Source/WebCore/svg/animation/SVGSMILElement.cpp 2012-03-01 17:53:00 UTC (rev 109357)
+++ branches/chromium/963/Source/WebCore/svg/animation/SVGSMILElement.cpp 2012-03-01 18:05:41 UTC (rev 109358)
@@ -498,17 +498,32 @@
ContainerNode* target = href.isEmpty() ? parentNode() : SVGURIReference::targetElementFromIRIString(href, document());
if (!target || !target->isSVGElement())
return 0;
-
+
m_targetElement = static_cast<SVGElement*>(target);
document()->accessSVGExtensions()->addAnimationElementToTarget(this, m_targetElement);
+
+ targetElementDidChange(m_targetElement);
+
return m_targetElement;
}
-SMILTime SVGSMILElement::elapsed() const
+void SVGSMILElement::resetTargetElement()
{
+ m_targetElement = 0;
+
+ // Force the animation to recompute values that are only calculated when an animation becomes active.
+ // Failing to do this means that a target reset and change during active animation may result in
+ // invalid state.
+ m_activeState = Inactive;
+
+ targetElementDidChange(0);
+}
+
+SMILTime SVGSMILElement::elapsed() const
+{
return m_timeContainer ? m_timeContainer->elapsed() : 0;
-}
-
+}
+
bool SVGSMILElement::isInactive() const
{
return m_activeState == Inactive;
Modified: branches/chromium/963/Source/WebCore/svg/animation/SVGSMILElement.h (109357 => 109358)
--- branches/chromium/963/Source/WebCore/svg/animation/SVGSMILElement.h 2012-03-01 17:53:00 UTC (rev 109357)
+++ branches/chromium/963/Source/WebCore/svg/animation/SVGSMILElement.h 2012-03-01 18:05:41 UTC (rev 109358)
@@ -54,7 +54,7 @@
SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
SVGElement* targetElement();
- void resetTargetElement() { m_targetElement = 0; }
+ void resetTargetElement();
const QualifiedName& attributeName() const { return m_attributeName; }
void beginByLinkActivation();
@@ -112,6 +112,9 @@
void setInactive() { m_activeState = Inactive; }
+ // Sub-classes may need to take action when the target is changed.
+ virtual void targetElementDidChange(SVGElement*) { }
+
private:
virtual void startedActiveInterval() = 0;
virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
@@ -228,4 +231,3 @@
#endif // ENABLE(SVG)
#endif // SVGSMILElement_h
-