[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198

krit at webkit.org krit at webkit.org
Mon Feb 21 00:03:36 UTC 2011


The following commit has been merged in the webkit-1.3 branch:
commit 7a6abf6b59669fd6d11abe7619ca9de0ee2fb41d
Author: krit at webkit.org <krit at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Jan 27 21:03:14 2011 +0000

    2011-01-27  Dirk Schulze  <krit at webkit.org>
    
            Reviewed by Nikolas Zimmermann.
    
            SVG animation of Paths with segments of different coordinate modes on begin and end
            https://bugs.webkit.org/show_bug.cgi?id=52984
    
            Added tests to check the correct behavior on path animations, where the coordinate modes
            of the start path differs from the one on the end path.
    
            * svg/animations/animate-path-animation-Cc-Ss-expected.txt: Added.
            * svg/animations/animate-path-animation-Cc-Ss.html: Added.
            * svg/animations/animate-path-animation-Ll-Vv-Hh-expected.txt: Added.
            * svg/animations/animate-path-animation-Ll-Vv-Hh.html: Added.
            * svg/animations/animate-path-animation-Qq-Tt-expected.txt: Added.
            * svg/animations/animate-path-animation-Qq-Tt.html: Added.
            * svg/animations/animate-path-animation-cC-sS-inverse-expected.txt: Added.
            * svg/animations/animate-path-animation-cC-sS-inverse.html: Added.
            * svg/animations/animate-path-animation-lL-vV-hH-inverse-expected.txt: Added.
            * svg/animations/animate-path-animation-lL-vV-hH-inverse.html: Added.
            * svg/animations/animate-path-animation-qQ-tT-inverse-expected.txt: Added.
            * svg/animations/animate-path-animation-qQ-tT-inverse.html: Added.
            * svg/animations/animate-path-nested-transforms.html: Cleanup.
            * svg/animations/animate-text-nested-transforms.html: Cleanup.
            * svg/animations/resources/SVGAnimationTestCase.js:
            (shouldBeCloseEnough): For debug output of values with tolerance level.
            (startTest):
            (sampleAnimation):
            * svg/animations/script-tests/animate-path-animation-Cc-Ss.js: Added.
            (sample1):
            (sample2):
            (sample3):
            (sample4):
            (executeTest):
            * svg/animations/script-tests/animate-path-animation-Ll-Vv-Hh.js: Added.
            (sample1):
            (sample2):
            (sample3):
            (sample4):
            (executeTest):
            * svg/animations/script-tests/animate-path-animation-Qq-Tt.js: Added.
            (sample1):
            (sample2):
            (sample3):
            (sample4):
            (executeTest):
            * svg/animations/script-tests/animate-path-animation-cC-sS-inverse.js: Added.
            (sample1):
            (sample2):
            (sample3):
            (sample4):
            (executeTest):
            * svg/animations/script-tests/animate-path-animation-lL-vV-hH-inverse.js: Added.
            (sample1):
            (sample2):
            (sample3):
            (sample4):
            (executeTest):
            * svg/animations/script-tests/animate-path-animation-qQ-tT-inverse.js: Added.
            (sample1):
            (sample2):
            (sample3):
            (sample4):
            (executeTest):
    2011-01-27  Dirk Schulze  <krit at webkit.org>
    
            Reviewed by Nikolas Zimmermann.
    
            SVG animation of Paths with segments of different coordinate modes on begin and end
            https://bugs.webkit.org/show_bug.cgi?id=52984
    
            At the moment we just support SVG path animations, if the number of segments on the given start path
            is the same as the number of segments on the given end path. But a segment on a given position must be identical
            on both paths as well. Not only the segment type, also the coordinate mode of the segments must be identical.
            If MoveToRel is on the second position on the start path a MoveToRel must be on the second position
            of the end path too. According to the SVG spec, at least the coordinate mode can differ. Means, if we have MoveToRel
            in the start path, we can use MoveToAbs on the same position in the end path.
    
            This patch fixes the blending code to follow the spec here. It was necessary to track the current position of
            both paths, transform coordinates to the same coordinate mode and transform the resulting animation coordinate back
            to the coordinate mode of either the start or the end path. Which mode is taken depends on the progress of the
            animation.
    
            Tests: svg/animations/animate-path-animation-Cc-Ss.html
                   svg/animations/animate-path-animation-Ll-Vv-Hh.html
                   svg/animations/animate-path-animation-Qq-Tt.html
                   svg/animations/animate-path-animation-cC-sS-inverse.html
                   svg/animations/animate-path-animation-lL-vV-hH-inverse.html
                   svg/animations/animate-path-animation-qQ-tT-inverse.html
    
            * svg/SVGPathBlender.cpp:
            (WebCore::blendFloatPoint):
            (WebCore::blendAnimatedFloat):
            (WebCore::SVGPathBlender::blendAnimatedDimensionalFloat):
            (WebCore::SVGPathBlender::blendAnimatedFloatPoint):
            (WebCore::SVGPathBlender::blendMoveToSegment):
            (WebCore::SVGPathBlender::blendLineToSegment):
            (WebCore::SVGPathBlender::blendLineToHorizontalSegment):
            (WebCore::SVGPathBlender::blendLineToVerticalSegment):
            (WebCore::SVGPathBlender::blendCurveToCubicSegment):
            (WebCore::SVGPathBlender::blendCurveToCubicSmoothSegment):
            (WebCore::SVGPathBlender::blendCurveToQuadraticSegment):
            (WebCore::SVGPathBlender::blendCurveToQuadraticSmoothSegment):
            (WebCore::SVGPathBlender::blendArcToSegment):
            (WebCore::coordinateModeOfCommand):
            (WebCore::isSegmentEqual):
            (WebCore::SVGPathBlender::blendAnimatedPath):
            (WebCore::SVGPathBlender::cleanup):
            * svg/SVGPathBlender.h:
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76830 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index b1cd115..67d32c4 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,68 @@
+2011-01-27  Dirk Schulze  <krit at webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVG animation of Paths with segments of different coordinate modes on begin and end
+        https://bugs.webkit.org/show_bug.cgi?id=52984
+
+        Added tests to check the correct behavior on path animations, where the coordinate modes
+        of the start path differs from the one on the end path.
+
+        * svg/animations/animate-path-animation-Cc-Ss-expected.txt: Added.
+        * svg/animations/animate-path-animation-Cc-Ss.html: Added.
+        * svg/animations/animate-path-animation-Ll-Vv-Hh-expected.txt: Added.
+        * svg/animations/animate-path-animation-Ll-Vv-Hh.html: Added.
+        * svg/animations/animate-path-animation-Qq-Tt-expected.txt: Added.
+        * svg/animations/animate-path-animation-Qq-Tt.html: Added.
+        * svg/animations/animate-path-animation-cC-sS-inverse-expected.txt: Added.
+        * svg/animations/animate-path-animation-cC-sS-inverse.html: Added.
+        * svg/animations/animate-path-animation-lL-vV-hH-inverse-expected.txt: Added.
+        * svg/animations/animate-path-animation-lL-vV-hH-inverse.html: Added.
+        * svg/animations/animate-path-animation-qQ-tT-inverse-expected.txt: Added.
+        * svg/animations/animate-path-animation-qQ-tT-inverse.html: Added.
+        * svg/animations/animate-path-nested-transforms.html: Cleanup.
+        * svg/animations/animate-text-nested-transforms.html: Cleanup.
+        * svg/animations/resources/SVGAnimationTestCase.js:
+        (shouldBeCloseEnough): For debug output of values with tolerance level.
+        (startTest):
+        (sampleAnimation):
+        * svg/animations/script-tests/animate-path-animation-Cc-Ss.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (sample4):
+        (executeTest):
+        * svg/animations/script-tests/animate-path-animation-Ll-Vv-Hh.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (sample4):
+        (executeTest):
+        * svg/animations/script-tests/animate-path-animation-Qq-Tt.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (sample4):
+        (executeTest):
+        * svg/animations/script-tests/animate-path-animation-cC-sS-inverse.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (sample4):
+        (executeTest):
+        * svg/animations/script-tests/animate-path-animation-lL-vV-hH-inverse.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (sample4):
+        (executeTest):
+        * svg/animations/script-tests/animate-path-animation-qQ-tT-inverse.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (sample4):
+        (executeTest):
+
 2011-01-27  Cris Neckar  <cdn at chromium.org>
 
         Reviewed by Dimitri Glazkov.
diff --git a/LayoutTests/svg/animations/animate-path-animation-Cc-Ss-expected.txt b/LayoutTests/svg/animations/animate-path-animation-Cc-Ss-expected.txt
new file mode 100644
index 0000000..135495e
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-Cc-Ss-expected.txt
@@ -0,0 +1,86 @@
+SVG 1.1 dynamic animation tests
+
+Test path animation where coordinate modes of start and end differ. You should see PASS messages
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'C'
+PASS path.pathSegList.getItem(1).x is 20
+PASS path.pathSegList.getItem(1).y is 20
+PASS path.pathSegList.getItem(1).x1 is 20
+PASS path.pathSegList.getItem(1).y1 is -20
+PASS path.pathSegList.getItem(1).x2 is 20
+PASS path.pathSegList.getItem(1).y2 is -20
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'S'
+PASS path.pathSegList.getItem(2).x is -20
+PASS path.pathSegList.getItem(2).y is 20
+PASS path.pathSegList.getItem(2).x2 is 20
+PASS path.pathSegList.getItem(2).y2 is 40
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'C'
+PASS path.pathSegList.getItem(1).x is 20
+PASS path.pathSegList.getItem(1).y is 20
+PASS path.pathSegList.getItem(1).x1 is 10
+PASS path.pathSegList.getItem(1).y1 is -10
+PASS path.pathSegList.getItem(1).x2 is 10
+PASS path.pathSegList.getItem(1).y2 is -10
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'S'
+PASS path.pathSegList.getItem(2).x is -10
+PASS path.pathSegList.getItem(2).y is 10
+PASS path.pathSegList.getItem(2).x2 is 30
+PASS path.pathSegList.getItem(2).y2 is 35
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'c'
+PASS path.pathSegList.getItem(1).x is 40
+PASS path.pathSegList.getItem(1).y is 40
+PASS path.pathSegList.getItem(1).x1 is 10
+PASS path.pathSegList.getItem(1).y1 is 30
+PASS path.pathSegList.getItem(1).x2 is 10
+PASS path.pathSegList.getItem(1).y2 is 30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 's'
+PASS path.pathSegList.getItem(2).x is -10
+PASS path.pathSegList.getItem(2).y is -30
+PASS path.pathSegList.getItem(2).x2 is 30
+PASS path.pathSegList.getItem(2).y2 is 5
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'c'
+PASS path.pathSegList.getItem(1).x is 40
+PASS path.pathSegList.getItem(1).y is 40
+PASS path.pathSegList.getItem(1).x1 is 0
+PASS path.pathSegList.getItem(1).y1 is 40
+PASS path.pathSegList.getItem(1).x2 is 0
+PASS path.pathSegList.getItem(1).y2 is 40
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 's'
+PASS path.pathSegList.getItem(2).x is 0
+PASS path.pathSegList.getItem(2).y is -40
+PASS path.pathSegList.getItem(2).x2 is 40
+PASS path.pathSegList.getItem(2).y2 is 0
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'C'
+PASS path.pathSegList.getItem(1).x is 20
+PASS path.pathSegList.getItem(1).y is 20
+PASS path.pathSegList.getItem(1).x1 is 20
+PASS path.pathSegList.getItem(1).y1 is -20
+PASS path.pathSegList.getItem(1).x2 is 20
+PASS path.pathSegList.getItem(1).y2 is -20
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'S'
+PASS path.pathSegList.getItem(2).x is -20
+PASS path.pathSegList.getItem(2).y is 20
+PASS path.pathSegList.getItem(2).x2 is 20
+PASS path.pathSegList.getItem(2).y2 is 40
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-path-animation-Cc-Ss.html b/LayoutTests/svg/animations/animate-path-animation-Cc-Ss.html
new file mode 100644
index 0000000..b8f4078
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-Cc-Ss.html
@@ -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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-animation-Cc-Ss.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/animate-path-animation-Ll-Vv-Hh-expected.txt b/LayoutTests/svg/animations/animate-path-animation-Ll-Vv-Hh-expected.txt
new file mode 100644
index 0000000..715fa61
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-Ll-Vv-Hh-expected.txt
@@ -0,0 +1,61 @@
+SVG 1.1 dynamic animation tests
+
+Test path animation where coordinate modes of start and end differ. You should see PASS messages
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'L'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'V'
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'H'
+PASS path.pathSegList.getItem(3).x is 0
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -15
+PASS path.pathSegList.getItem(0).y is -15
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'L'
+PASS path.pathSegList.getItem(1).x is 15
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'V'
+PASS path.pathSegList.getItem(2).y is 15
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'H'
+PASS path.pathSegList.getItem(3).x is 0
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is 15
+PASS path.pathSegList.getItem(0).y is 15
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'l'
+PASS path.pathSegList.getItem(1).x is -30
+PASS path.pathSegList.getItem(1).y is -15
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'v'
+PASS path.pathSegList.getItem(2).y is -15
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'h'
+PASS path.pathSegList.getItem(3).x is 15
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is 30
+PASS path.pathSegList.getItem(0).y is 30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'l'
+PASS path.pathSegList.getItem(1).x is -60
+PASS path.pathSegList.getItem(1).y is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'v'
+PASS path.pathSegList.getItem(2).y is -30
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'h'
+PASS path.pathSegList.getItem(3).x is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'L'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'V'
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'H'
+PASS path.pathSegList.getItem(3).x is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-path-animation-Ll-Vv-Hh.html b/LayoutTests/svg/animations/animate-path-animation-Ll-Vv-Hh.html
new file mode 100644
index 0000000..d2b83ae
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-Ll-Vv-Hh.html
@@ -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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-animation-Ll-Vv-Hh.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/animate-path-animation-Qq-Tt-expected.txt b/LayoutTests/svg/animations/animate-path-animation-Qq-Tt-expected.txt
new file mode 100644
index 0000000..ea0fc45
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-Qq-Tt-expected.txt
@@ -0,0 +1,66 @@
+SVG 1.1 dynamic animation tests
+
+Test path animation where coordinate modes of start and end differ. You should see PASS messages
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'Q'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(1).x1 is 30
+PASS path.pathSegList.getItem(1).y1 is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'T'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'Q'
+PASS path.pathSegList.getItem(1).x is 22.5
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(1).x1 is 22.5
+PASS path.pathSegList.getItem(1).y1 is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'T'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'q'
+PASS path.pathSegList.getItem(1).x is 37.5
+PASS path.pathSegList.getItem(1).y is 30
+PASS path.pathSegList.getItem(1).x1 is 37.5
+PASS path.pathSegList.getItem(1).y1 is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 't'
+PASS path.pathSegList.getItem(2).x is -37.5
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'q'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 30
+PASS path.pathSegList.getItem(1).x1 is 30
+PASS path.pathSegList.getItem(1).y1 is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 't'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'Q'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(1).x1 is 30
+PASS path.pathSegList.getItem(1).y1 is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'T'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-path-animation-Qq-Tt.html b/LayoutTests/svg/animations/animate-path-animation-Qq-Tt.html
new file mode 100644
index 0000000..05121f5
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-Qq-Tt.html
@@ -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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-animation-Qq-Tt.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/animate-path-animation-cC-sS-inverse-expected.txt b/LayoutTests/svg/animations/animate-path-animation-cC-sS-inverse-expected.txt
new file mode 100644
index 0000000..764d34e
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-cC-sS-inverse-expected.txt
@@ -0,0 +1,86 @@
+SVG 1.1 dynamic animation tests
+
+Test path animation where coordinate modes of start and end differ. You should see PASS messages
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'c'
+PASS path.pathSegList.getItem(1).x is 40
+PASS path.pathSegList.getItem(1).y is 40
+PASS path.pathSegList.getItem(1).x1 is 0
+PASS path.pathSegList.getItem(1).y1 is 40
+PASS path.pathSegList.getItem(1).x2 is 0
+PASS path.pathSegList.getItem(1).y2 is 40
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 's'
+PASS path.pathSegList.getItem(2).x is 0
+PASS path.pathSegList.getItem(2).y is -40
+PASS path.pathSegList.getItem(2).x2 is 40
+PASS path.pathSegList.getItem(2).y2 is 0
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'c'
+PASS path.pathSegList.getItem(1).x is 40
+PASS path.pathSegList.getItem(1).y is 40
+PASS path.pathSegList.getItem(1).x1 is 10
+PASS path.pathSegList.getItem(1).y1 is 30
+PASS path.pathSegList.getItem(1).x2 is 10
+PASS path.pathSegList.getItem(1).y2 is 30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 's'
+PASS path.pathSegList.getItem(2).x is -10
+PASS path.pathSegList.getItem(2).y is -30
+PASS path.pathSegList.getItem(2).x2 is 30
+PASS path.pathSegList.getItem(2).y2 is 5
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'C'
+PASS path.pathSegList.getItem(1).x is 20
+PASS path.pathSegList.getItem(1).y is 20
+PASS path.pathSegList.getItem(1).x1 is 10
+PASS path.pathSegList.getItem(1).y1 is -10
+PASS path.pathSegList.getItem(1).x2 is 10
+PASS path.pathSegList.getItem(1).y2 is -10
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'S'
+PASS path.pathSegList.getItem(2).x is -10
+PASS path.pathSegList.getItem(2).y is 10
+PASS path.pathSegList.getItem(2).x2 is 30
+PASS path.pathSegList.getItem(2).y2 is 35
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'C'
+PASS path.pathSegList.getItem(1).x is 20
+PASS path.pathSegList.getItem(1).y is 20
+PASS path.pathSegList.getItem(1).x1 is 20
+PASS path.pathSegList.getItem(1).y1 is -20
+PASS path.pathSegList.getItem(1).x2 is 20
+PASS path.pathSegList.getItem(1).y2 is -20
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'S'
+PASS path.pathSegList.getItem(2).x is -20
+PASS path.pathSegList.getItem(2).y is 20
+PASS path.pathSegList.getItem(2).x2 is 20
+PASS path.pathSegList.getItem(2).y2 is 40
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -20
+PASS path.pathSegList.getItem(0).y is -20
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'c'
+PASS path.pathSegList.getItem(1).x is 40
+PASS path.pathSegList.getItem(1).y is 40
+PASS path.pathSegList.getItem(1).x1 is 0
+PASS path.pathSegList.getItem(1).y1 is 40
+PASS path.pathSegList.getItem(1).x2 is 0
+PASS path.pathSegList.getItem(1).y2 is 40
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 's'
+PASS path.pathSegList.getItem(2).x is 0
+PASS path.pathSegList.getItem(2).y is -40
+PASS path.pathSegList.getItem(2).x2 is 40
+PASS path.pathSegList.getItem(2).y2 is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-path-animation-cC-sS-inverse.html b/LayoutTests/svg/animations/animate-path-animation-cC-sS-inverse.html
new file mode 100644
index 0000000..685062d
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-cC-sS-inverse.html
@@ -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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-animation-cC-sS-inverse.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/animate-path-animation-lL-vV-hH-inverse-expected.txt b/LayoutTests/svg/animations/animate-path-animation-lL-vV-hH-inverse-expected.txt
new file mode 100644
index 0000000..9b8747e
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-lL-vV-hH-inverse-expected.txt
@@ -0,0 +1,61 @@
+SVG 1.1 dynamic animation tests
+
+Test path animation where coordinate modes of start and end differ. You should see PASS messages
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is 30
+PASS path.pathSegList.getItem(0).y is 30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'l'
+PASS path.pathSegList.getItem(1).x is -60
+PASS path.pathSegList.getItem(1).y is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'v'
+PASS path.pathSegList.getItem(2).y is -30
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'h'
+PASS path.pathSegList.getItem(3).x is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is 15
+PASS path.pathSegList.getItem(0).y is 15
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'l'
+PASS path.pathSegList.getItem(1).x is -30
+PASS path.pathSegList.getItem(1).y is -15
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'v'
+PASS path.pathSegList.getItem(2).y is -15
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'h'
+PASS path.pathSegList.getItem(3).x is 15
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -15
+PASS path.pathSegList.getItem(0).y is -15
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'L'
+PASS path.pathSegList.getItem(1).x is 15
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'V'
+PASS path.pathSegList.getItem(2).y is 15
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'H'
+PASS path.pathSegList.getItem(3).x is 0
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'L'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'V'
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'H'
+PASS path.pathSegList.getItem(3).x is 0
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is 30
+PASS path.pathSegList.getItem(0).y is 30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'l'
+PASS path.pathSegList.getItem(1).x is -60
+PASS path.pathSegList.getItem(1).y is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'v'
+PASS path.pathSegList.getItem(2).y is -30
+PASS path.pathSegList.getItem(3).pathSegTypeAsLetter is 'h'
+PASS path.pathSegList.getItem(3).x is 30
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-path-animation-lL-vV-hH-inverse.html b/LayoutTests/svg/animations/animate-path-animation-lL-vV-hH-inverse.html
new file mode 100644
index 0000000..ef37207
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-lL-vV-hH-inverse.html
@@ -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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-animation-lL-vV-hH-inverse.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/animate-path-animation-qQ-tT-inverse-expected.txt b/LayoutTests/svg/animations/animate-path-animation-qQ-tT-inverse-expected.txt
new file mode 100644
index 0000000..3477479
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-qQ-tT-inverse-expected.txt
@@ -0,0 +1,66 @@
+SVG 1.1 dynamic animation tests
+
+Test path animation where coordinate modes of start and end differ. You should see PASS messages
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'q'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 30
+PASS path.pathSegList.getItem(1).x1 is 30
+PASS path.pathSegList.getItem(1).y1 is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 't'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'q'
+PASS path.pathSegList.getItem(1).x is 37.5
+PASS path.pathSegList.getItem(1).y is 30
+PASS path.pathSegList.getItem(1).x1 is 37.5
+PASS path.pathSegList.getItem(1).y1 is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 't'
+PASS path.pathSegList.getItem(2).x is -37.5
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'Q'
+PASS path.pathSegList.getItem(1).x is 22.5
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(1).x1 is 22.5
+PASS path.pathSegList.getItem(1).y1 is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'T'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'Q'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 0
+PASS path.pathSegList.getItem(1).x1 is 30
+PASS path.pathSegList.getItem(1).y1 is -30
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 'T'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS path.pathSegList.getItem(0).pathSegTypeAsLetter is 'M'
+PASS path.pathSegList.getItem(0).x is -30
+PASS path.pathSegList.getItem(0).y is -30
+PASS path.pathSegList.getItem(1).pathSegTypeAsLetter is 'q'
+PASS path.pathSegList.getItem(1).x is 30
+PASS path.pathSegList.getItem(1).y is 30
+PASS path.pathSegList.getItem(1).x1 is 30
+PASS path.pathSegList.getItem(1).y1 is 0
+PASS path.pathSegList.getItem(2).pathSegTypeAsLetter is 't'
+PASS path.pathSegList.getItem(2).x is -30
+PASS path.pathSegList.getItem(2).y is 30
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-path-animation-qQ-tT-inverse.html b/LayoutTests/svg/animations/animate-path-animation-qQ-tT-inverse.html
new file mode 100644
index 0000000..64f5c3d
--- /dev/null
+++ b/LayoutTests/svg/animations/animate-path-animation-qQ-tT-inverse.html
@@ -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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-animation-qQ-tT-inverse.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/animate-path-nested-transforms.html b/LayoutTests/svg/animations/animate-path-nested-transforms.html
index 9d03aa3..b54a44d 100644
--- a/LayoutTests/svg/animations/animate-path-nested-transforms.html
+++ b/LayoutTests/svg/animations/animate-path-nested-transforms.html
@@ -1,15 +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>Test nested transforms with animateMotion</h1>
-    <p id="description"/>
-    <div id="console"/>
-    <script src="script-tests/animate-path-nested-transforms.js"></script>
-  </body>
+<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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-path-nested-transforms.js"></script>
+</body>
 </html>
diff --git a/LayoutTests/svg/animations/animate-text-nested-transforms.html b/LayoutTests/svg/animations/animate-text-nested-transforms.html
index 1ce9109..c3cd5c9 100644
--- a/LayoutTests/svg/animations/animate-text-nested-transforms.html
+++ b/LayoutTests/svg/animations/animate-text-nested-transforms.html
@@ -1,15 +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>Test nested text transforms with animateMotion</h1>
-    <p id="description"/>
-    <div id="console"/>
-    <script src="script-tests/animate-text-nested-transforms.js"></script>
-  </body>
+<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 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-text-nested-transforms.js"></script>
+</body>
 </html>
diff --git a/LayoutTests/svg/animations/resources/SVGAnimationTestCase.js b/LayoutTests/svg/animations/resources/SVGAnimationTestCase.js
index 258f480..6ef6738 100644
--- a/LayoutTests/svg/animations/resources/SVGAnimationTestCase.js
+++ b/LayoutTests/svg/animations/resources/SVGAnimationTestCase.js
@@ -7,6 +7,29 @@ function isCloseEnough(actual, desired, tolerance)
     return diff <= tolerance;
 }
 
