Patch by Kulanthaivel Palanichamy <kulanthaivel@codeaurora.org> on 2011-07-16
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Jul 2011 07:33:14 +0000 (07:33 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Jul 2011 07:33:14 +0000 (07:33 +0000)
Reviewed by Nikolas Zimmermann.

SVG animation API crashes on SVGAnimateTransform
https://bugs.webkit.org/show_bug.cgi?id=64104

Source/WebCore:

This patch ensures the update in AnimatedTransform list in
SVGAnimateTransformElement.cpp is in sync with its wrapper list.

Test: svg/animations/svgtransform-animation-discrete.html

* svg/SVGAnimateTransformElement.cpp:
(WebCore::animatedTransformListFor):
(WebCore::SVGAnimateTransformElement::resetToBaseValue):
(WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
(WebCore::SVGAnimateTransformElement::applyResultsToTarget):

LayoutTests:

Added the test to cover assertion in AnimatedTransform list where its
value and wrapper length mismatch occurs.

* svg/animations/script-tests/svgtransform-animation-discrete.js: Added.
(sample1):
(sample2):
(executeTest):
* svg/animations/svgtransform-animation-discrete-expected.txt: Added.
* svg/animations/svgtransform-animation-discrete.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@91148 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/svg/animations/script-tests/svgtransform-animation-discrete.js [new file with mode: 0644]
LayoutTests/svg/animations/svgtransform-animation-discrete-expected.txt [new file with mode: 0644]
LayoutTests/svg/animations/svgtransform-animation-discrete.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/svg/SVGAnimateTransformElement.cpp

index 1f059a0..569e48d 100644 (file)
@@ -1,3 +1,20 @@
+2011-07-16  Kulanthaivel Palanichamy  <kulanthaivel@codeaurora.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVG animation API crashes on SVGAnimateTransform
+        https://bugs.webkit.org/show_bug.cgi?id=64104
+
+        Added the test to cover assertion in AnimatedTransform list where its
+        value and wrapper length mismatch occurs.
+
+        * svg/animations/script-tests/svgtransform-animation-discrete.js: Added.
+        (sample1):
+        (sample2):
+        (executeTest):
+        * svg/animations/svgtransform-animation-discrete-expected.txt: Added.
+        * svg/animations/svgtransform-animation-discrete.html: Added.
+
 2011-07-13  Jon Honeycutt  <jhoneycutt@apple.com>
 
         Focus and selection events are not fired when a <select>'s selection
diff --git a/LayoutTests/svg/animations/script-tests/svgtransform-animation-discrete.js b/LayoutTests/svg/animations/script-tests/svgtransform-animation-discrete.js
new file mode 100644 (file)
index 0000000..10dea0c
--- /dev/null
@@ -0,0 +1,66 @@
+description("Test calcMode=discrete animation on SVGAnimateTransform.");
+createSVGTestCase();
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "0");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animateTransform");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "transform");
+animate.setAttribute("type", "translate");
+animate.setAttribute("from", "100,100");
+animate.setAttribute("to", "0,0");
+animate.setAttribute("type", "translate");
+animate.setAttribute("calcMode", "discrete");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("rect.transform.animVal.numberOfItems", "0");
+    shouldBeCloseEnough("document.defaultView.getComputedStyle(rect).getPropertyValue('x')", "0", 0.01);
+    shouldBeCloseEnough("document.defaultView.getComputedStyle(rect).getPropertyValue('y')", "0", 0.01);
+}
+
+function sample2() {
+    // Check initial/end conditions
+    shouldBe("rect.transform.animVal.numberOfItems", "1");
+    shouldBe("rect.transform.animVal.getItem(0).type", "SVGTransform.SVG_TRANSFORM_TRANSLATE");
+    shouldBeCloseEnough("rect.transform.animVal.getItem(0).matrix.e", "100", 0.01);
+    shouldBeCloseEnough("rect.transform.animVal.getItem(0).matrix.f", "100", 0.01);
+}
+
+function sample3() {
+    shouldBe("rect.transform.animVal.numberOfItems", "1");
+    shouldBe("rect.transform.animVal.getItem(0).type", "SVGTransform.SVG_TRANSFORM_TRANSLATE");
+    shouldBeCloseEnough("rect.transform.animVal.getItem(0).matrix.e", "0", 0.01);
+    shouldBeCloseEnough("rect.transform.animVal.getItem(0).matrix.f", "0", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,  "rect", sample1],
+        ["animation", 0.001,  "rect", sample2],
+        ["animation", 1.0,    "rect", sample2],
+        ["animation", 3.0,    "rect", sample3],
+        ["animation", 3.9999, "rect", sample3],
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/LayoutTests/svg/animations/svgtransform-animation-discrete-expected.txt b/LayoutTests/svg/animations/svgtransform-animation-discrete-expected.txt
new file mode 100644 (file)
index 0000000..7b49694
--- /dev/null
@@ -0,0 +1,30 @@
+SVG 1.1 transform animation tests
+
+Test calcMode=discrete animation on SVGAnimateTransform.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS rect.transform.animVal.numberOfItems is 0
+PASS document.defaultView.getComputedStyle(rect).getPropertyValue('x') is 0
+PASS document.defaultView.getComputedStyle(rect).getPropertyValue('y') is 0
+PASS rect.transform.animVal.numberOfItems is 1
+PASS rect.transform.animVal.getItem(0).type is SVGTransform.SVG_TRANSFORM_TRANSLATE
+PASS rect.transform.animVal.getItem(0).matrix.e is 100
+PASS rect.transform.animVal.getItem(0).matrix.f is 100
+PASS rect.transform.animVal.numberOfItems is 1
+PASS rect.transform.animVal.getItem(0).type is SVGTransform.SVG_TRANSFORM_TRANSLATE
+PASS rect.transform.animVal.getItem(0).matrix.e is 100
+PASS rect.transform.animVal.getItem(0).matrix.f is 100
+PASS rect.transform.animVal.numberOfItems is 1
+PASS rect.transform.animVal.getItem(0).type is SVGTransform.SVG_TRANSFORM_TRANSLATE
+PASS rect.transform.animVal.getItem(0).matrix.e is 0
+PASS rect.transform.animVal.getItem(0).matrix.f is 0
+PASS rect.transform.animVal.numberOfItems is 1
+PASS rect.transform.animVal.getItem(0).type is SVGTransform.SVG_TRANSFORM_TRANSLATE
+PASS rect.transform.animVal.getItem(0).matrix.e is 0
+PASS rect.transform.animVal.getItem(0).matrix.f is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/svgtransform-animation-discrete.html b/LayoutTests/svg/animations/svgtransform-animation-discrete.html
new file mode 100644 (file)
index 0000000..d2e37c9
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="../dynamic-updates/resources/SVGTestCase.js"></script>
+<script src="resources/SVGAnimationTestCase.js"></script>
+</head>
+<body>
+<h1>SVG 1.1 transform animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/svgtransform-animation-discrete.js"></script>
+</body>
+</html>
index 3ea84a0..419dd37 100644 (file)
@@ -1,3 +1,21 @@
+2011-07-16  Kulanthaivel Palanichamy  <kulanthaivel@codeaurora.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVG animation API crashes on SVGAnimateTransform
+        https://bugs.webkit.org/show_bug.cgi?id=64104
+
+        This patch ensures the update in AnimatedTransform list in
+        SVGAnimateTransformElement.cpp is in sync with its wrapper list.
+
+        Test: svg/animations/svgtransform-animation-discrete.html
+
+        * svg/SVGAnimateTransformElement.cpp:
+        (WebCore::animatedTransformListFor):
+        (WebCore::SVGAnimateTransformElement::resetToBaseValue):
+        (WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
+        (WebCore::SVGAnimateTransformElement::applyResultsToTarget):
+
 2011-07-15  Simon Fraser  <simon.fraser@apple.com>
 
         Fix the build.
index 946862a..4817121 100644 (file)
@@ -117,17 +117,17 @@ void SVGAnimateTransformElement::parseMappedAttribute(Attribute* attr)
     ASSERT_NOT_REACHED();
 }
 
-static SVGTransformList* transformListFor(SVGElement* element)
+static PassRefPtr<SVGAnimatedTransformList> animatedTransformListFor(SVGElement* element)
 {
     ASSERT(element);
     if (element->isStyledTransformable())
-        return &static_cast<SVGStyledTransformableElement*>(element)->transform();
+        return static_cast<SVGStyledTransformableElement*>(element)->transformAnimated();
     if (element->hasTagName(SVGNames::textTag))
-        return &static_cast<SVGTextElement*>(element)->transform();
+        return static_cast<SVGTextElement*>(element)->transformAnimated();
     if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
-        return &static_cast<SVGGradientElement*>(element)->gradientTransform();
+        return static_cast<SVGGradientElement*>(element)->gradientTransformAnimated();
     if (element->hasTagName(SVGNames::patternTag))
-        return &static_cast<SVGPatternElement*>(element)->patternTransform();
+        return static_cast<SVGPatternElement*>(element)->patternTransformAnimated();
     return 0;
 }
     
@@ -148,8 +148,10 @@ void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
     }
     
     if (baseValue.isEmpty()) {
-        if (SVGTransformList* list = transformListFor(targetElement))
-            list->clear();
+        if (RefPtr<SVGAnimatedTransformList> list = animatedTransformListFor(targetElement)) {
+            list->detachListWrappers(0);
+            list->values().clear();
+        }
     } else
         targetElement->setAttribute(SVGNames::transformAttr, baseValue);
 }