+function shouldBeCloseEnough(_a, _b, tolerance)
+{
+    if (typeof _a != "string" || typeof _b != "string" || typeof tolerance != "number")
+        debug("WARN: shouldBeCloseEnough() expects two string and one number arguments");
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
+    var _bv = eval(_b);
+    
+    if (exception)
+        testFailed(_a + " should be " + _bv + ". Threw exception " + exception);
+    else if (isCloseEnough(_av, _bv, tolerance))
+        testPassed(_a + " is " + _b);
+    else if (typeof(_av) == typeof(_bv))
+        testFailed(_a + " should be close to " + _bv + ". Was " + stringify(_av) + ".");
+    else
+        testFailed(_a + " should be close to " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+}
+
 function moveAnimationTimelineAndSample(index)
 {
     var animationId = expectedResults[index][0];
diff --git a/LayoutTests/svg/animations/script-tests/animate-path-animation-Cc-Ss.js b/LayoutTests/svg/animations/script-tests/animate-path-animation-Cc-Ss.js
new file mode 100644
index 0000000..fa10ff2
--- /dev/null
+++ b/LayoutTests/svg/animations/script-tests/animate-path-animation-Cc-Ss.js
@@ -0,0 +1,112 @@
+description("Test path animation where coordinate modes of start and end differ. You should see PASS messages");
+createSVGTestCase();
+// FIXME: We should move to animatedPathSegList, once it is implemented.
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+animate.setAttribute("to", "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 z");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBe("path.pathSegList.getItem(0).x", "-20");
+    shouldBe("path.pathSegList.getItem(0).y", "-20");
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'C'");
+    shouldBe("path.pathSegList.getItem(1).x", "20");
+    shouldBe("path.pathSegList.getItem(1).y", "20");
+    shouldBe("path.pathSegList.getItem(1).x1", "20");
+    shouldBe("path.pathSegList.getItem(1).y1", "-20");
+    shouldBe("path.pathSegList.getItem(1).x2", "20");
+    shouldBe("path.pathSegList.getItem(1).y2", "-20");
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'S'");
+    shouldBe("path.pathSegList.getItem(2).x", "-20");
+    shouldBe("path.pathSegList.getItem(2).y", "20");
+    shouldBe("path.pathSegList.getItem(2).x2", "20");
+    shouldBe("path.pathSegList.getItem(2).y2", "40");
+}
+
+function sample2() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'C'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "-10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x2", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y2", "-10", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'S'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x2", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y2", "35", 0.01);
+}
+
+function sample3() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'c'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x2", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y2", "30", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'s'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x2", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y2", "5", 0.01);
+}
+
+function sample4() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'c'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "0", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x2", "0", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y2", "40", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'s'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "0", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "-40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x2", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y2", "0", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,    "path", sample1],
+        ["animation", 1.0,    "path", sample2],
+        ["animation", 3.0,    "path", sample3],
+        ["animation", 3.9999, "path", sample4],
+        ["animation", 4.0 ,   "path", sample1]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/LayoutTests/svg/animations/script-tests/animate-path-animation-Ll-Vv-Hh.js b/LayoutTests/svg/animations/script-tests/animate-path-animation-Ll-Vv-Hh.js
new file mode 100644
index 0000000..44b1de2
--- /dev/null
+++ b/LayoutTests/svg/animations/script-tests/animate-path-animation-Ll-Vv-Hh.js
@@ -0,0 +1,92 @@
+description("Test path animation where coordinate modes of start and end differ. You should see PASS messages");
+createSVGTestCase();
+// FIXME: We should move to animatedPathSegList, once it is implemented.
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -30 -30 L 30 0 V 30 H 0 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -30 -30 L 30 0 V 30 H 0 Z");
+animate.setAttribute("to", "M 30 30 l -60 -30 v -30 h 30 Z");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBe("path.pathSegList.getItem(0).x", "-30");
+    shouldBe("path.pathSegList.getItem(0).y", "-30");
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'L'");
+    shouldBe("path.pathSegList.getItem(1).x", "30");
+    shouldBe("path.pathSegList.getItem(1).y", "0");
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'V'");
+    shouldBe("path.pathSegList.getItem(2).y", "30");
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'H'");
+    shouldBe("path.pathSegList.getItem(3).x", "0");
+}
+
+function sample2() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-15", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-15", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'L'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "15", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "0", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'V'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "15", 0.01);
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'H'");
+    shouldBeCloseEnough("path.pathSegList.getItem(3).x", "0", 0.01);
+}
+
+function sample3() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "15", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "15", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'l'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "-15", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'v'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "-15", 0.01);
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'h'");
+    shouldBeCloseEnough("path.pathSegList.getItem(3).x", "15", 0.01);
+}
+
+function sample4() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'l'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "-60", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'v'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'h'");
+    shouldBeCloseEnough("path.pathSegList.getItem(3).x", "30", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,    "path", sample1],
+        ["animation", 1.0,    "path", sample2],
+        ["animation", 3.0,    "path", sample3],
+        ["animation", 3.9999, "path", sample4],
+        ["animation", 4.0 ,   "path", sample1]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/LayoutTests/svg/animations/script-tests/animate-path-animation-Qq-Tt.js b/LayoutTests/svg/animations/script-tests/animate-path-animation-Qq-Tt.js
new file mode 100644
index 0000000..c5f7e84
--- /dev/null
+++ b/LayoutTests/svg/animations/script-tests/animate-path-animation-Qq-Tt.js
@@ -0,0 +1,96 @@
+description("Test path animation where coordinate modes of start and end differ. You should see PASS messages");
+createSVGTestCase();
+// FIXME: We should move to animatedPathSegList, once it is implemented.
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+animate.setAttribute("to", "M -30 -30 q 30 0 30 30 t -30 30 z");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBe("path.pathSegList.getItem(0).x", "-30");
+    shouldBe("path.pathSegList.getItem(0).y", "-30");
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'Q'");
+    shouldBe("path.pathSegList.getItem(1).x", "30");
+    shouldBe("path.pathSegList.getItem(1).y", "0");
+    shouldBe("path.pathSegList.getItem(1).x1", "30");
+    shouldBe("path.pathSegList.getItem(1).y1", "-30");
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'T'");
+    shouldBe("path.pathSegList.getItem(2).x", "-30");
+    shouldBe("path.pathSegList.getItem(2).y", "30");
+}
+
+function sample2() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'Q'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "22.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "0", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "22.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'T'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+}
+
+function sample3() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'q'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "37.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "37.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "0", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'t'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-37.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+}
+
+function sample4() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'q'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "0", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'t'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,    "path", sample1],
+        ["animation", 1.0,    "path", sample2],
+        ["animation", 3.0,    "path", sample3],
+        ["animation", 3.9999, "path", sample4],
+        ["animation", 4.0 ,   "path", sample1]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/LayoutTests/svg/animations/script-tests/animate-path-animation-cC-sS-inverse.js b/LayoutTests/svg/animations/script-tests/animate-path-animation-cC-sS-inverse.js
new file mode 100644
index 0000000..8cdf37f
--- /dev/null
+++ b/LayoutTests/svg/animations/script-tests/animate-path-animation-cC-sS-inverse.js
@@ -0,0 +1,112 @@
+description("Test path animation where coordinate modes of start and end differ. You should see PASS messages");
+createSVGTestCase();
+// FIXME: We should move to animatedPathSegList, once it is implemented.
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 z");
+animate.setAttribute("to", "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBe("path.pathSegList.getItem(0).x", "-20");
+    shouldBe("path.pathSegList.getItem(0).y", "-20");
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'c'");
+    shouldBe("path.pathSegList.getItem(1).x", "40");
+    shouldBe("path.pathSegList.getItem(1).y", "40");
+    shouldBe("path.pathSegList.getItem(1).x1", "0");
+    shouldBe("path.pathSegList.getItem(1).y1", "40");
+    shouldBe("path.pathSegList.getItem(1).x2", "0");
+    shouldBe("path.pathSegList.getItem(1).y2", "40");
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'s'");
+    shouldBe("path.pathSegList.getItem(2).x", "0");
+    shouldBe("path.pathSegList.getItem(2).y", "-40");
+    shouldBe("path.pathSegList.getItem(2).x2", "40");
+    shouldBe("path.pathSegList.getItem(2).y2", "0");
+}
+
+function sample2() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'c'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "40", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x2", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y2", "30", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'s'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x2", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y2", "5", 0.01);
+}
+
+function sample3() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'C'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "-10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x2", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y2", "-10", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'S'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "10", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x2", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y2", "35", 0.01);
+}
+
+function sample4() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'C'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x2", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y2", "-20", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'S'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x2", "20", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y2", "40", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,    "path", sample1],
+        ["animation", 1.0,    "path", sample2],
+        ["animation", 3.0,    "path", sample3],
+        ["animation", 3.9999, "path", sample4],
+        ["animation", 4.0 ,   "path", sample1]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/LayoutTests/svg/animations/script-tests/animate-path-animation-lL-vV-hH-inverse.js b/LayoutTests/svg/animations/script-tests/animate-path-animation-lL-vV-hH-inverse.js
new file mode 100644
index 0000000..f5ca8ca
--- /dev/null
+++ b/LayoutTests/svg/animations/script-tests/animate-path-animation-lL-vV-hH-inverse.js
@@ -0,0 +1,92 @@
+description("Test path animation where coordinate modes of start and end differ. You should see PASS messages");
+createSVGTestCase();
+// FIXME: We should move to animatedPathSegList, once it is implemented.
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M 30 30 l -60 -30 v -30 h 30 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M 30 30 l -60 -30 v -30 h 30 Z");
+animate.setAttribute("to", "M -30 -30 L 30 0 V 30 H 0 Z");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBe("path.pathSegList.getItem(0).x", "30");
+    shouldBe("path.pathSegList.getItem(0).y", "30");
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'l'");
+    shouldBe("path.pathSegList.getItem(1).x", "-60");
+    shouldBe("path.pathSegList.getItem(1).y", "-30");
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'v'");
+    shouldBe("path.pathSegList.getItem(2).y", "-30");
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'h'");
+    shouldBe("path.pathSegList.getItem(3).x", "30");
+}
+
+function sample2() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "15", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "15", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'l'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "-15", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'v'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "-15", 0.01);
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'h'");
+    shouldBeCloseEnough("path.pathSegList.getItem(3).x", "15", 0.01);
+}
+
+function sample3() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-15", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-15", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'L'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "15", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "0", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'V'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "15", 0.01);
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'H'");
+    shouldBeCloseEnough("path.pathSegList.getItem(3).x", "0", 0.01);
+}
+
+function sample4() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'L'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "0", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'V'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+    shouldBe("path.pathSegList.getItem(3).pathSegTypeAsLetter", "'H'");
+    shouldBeCloseEnough("path.pathSegList.getItem(3).x", "0", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,    "path", sample1],
+        ["animation", 1.0,    "path", sample2],
+        ["animation", 3.0,    "path", sample3],
+        ["animation", 3.9999, "path", sample4],
+        ["animation", 4.0 ,   "path", sample1]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/LayoutTests/svg/animations/script-tests/animate-path-animation-qQ-tT-inverse.js b/LayoutTests/svg/animations/script-tests/animate-path-animation-qQ-tT-inverse.js
new file mode 100644
index 0000000..9849a77
--- /dev/null
+++ b/LayoutTests/svg/animations/script-tests/animate-path-animation-qQ-tT-inverse.js
@@ -0,0 +1,96 @@
+description("Test path animation where coordinate modes of start and end differ. You should see PASS messages");
+createSVGTestCase();
+// FIXME: We should move to animatedPathSegList, once it is implemented.
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -30 -30 q 30 0 30 30 t -30 30 z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -30 -30 q 30 0 30 30 t -30 30 z");
+animate.setAttribute("to", "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBe("path.pathSegList.getItem(0).x", "-30");
+    shouldBe("path.pathSegList.getItem(0).y", "-30");
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'q'");
+    shouldBe("path.pathSegList.getItem(1).x", "30");
+    shouldBe("path.pathSegList.getItem(1).y", "30");
+    shouldBe("path.pathSegList.getItem(1).x1", "30");
+    shouldBe("path.pathSegList.getItem(1).y1", "0");
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'t'");
+    shouldBe("path.pathSegList.getItem(2).x", "-30");
+    shouldBe("path.pathSegList.getItem(2).y", "30");
+}
+
+function sample2() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'q'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "37.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "37.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "0", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'t'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-37.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+}
+
+function sample3() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'Q'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "22.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "0", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "22.5", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'T'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+}
+
+function sample4() {
+    shouldBe("path.pathSegList.getItem(0).pathSegTypeAsLetter", "'M'");
+    shouldBeCloseEnough("path.pathSegList.getItem(0).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(0).y", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(1).pathSegTypeAsLetter", "'Q'");
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y", "0", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).x1", "30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(1).y1", "-30", 0.01);
+    shouldBe("path.pathSegList.getItem(2).pathSegTypeAsLetter", "'T'");
+    shouldBeCloseEnough("path.pathSegList.getItem(2).x", "-30", 0.01);
+    shouldBeCloseEnough("path.pathSegList.getItem(2).y", "30", 0.01);
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.0,    "path", sample1],
+        ["animation", 1.0,    "path", sample2],
+        ["animation", 3.0,    "path", sample3],
+        ["animation", 3.9999, "path", sample4],
+        ["animation", 4.0 ,   "path", sample1]
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index f142930..660783b 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,49 @@
+2011-01-27  Dirk Schulze  <krit at webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVG animation of Paths with segments of different coordinate modes on begin and end
+        https://bugs.webkit.org/show_bug.cgi?id=52984
+
+        At the moment we just support SVG path animations, if the number of segments on the given start path
+        is the same as the number of segments on the given end path. But a segment on a given position must be identical
+        on both paths as well. Not only the segment type, also the coordinate mode of the segments must be identical.
+        If MoveToRel is on the second position on the start path a MoveToRel must be on the second position
+        of the end path too. According to the SVG spec, at least the coordinate mode can differ. Means, if we have MoveToRel
+        in the start path, we can use MoveToAbs on the same position in the end path.
+
+        This patch fixes the blending code to follow the spec here. It was necessary to track the current position of
+        both paths, transform coordinates to the same coordinate mode and transform the resulting animation coordinate back
+        to the coordinate mode of either the start or the end path. Which mode is taken depends on the progress of the
+        animation.
+
+        Tests: svg/animations/animate-path-animation-Cc-Ss.html
+               svg/animations/animate-path-animation-Ll-Vv-Hh.html
+               svg/animations/animate-path-animation-Qq-Tt.html
+               svg/animations/animate-path-animation-cC-sS-inverse.html
+               svg/animations/animate-path-animation-lL-vV-hH-inverse.html
+               svg/animations/animate-path-animation-qQ-tT-inverse.html
+
+        * svg/SVGPathBlender.cpp:
+        (WebCore::blendFloatPoint):
+        (WebCore::blendAnimatedFloat):
+        (WebCore::SVGPathBlender::blendAnimatedDimensionalFloat):
+        (WebCore::SVGPathBlender::blendAnimatedFloatPoint):
+        (WebCore::SVGPathBlender::blendMoveToSegment):
+        (WebCore::SVGPathBlender::blendLineToSegment):
+        (WebCore::SVGPathBlender::blendLineToHorizontalSegment):
+        (WebCore::SVGPathBlender::blendLineToVerticalSegment):
+        (WebCore::SVGPathBlender::blendCurveToCubicSegment):
+        (WebCore::SVGPathBlender::blendCurveToCubicSmoothSegment):
+        (WebCore::SVGPathBlender::blendCurveToQuadraticSegment):
+        (WebCore::SVGPathBlender::blendCurveToQuadraticSmoothSegment):
+        (WebCore::SVGPathBlender::blendArcToSegment):
+        (WebCore::coordinateModeOfCommand):
+        (WebCore::isSegmentEqual):
+        (WebCore::SVGPathBlender::blendAnimatedPath):
+        (WebCore::SVGPathBlender::cleanup):
+        * svg/SVGPathBlender.h:
+
 2011-01-27  Cris Neckar  <cdn at chromium.org>
 
         Reviewed by Dimitri Glazkov.
diff --git a/Source/WebCore/svg/SVGPathBlender.cpp b/Source/WebCore/svg/SVGPathBlender.cpp
index d46e24a..6de783d 100644
--- a/Source/WebCore/svg/SVGPathBlender.cpp
+++ b/Source/WebCore/svg/SVGPathBlender.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -34,14 +34,60 @@ SVGPathBlender::SVGPathBlender()
 {
 }
 
-float SVGPathBlender::blendAnimatedFloat(float from, float to)
+// Helper functions
+static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint& b, float progress)
 {
-    return (to - from) * m_progress + from;
+    return FloatPoint((b.x() - a.x()) * progress + a.x(), (b.y() - a.y()) * progress + a.y());
 }
 
-FloatPoint SVGPathBlender::blendAnimatedFloatPoint(FloatPoint& from, FloatPoint& to)
+static inline float blendAnimatedFloat(float from, float to, float progress)
 {
-    return FloatPoint((to.x() - from.x()) * m_progress + from.x(), (to.y() - from.y()) * m_progress + from.y());
+    return (to - from) * progress + from;
+}
+
+float SVGPathBlender::blendAnimatedDimensonalFloat(float from, float to, FloatBlendMode blendMode)
+{
+    if (m_fromMode == m_toMode)
+        return blendAnimatedFloat(from, to, m_progress);
+    
+    float fromValue = blendMode == BlendHorizontal ? m_fromCurrentPoint.x() : m_fromCurrentPoint.y();
+    float toValue = blendMode == BlendHorizontal ? m_toCurrentPoint.x() : m_toCurrentPoint.y();
+
+    // Transform toY to the coordinate mode of fromY
+    float animValue = blendAnimatedFloat(from, m_fromMode == AbsoluteCoordinates ? to + toValue : to - toValue, m_progress);
+    
+    if (m_isInFirstHalfOfAnimation)
+        return animValue;
+    
+    // Transform the animated point to the coordinate mode, needed for the current progress.
+    float currentValue = blendAnimatedFloat(fromValue, toValue, m_progress);
+    return m_toMode == AbsoluteCoordinates ? animValue + currentValue : animValue - currentValue;
+}
+
+FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint)
+{
+    if (m_fromMode == m_toMode)
+        return blendFloatPoint(fromPoint, toPoint, m_progress);
+
+    // Transform toPoint to the coordinate mode of fromPoint
+    FloatPoint animatedPoint = toPoint;
+    if (m_fromMode == AbsoluteCoordinates)
+        animatedPoint += m_toCurrentPoint;
+    else
+        animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y());
+
+    animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress);
+
+    if (m_isInFirstHalfOfAnimation)
+        return animatedPoint;
+
+    // Transform the animated point to the coordinate mode, needed for the current progress.
+    FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoint, m_progress);
+    if (m_toMode == AbsoluteCoordinates)
+        return animatedPoint + currentPoint;
+
+    animatedPoint.move(-currentPoint.x(), -currentPoint.y());
+    return animatedPoint;
 }
 
 bool SVGPathBlender::blendMoveToSegment()