@@ -159,18 +161,21 @@ void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsign
     SVGElement* targetElement = this->targetElement();
     if (!targetElement || determineAnimatedPropertyType(targetElement) == AnimatedUnknown)
         return;
-    SVGTransformList* transformList = transformListFor(targetElement);
-    ASSERT(transformList);
+    RefPtr<SVGAnimatedTransformList> animatedList = animatedTransformListFor(targetElement);
+    ASSERT(animatedList);
     
     if (calcMode() == CalcModeDiscrete)
         percentage = percentage < 0.5 ? 0 : 1;
 
-    if (!isAdditive())
-        transformList->clear();
+    if (!isAdditive()) {
+        animatedList->detachListWrappers(0);
+        animatedList->values().clear();
+    }
     if (isAccumulated() && repeat)
         percentage += repeat;
     SVGTransform transform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(percentage).addToSVGTransform(m_fromTransform);
-    transformList->append(transform);
+    animatedList->values().append(transform);
+    animatedList->wrappers().append(RefPtr<SVGPropertyTearOff<SVGTransform> >());
 }
     
 bool SVGAnimateTransformElement::calculateFromAndToValues(const String& fromString, const String& toString)
@@ -216,9 +221,10 @@ void SVGAnimateTransformElement::applyResultsToTarget()
     }
 
     // ...except in case where we have additional instances in <use> trees.
-    SVGTransformList* transformList = transformListFor(targetElement);
-    if (!transformList)
+    RefPtr<SVGAnimatedTransformList> animatedList = animatedTransformListFor(targetElement);
+    if (!animatedList)
         return;
+    SVGTransformList* transformList = &animatedList->values();
 
     const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
     const HashSet<SVGElementInstance*>::const_iterator end = instances.end();