@@ -52,7 +98,9 @@ bool SVGPathBlender::blendMoveToSegment()
         || !m_toSource->parseMoveToSegment(toTargetPoint))
         return false;
 
-    m_consumer->moveTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), false, m_mode);
+    m_consumer->moveTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), false, m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
@@ -64,7 +112,9 @@ bool SVGPathBlender::blendLineToSegment()
         || !m_toSource->parseLineToSegment(toTargetPoint))
         return false;
 
-    m_consumer->lineTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_mode);
+    m_consumer->lineTo(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
@@ -76,7 +126,9 @@ bool SVGPathBlender::blendLineToHorizontalSegment()
         || !m_toSource->parseLineToHorizontalSegment(toX))
         return false;
 
-    m_consumer->lineToHorizontal(blendAnimatedFloat(fromX, toX), m_mode);
+    m_consumer->lineToHorizontal(blendAnimatedDimensonalFloat(fromX, toX, BlendHorizontal), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint.setX(m_fromMode == AbsoluteCoordinates ? fromX : m_fromCurrentPoint.x() + fromX);
+    m_toCurrentPoint.setX(m_toMode == AbsoluteCoordinates ? toX : m_toCurrentPoint.x() + toX);
     return true;
 }
 
@@ -88,7 +140,9 @@ bool SVGPathBlender::blendLineToVerticalSegment()
         || !m_toSource->parseLineToVerticalSegment(toY))
         return false;
 
-    m_consumer->lineToVertical(blendAnimatedFloat(fromY, toY), m_mode);
+    m_consumer->lineToVertical(blendAnimatedDimensonalFloat(fromY, toY, BlendVertical), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint.setY(m_fromMode == AbsoluteCoordinates ? fromY : m_fromCurrentPoint.y() + fromY);
+    m_toCurrentPoint.setY(m_toMode == AbsoluteCoordinates ? toY : m_toCurrentPoint.y() + toY);
     return true;
 }
 
@@ -107,7 +161,9 @@ bool SVGPathBlender::blendCurveToCubicSegment()
     m_consumer->curveToCubic(blendAnimatedFloatPoint(fromPoint1, toPoint1),
                              blendAnimatedFloatPoint(fromPoint2, toPoint2),
                              blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
-                             m_mode);
+                             m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
@@ -123,7 +179,9 @@ bool SVGPathBlender::blendCurveToCubicSmoothSegment()
 
     m_consumer->curveToCubicSmooth(blendAnimatedFloatPoint(fromPoint2, toPoint2),
                                    blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
-                                   m_mode);
+                                   m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
@@ -139,7 +197,9 @@ bool SVGPathBlender::blendCurveToQuadraticSegment()
 
     m_consumer->curveToQuadratic(blendAnimatedFloatPoint(fromPoint1, toPoint1),
                                  blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
-                                 m_mode);
+                                 m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
@@ -151,7 +211,9 @@ bool SVGPathBlender::blendCurveToQuadraticSmoothSegment()
         || !m_toSource->parseCurveToQuadraticSmoothSegment(toTargetPoint))
         return false;
 
-    m_consumer->curveToQuadraticSmooth(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_mode);
+    m_consumer->curveToQuadraticSmooth(blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint), m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
@@ -173,16 +235,44 @@ bool SVGPathBlender::blendArcToSegment()
         || !m_toSource->parseArcToSegment(toRx, toRy, toAngle, toLargeArc, toSweep, toTargetPoint))
         return false;
 
-    m_consumer->arcTo(blendAnimatedFloat(fromRx, toRx),
-                      blendAnimatedFloat(fromRy, toRy),
-                      blendAnimatedFloat(fromAngle, toAngle),
-                      m_progress < 0.5 ? fromLargeArc : toLargeArc,
-                      m_progress < 0.5 ? fromSweep : toSweep,
+    m_consumer->arcTo(blendAnimatedFloat(fromRx, toRx, m_progress),
+                      blendAnimatedFloat(fromRy, toRy, m_progress),
+                      blendAnimatedFloat(fromAngle, toAngle, m_progress),
+                      m_isInFirstHalfOfAnimation ? fromLargeArc : toLargeArc,
+                      m_isInFirstHalfOfAnimation ? fromSweep : toSweep,
                       blendAnimatedFloatPoint(fromTargetPoint, toTargetPoint),
-                      m_mode);
+                      m_isInFirstHalfOfAnimation ? m_fromMode : m_toMode);
+    m_fromCurrentPoint = m_fromMode == AbsoluteCoordinates ? fromTargetPoint : m_fromCurrentPoint + fromTargetPoint;
+    m_toCurrentPoint = m_toMode == AbsoluteCoordinates ? toTargetPoint : m_toCurrentPoint + toTargetPoint;
     return true;
 }
 
+static inline PathCoordinateMode coordinateModeOfCommand(const SVGPathSegType& type)
+{
+    if (type < PathSegMoveToAbs)
+        return AbsoluteCoordinates;
+
+    // Odd number = relative command
+    if (type % 2)
+        return RelativeCoordinates;
+
+    return AbsoluteCoordinates;
+}
+
+static inline bool isSegmentEqual(const SVGPathSegType& fromType, const SVGPathSegType& toType, const PathCoordinateMode& fromMode, const PathCoordinateMode& toMode)
+{
+    if (fromType == toType && (fromType == PathSegUnknown || fromType == PathSegClosePath))
+        return true;
+
+    unsigned short from = fromType;
+    unsigned short to = toType;
+    if (fromMode == toMode)
+        return from == to;
+    if (fromMode == AbsoluteCoordinates)
+        return from == to - 1;
+    return to == from - 1;
+}
+
 bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource, SVGPathSource* toSource, SVGPathConsumer* consumer)
 {
     ASSERT(fromSource);
@@ -191,6 +281,7 @@ bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource
     m_fromSource = fromSource;
     m_toSource = toSource;
     m_consumer = consumer;
+    m_isInFirstHalfOfAnimation = progress < 0.5f;
 
     m_progress = progress;
     while (true) {
@@ -198,31 +289,29 @@ bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource
         SVGPathSegType toCommand;
         if (!m_fromSource->parseSVGSegmentType(fromCommand) || !m_toSource->parseSVGSegmentType(toCommand))
             return false;
-        if (fromCommand != toCommand)
+
+        m_fromMode = coordinateModeOfCommand(fromCommand);
+        m_toMode = coordinateModeOfCommand(toCommand);
+        if (!isSegmentEqual(fromCommand, toCommand, m_fromMode, m_toMode))
             return false;
 
-        m_mode = AbsoluteCoordinates;
         switch (fromCommand) {
         case PathSegMoveToRel:
-            m_mode = RelativeCoordinates;
         case PathSegMoveToAbs:
             if (!blendMoveToSegment())
                 return false;
             break;
         case PathSegLineToRel:
-            m_mode = RelativeCoordinates;
         case PathSegLineToAbs:
             if (!blendLineToSegment())
                 return false;
             break;
         case PathSegLineToHorizontalRel:
-            m_mode = RelativeCoordinates;
         case PathSegLineToHorizontalAbs:
             if (!blendLineToHorizontalSegment())
                 return false;
             break;
         case PathSegLineToVerticalRel:
-            m_mode = RelativeCoordinates;
         case PathSegLineToVerticalAbs:
             if (!blendLineToVerticalSegment())
                 return false;
@@ -231,31 +320,26 @@ bool SVGPathBlender::blendAnimatedPath(float progress, SVGPathSource* fromSource
             m_consumer->closePath();
             break;
         case PathSegCurveToCubicRel:
-            m_mode = RelativeCoordinates;
         case PathSegCurveToCubicAbs:
             if (!blendCurveToCubicSegment())
                 return false;
             break;
         case PathSegCurveToCubicSmoothRel:
-            m_mode = RelativeCoordinates;
         case PathSegCurveToCubicSmoothAbs:
             if (!blendCurveToCubicSmoothSegment())
                 return false;
             break;
         case PathSegCurveToQuadraticRel:
-            m_mode = RelativeCoordinates;
         case PathSegCurveToQuadraticAbs:
             if (!blendCurveToQuadraticSegment())
                 return false;
             break;
         case PathSegCurveToQuadraticSmoothRel:
-            m_mode = RelativeCoordinates;
         case PathSegCurveToQuadraticSmoothAbs:
             if (!blendCurveToQuadraticSmoothSegment())
                 return false;
             break;
         case PathSegArcRel:
-            m_mode = RelativeCoordinates;
         case PathSegArcAbs:
             if (!blendArcToSegment())
                 return false;
@@ -281,6 +365,8 @@ void SVGPathBlender::cleanup()
     m_toSource = 0;
     m_fromSource = 0;
     m_consumer = 0;
+    m_fromCurrentPoint = FloatPoint();
+    m_toCurrentPoint = FloatPoint();
 }
 
 }
diff --git a/Source/WebCore/svg/SVGPathBlender.h b/Source/WebCore/svg/SVGPathBlender.h
index 8e43b94..2290fbb 100644
--- a/Source/WebCore/svg/SVGPathBlender.h
+++ b/Source/WebCore/svg/SVGPathBlender.h
@@ -26,6 +26,11 @@
 
 namespace WebCore {
 
+enum FloatBlendMode {
+    BlendHorizontal,
+    BlendVertical
+};
+
 class SVGPathBlender {
     WTF_MAKE_NONCOPYABLE(SVGPathBlender); WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -45,14 +50,20 @@ private:
     bool blendCurveToQuadraticSmoothSegment();
     bool blendArcToSegment();
 
-    float blendAnimatedFloat(float, float);
-    FloatPoint blendAnimatedFloatPoint(FloatPoint&, FloatPoint&);
+    float blendAnimatedDimensonalFloat(float, float, FloatBlendMode);
+    FloatPoint blendAnimatedFloatPoint(const FloatPoint& from, const FloatPoint& to);
 
     SVGPathSource* m_fromSource;
     SVGPathSource* m_toSource;
     SVGPathConsumer* m_consumer;
-    PathCoordinateMode m_mode;
+
+    FloatPoint m_fromCurrentPoint;
+    FloatPoint m_toCurrentPoint;
+    
+    PathCoordinateMode m_fromMode;
+    PathCoordinateMode m_toMode;
     float m_progress;
+    bool m_isInFirstHalfOfAnimation;
 };
 
 } // namespace WebCore

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list