Enable animVal support for SVGLengthList
authorzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Mar 2012 10:00:04 +0000 (10:00 +0000)
committerzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Mar 2012 10:00:04 +0000 (10:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=80750

Reviewed by Zoltan Herczeg.

Source/WebCore:

Introduce animVal support for generic SVGList types. This aligns SVGListProperty with SVGProperty
in terms of animVal/baseVal support. Use this to turn on animVal support for SVGLengthList.

Extend all existing SVGLengthList tests to correctly differentiate between baseVal/animVal.

* svg/SVGAnimateElement.cpp:
(WebCore::SVGAnimateElement::calculateAnimatedValue):
* svg/SVGAnimateTransformElement.cpp:
(WebCore::SVGAnimateTransformElement::resetToBaseValue):
(WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
(WebCore::SVGAnimateTransformElement::applyResultsToTarget):
* svg/SVGAnimatedLengthList.cpp:
(WebCore::SVGAnimatedLengthListAnimator::constructFromCopy):
(WebCore):
* svg/SVGAnimatedLengthList.h:
(WebCore):
(SVGAnimatedLengthListAnimator):
* svg/SVGAnimatedType.cpp:
(WebCore::SVGAnimatedType::supportsAnimVal):
(WebCore::SVGAnimatedType::setVariantValue):
* svg/SVGAnimatedType.h:
* svg/SVGAnimationElement.cpp:
(WebCore::SVGAnimationElement::applyAnimatedValue):
* svg/properties/SVGAnimatedListPropertyTearOff.h:
(SVGAnimatedListPropertyTearOff):
(WebCore::SVGAnimatedListPropertyTearOff::baseVal):
(WebCore::SVGAnimatedListPropertyTearOff::animVal):
(WebCore::SVGAnimatedListPropertyTearOff::removeItemFromList):
(WebCore::SVGAnimatedListPropertyTearOff::detachListWrappers):
(WebCore::SVGAnimatedListPropertyTearOff::currentAnimatedValue):
(WebCore::SVGAnimatedListPropertyTearOff::currentBaseValue):
(WebCore::SVGAnimatedListPropertyTearOff::animationStarted):
(WebCore::SVGAnimatedListPropertyTearOff::animationEnded):
(WebCore::SVGAnimatedListPropertyTearOff::synchronizeWrappersIfNeeded):
(WebCore::SVGAnimatedListPropertyTearOff::animationValueWillChange):
(WebCore::SVGAnimatedListPropertyTearOff::animationValueDidChange):
* svg/properties/SVGAnimatedPathSegListPropertyTearOff.h:
(WebCore::SVGAnimatedPathSegListPropertyTearOff::baseVal):
(WebCore::SVGAnimatedPathSegListPropertyTearOff::animVal):
* svg/properties/SVGAnimatedProperty.h:
(WebCore::SVGAnimatedProperty::isAnimating):
(SVGAnimatedProperty):
(WebCore::SVGAnimatedProperty::animationValueWillChange):
(WebCore::SVGAnimatedProperty::animationValueDidChange):
(WebCore::SVGAnimatedProperty::~SVGAnimatedProperty):
(WebCore::SVGAnimatedProperty::SVGAnimatedProperty):
* svg/properties/SVGAnimatedPropertyTearOff.h:
(SVGAnimatedPropertyTearOff):
(WebCore::SVGAnimatedPropertyTearOff::baseVal):
(WebCore::SVGAnimatedPropertyTearOff::animVal):
(WebCore::SVGAnimatedPropertyTearOff::currentAnimatedValue):
(WebCore::SVGAnimatedPropertyTearOff::animationStarted):
(WebCore::SVGAnimatedPropertyTearOff::animationEnded):
(WebCore::SVGAnimatedPropertyTearOff::animationValueWillChange):
(WebCore::SVGAnimatedPropertyTearOff::animationValueDidChange):
(WebCore::SVGAnimatedPropertyTearOff::SVGAnimatedPropertyTearOff):
* svg/properties/SVGAnimatedTransformListPropertyTearOff.h:
(WebCore::SVGAnimatedTransformListPropertyTearOff::baseVal):
(WebCore::SVGAnimatedTransformListPropertyTearOff::animVal):
* svg/properties/SVGListProperty.h:
(WebCore::SVGListProperty::detachListWrappers):
(SVGListProperty):
(WebCore::SVGListProperty::setValuesAndWrappers):
(WebCore::SVGListProperty::clearValues):
(WebCore::SVGListProperty::clearValuesAndWrappers):
(WebCore::SVGListProperty::numberOfItems):
(WebCore::SVGListProperty::initializeValues):
(WebCore::SVGListProperty::initializeValuesAndWrappers):
(WebCore::SVGListProperty::canGetItem):
(WebCore::SVGListProperty::getItemValues):
(WebCore::SVGListProperty::getItemValuesAndWrappers):
(WebCore::SVGListProperty::insertItemBeforeValues):
(WebCore::SVGListProperty::insertItemBeforeValuesAndWrappers):
(WebCore::SVGListProperty::canReplaceItem):
(WebCore::SVGListProperty::replaceItemValues):
(WebCore::SVGListProperty::replaceItemValuesAndWrappers):
(WebCore::SVGListProperty::canRemoveItem):
(WebCore::SVGListProperty::removeItemValues):
(WebCore::SVGListProperty::removeItemValuesAndWrappers):
(WebCore::SVGListProperty::appendItemValues):
(WebCore::SVGListProperty::appendItemValuesAndWrappers):
(WebCore::SVGListProperty::values):
(WebCore::SVGListProperty::wrappers):
(WebCore::SVGListProperty::SVGListProperty):
* svg/properties/SVGListPropertyTearOff.h:
(SVGListPropertyTearOff):
(WebCore::SVGListPropertyTearOff::create):
(WebCore::SVGListPropertyTearOff::removeItemFromList):
(WebCore::SVGListPropertyTearOff::clear):
(WebCore::SVGListPropertyTearOff::initialize):
(WebCore::SVGListPropertyTearOff::insertItemBefore):
(WebCore::SVGListPropertyTearOff::replaceItem):
(WebCore::SVGListPropertyTearOff::appendItem):
(WebCore::SVGListPropertyTearOff::SVGListPropertyTearOff):
(WebCore::SVGListPropertyTearOff::commitChange):
* svg/properties/SVGPathSegListPropertyTearOff.cpp:
(WebCore::SVGPathSegListPropertyTearOff::clear):
(WebCore::SVGPathSegListPropertyTearOff::getItem):
(WebCore::SVGPathSegListPropertyTearOff::removeItem):
* svg/properties/SVGPathSegListPropertyTearOff.h:
(WebCore::SVGPathSegListPropertyTearOff::create):
(WebCore::SVGPathSegListPropertyTearOff::removeItemFromList):
(SVGPathSegListPropertyTearOff):
(WebCore::SVGPathSegListPropertyTearOff::initialize):
(WebCore::SVGPathSegListPropertyTearOff::insertItemBefore):
(WebCore::SVGPathSegListPropertyTearOff::replaceItem):
(WebCore::SVGPathSegListPropertyTearOff::appendItem):
(WebCore::SVGPathSegListPropertyTearOff::SVGPathSegListPropertyTearOff):
(WebCore::SVGPathSegListPropertyTearOff::commitChange):
* svg/properties/SVGPropertyInfo.h:
* svg/properties/SVGStaticListPropertyTearOff.h:
(SVGStaticListPropertyTearOff):
(WebCore::SVGStaticListPropertyTearOff::clear):
(WebCore::SVGStaticListPropertyTearOff::initialize):
(WebCore::SVGStaticListPropertyTearOff::getItem):
(WebCore::SVGStaticListPropertyTearOff::insertItemBefore):
(WebCore::SVGStaticListPropertyTearOff::replaceItem):
(WebCore::SVGStaticListPropertyTearOff::removeItem):
(WebCore::SVGStaticListPropertyTearOff::appendItem):
(WebCore::SVGStaticListPropertyTearOff::SVGStaticListPropertyTearOff):
(WebCore::SVGStaticListPropertyTearOff::commitChange):
* svg/properties/SVGTransformListPropertyTearOff.h:
(WebCore::SVGTransformListPropertyTearOff::create):
(WebCore::SVGTransformListPropertyTearOff::createSVGTransformFromMatrix):
(WebCore::SVGTransformListPropertyTearOff::consolidate):
(WebCore::SVGTransformListPropertyTearOff::SVGTransformListPropertyTearOff):

LayoutTests:

Update test expectations after turning on animVal support for SVGLengthList.

* svg/animations/script-tests/svglengthlist-animation-1.js:
(sample1):
(sample2):
(sample3):
* svg/animations/script-tests/svglengthlist-animation-2.js:
(sample1):
(sample2):
(sample3):
* svg/animations/script-tests/svglengthlist-animation-3.js:
(sample1):
(sample2):
(sample3):
* svg/animations/script-tests/svglengthlist-animation-4.js:
(sample1):
(sample2):
(sample3):
* svg/animations/script-tests/svglengthlist-animation-5.js:
(sample1):
(sample2):
(sample3):
* svg/animations/svglengthlist-animation-1-expected.txt:
* svg/animations/svglengthlist-animation-2-expected.txt:
* svg/animations/svglengthlist-animation-3-expected.txt:
* svg/animations/svglengthlist-animation-4-expected.txt:
* svg/animations/svglengthlist-animation-5-expected.txt:

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

29 files changed:
LayoutTests/ChangeLog
LayoutTests/svg/animations/script-tests/svglengthlist-animation-1.js
LayoutTests/svg/animations/script-tests/svglengthlist-animation-2.js
LayoutTests/svg/animations/script-tests/svglengthlist-animation-3.js
LayoutTests/svg/animations/script-tests/svglengthlist-animation-4.js
LayoutTests/svg/animations/script-tests/svglengthlist-animation-5.js
LayoutTests/svg/animations/svglengthlist-animation-1-expected.txt
LayoutTests/svg/animations/svglengthlist-animation-2-expected.txt
LayoutTests/svg/animations/svglengthlist-animation-3-expected.txt
LayoutTests/svg/animations/svglengthlist-animation-4-expected.txt
LayoutTests/svg/animations/svglengthlist-animation-5-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/svg/SVGAnimateElement.cpp
Source/WebCore/svg/SVGAnimateTransformElement.cpp
Source/WebCore/svg/SVGAnimatedLengthList.cpp
Source/WebCore/svg/SVGAnimatedLengthList.h
Source/WebCore/svg/SVGAnimatedType.cpp
Source/WebCore/svg/SVGAnimationElement.cpp
Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h
Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h
Source/WebCore/svg/properties/SVGAnimatedProperty.h
Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h
Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h
Source/WebCore/svg/properties/SVGListProperty.h
Source/WebCore/svg/properties/SVGListPropertyTearOff.h
Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp
Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h
Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h
Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h

index be89205..ddad5db 100644 (file)
@@ -1,3 +1,38 @@
+2012-03-13  Nikolas Zimmermann  <nzimmermann@rim.com>
+
+        Enable animVal support for SVGLengthList
+        https://bugs.webkit.org/show_bug.cgi?id=80750
+
+        Reviewed by Zoltan Herczeg.
+
+        Update test expectations after turning on animVal support for SVGLengthList.
+
+        * svg/animations/script-tests/svglengthlist-animation-1.js:
+        (sample1):
+        (sample2):
+        (sample3):
+        * svg/animations/script-tests/svglengthlist-animation-2.js:
+        (sample1):
+        (sample2):
+        (sample3):
+        * svg/animations/script-tests/svglengthlist-animation-3.js:
+        (sample1):
+        (sample2):
+        (sample3):
+        * svg/animations/script-tests/svglengthlist-animation-4.js:
+        (sample1):
+        (sample2):
+        (sample3):
+        * svg/animations/script-tests/svglengthlist-animation-5.js:
+        (sample1):
+        (sample2):
+        (sample3):
+        * svg/animations/svglengthlist-animation-1-expected.txt:
+        * svg/animations/svglengthlist-animation-2-expected.txt:
+        * svg/animations/svglengthlist-animation-3-expected.txt:
+        * svg/animations/svglengthlist-animation-4-expected.txt:
+        * svg/animations/svglengthlist-animation-5-expected.txt:
+
 2012-03-15  Philippe Normand  <pnormand@igalia.com>
 
         Unreviewed, GTK baselines for new fast/css test.
index 32c8f20..4e4ab66 100644 (file)
@@ -21,24 +21,45 @@ text.appendChild(animate);
 
 // Setup animation test
 function sample1() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "50");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "70");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "110");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "70");
+    shouldBe("text.x.baseVal.getItem(2).value", "90");
+    shouldBe("text.x.baseVal.getItem(3).value", "110");
 }
 
 function sample2() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "55");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "105");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "130");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "70");
+    shouldBe("text.x.baseVal.getItem(2).value", "90");
+    shouldBe("text.x.baseVal.getItem(3).value", "110");
 }
 
 function sample3() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "60");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "90");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "120");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "150");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "70");
+    shouldBe("text.x.baseVal.getItem(2).value", "90");
+    shouldBe("text.x.baseVal.getItem(3).value", "110");
 }
 
 function executeTest() {
index c6cc076..1381fd8 100644 (file)
@@ -21,24 +21,45 @@ text.appendChild(animate);
 
 // Setup animation test
 function sample1() {
-       shouldBeCloseEnough("text.x.animVal.getItem(0).value", "50");
-       shouldBeCloseEnough("text.x.animVal.getItem(1).value", "70");
-       shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
-       shouldBeCloseEnough("text.x.animVal.getItem(3).value", "110");
+    shouldBe("text.x.animVal.numberOfItems", "4");
+    shouldBeCloseEnough("text.x.animVal.getItem(0).value", "50");
+    shouldBeCloseEnough("text.x.animVal.getItem(1).value", "70");
+    shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
+    shouldBeCloseEnough("text.x.animVal.getItem(3).value", "110");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "70");
+    shouldBe("text.x.baseVal.getItem(2).value", "90");
+    shouldBe("text.x.baseVal.getItem(3).value", "110");
 }
 
 function sample2() {
-       shouldBeCloseEnough("text.x.animVal.getItem(0).value", "81.7");
-       shouldBeCloseEnough("text.x.animVal.getItem(1).value", "75");
-       shouldBeCloseEnough("text.x.animVal.getItem(2).value", "144.5");
-       shouldBeCloseEnough("text.x.animVal.getItem(3).value", "197.3");
+    shouldBe("text.x.animVal.numberOfItems", "4");
+    shouldBeCloseEnough("text.x.animVal.getItem(0).value", "81.7");
+    shouldBeCloseEnough("text.x.animVal.getItem(1).value", "75");
+    shouldBeCloseEnough("text.x.animVal.getItem(2).value", "144.5");
+    shouldBeCloseEnough("text.x.animVal.getItem(3).value", "197.3");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "70");
+    shouldBe("text.x.baseVal.getItem(2).value", "90");
+    shouldBe("text.x.baseVal.getItem(3).value", "110");
 }
 
 function sample3() {
-       shouldBeCloseEnough("text.x.animVal.getItem(0).value", "113.4");
-       shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
-       shouldBeCloseEnough("text.x.animVal.getItem(2).value", "100");
-       shouldBeCloseEnough("text.x.animVal.getItem(3).value", "384");
+    shouldBe("text.x.animVal.numberOfItems", "4");
+    shouldBeCloseEnough("text.x.animVal.getItem(0).value", "113.4");
+    shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
+    shouldBeCloseEnough("text.x.animVal.getItem(2).value", "100");
+    shouldBeCloseEnough("text.x.animVal.getItem(3).value", "384");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "70");
+    shouldBe("text.x.baseVal.getItem(2).value", "90");
+    shouldBe("text.x.baseVal.getItem(3).value", "110");
 }
 
 function executeTest() {
index 7da9a4d..68ac562 100644 (file)
@@ -23,6 +23,9 @@ text.appendChild(animate);
 function sample1() {
     shouldBe("text.x.animVal.numberOfItems", "1");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "50");
+
+    shouldBe("text.x.baseVal.numberOfItems", "1");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
 }
 
 function sample2() {
@@ -31,6 +34,9 @@ function sample2() {
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "110");
+
+    shouldBe("text.x.baseVal.numberOfItems", "1");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
 }
 
 function sample3() {
@@ -39,6 +45,9 @@ function sample3() {
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "110");
+
+    shouldBe("text.x.baseVal.numberOfItems", "1");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
 }
 
 function executeTest() {
index acbe086..7ef4f36 100644 (file)
@@ -21,17 +21,31 @@ text.appendChild(animate);
 
 // Setup animation test
 function sample1() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "50");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "60");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "70");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "80");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "60");
+    shouldBe("text.x.baseVal.getItem(2).value", "70");
+    shouldBe("text.x.baseVal.getItem(3).value", "80");
 }
 
 function sample2() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "60");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "70");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "90");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "60");
+    shouldBe("text.x.baseVal.getItem(2).value", "70");
+    shouldBe("text.x.baseVal.getItem(3).value", "80");
 }
 
 function sample3() {
@@ -40,6 +54,12 @@ function sample3() {
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "100");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "60");
+    shouldBe("text.x.baseVal.getItem(2).value", "70");
+    shouldBe("text.x.baseVal.getItem(3).value", "80");
 }
 
 function executeTest() {
index ca1da72..66966d6 100644 (file)
@@ -22,24 +22,45 @@ text.appendChild(animate);
 
 // Setup animation test
 function sample1() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "50");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "60");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "70");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "80");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "60");
+    shouldBe("text.x.baseVal.getItem(2).value", "70");
+    shouldBe("text.x.baseVal.getItem(3).value", "80");
 }
 
 function sample2() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "60");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "70");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "90");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "60");
+    shouldBe("text.x.baseVal.getItem(2).value", "70");
+    shouldBe("text.x.baseVal.getItem(3).value", "80");
 }
 
 function sample3() {
+    shouldBe("text.x.animVal.numberOfItems", "4");
     shouldBeCloseEnough("text.x.animVal.getItem(0).value", "70");
     shouldBeCloseEnough("text.x.animVal.getItem(1).value", "80");
     shouldBeCloseEnough("text.x.animVal.getItem(2).value", "90");
     shouldBeCloseEnough("text.x.animVal.getItem(3).value", "100");
+
+    shouldBe("text.x.baseVal.numberOfItems", "4");
+    shouldBe("text.x.baseVal.getItem(0).value", "50");
+    shouldBe("text.x.baseVal.getItem(1).value", "60");
+    shouldBe("text.x.baseVal.getItem(2).value", "70");
+    shouldBe("text.x.baseVal.getItem(3).value", "80");
 }
 
 function executeTest() {
index 1b2a13e..2dd7360 100644 (file)
@@ -6,22 +6,46 @@ Test 'to' animation of SVGLengthList with LengthType number.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 70
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 110
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 55
 PASS text.x.animVal.getItem(1).value is 80
 PASS text.x.animVal.getItem(2).value is 105
 PASS text.x.animVal.getItem(3).value is 130
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 60
 PASS text.x.animVal.getItem(1).value is 90
 PASS text.x.animVal.getItem(2).value is 120
 PASS text.x.animVal.getItem(3).value is 150
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 70
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 110
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 954db38..fed1183 100644 (file)
@@ -6,22 +6,46 @@ Test 'to' animation of SVGLengthList with different LengthTypes.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 70
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 110
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 81.7
 PASS text.x.animVal.getItem(1).value is 75
 PASS text.x.animVal.getItem(2).value is 144.5
 PASS text.x.animVal.getItem(3).value is 197.3
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 113.4
 PASS text.x.animVal.getItem(1).value is 80
 PASS text.x.animVal.getItem(2).value is 100
 PASS text.x.animVal.getItem(3).value is 384
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 70
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 110
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 70
+PASS text.x.baseVal.getItem(2).value is 90
+PASS text.x.baseVal.getItem(3).value is 110
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 93162b4..22d2266 100644 (file)
@@ -8,18 +8,26 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 PASS text.x.animVal.numberOfItems is 1
 PASS text.x.animVal.getItem(0).value is 50
+PASS text.x.baseVal.numberOfItems is 1
+PASS text.x.baseVal.getItem(0).value is 50
 PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 70
 PASS text.x.animVal.getItem(1).value is 80
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 110
+PASS text.x.baseVal.numberOfItems is 1
+PASS text.x.baseVal.getItem(0).value is 50
 PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 70
 PASS text.x.animVal.getItem(1).value is 80
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 110
+PASS text.x.baseVal.numberOfItems is 1
+PASS text.x.baseVal.getItem(0).value is 50
 PASS text.x.animVal.numberOfItems is 1
 PASS text.x.animVal.getItem(0).value is 50
+PASS text.x.baseVal.numberOfItems is 1
+PASS text.x.baseVal.getItem(0).value is 50
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 3e39eef..60c228d 100644 (file)
@@ -6,23 +6,46 @@ Test 'by' animation of SVGLengthList.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 60
 PASS text.x.animVal.getItem(2).value is 70
 PASS text.x.animVal.getItem(3).value is 80
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 60
 PASS text.x.animVal.getItem(1).value is 70
 PASS text.x.animVal.getItem(2).value is 80
 PASS text.x.animVal.getItem(3).value is 90
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
 PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 70
 PASS text.x.animVal.getItem(1).value is 80
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 100
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 60
 PASS text.x.animVal.getItem(2).value is 70
 PASS text.x.animVal.getItem(3).value is 80
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 43278b7..cee3641 100644 (file)
@@ -6,22 +6,46 @@ Test additive='sum' animation of SVGLengthList.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 60
 PASS text.x.animVal.getItem(2).value is 70
 PASS text.x.animVal.getItem(3).value is 80
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 60
 PASS text.x.animVal.getItem(1).value is 70
 PASS text.x.animVal.getItem(2).value is 80
 PASS text.x.animVal.getItem(3).value is 90
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 70
 PASS text.x.animVal.getItem(1).value is 80
 PASS text.x.animVal.getItem(2).value is 90
 PASS text.x.animVal.getItem(3).value is 100
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
+PASS text.x.animVal.numberOfItems is 4
 PASS text.x.animVal.getItem(0).value is 50
 PASS text.x.animVal.getItem(1).value is 60
 PASS text.x.animVal.getItem(2).value is 70
 PASS text.x.animVal.getItem(3).value is 80
+PASS text.x.baseVal.numberOfItems is 4
+PASS text.x.baseVal.getItem(0).value is 50
+PASS text.x.baseVal.getItem(1).value is 60
+PASS text.x.baseVal.getItem(2).value is 70
+PASS text.x.baseVal.getItem(3).value is 80
 PASS successfullyParsed is true
 
 TEST COMPLETE
index a9666fe..37e9852 100644 (file)
@@ -1,3 +1,137 @@
+2012-03-13  Nikolas Zimmermann  <nzimmermann@rim.com>
+
+        Enable animVal support for SVGLengthList
+        https://bugs.webkit.org/show_bug.cgi?id=80750
+
+        Reviewed by Zoltan Herczeg.
+
+        Introduce animVal support for generic SVGList types. This aligns SVGListProperty with SVGProperty
+        in terms of animVal/baseVal support. Use this to turn on animVal support for SVGLengthList.
+
+        Extend all existing SVGLengthList tests to correctly differentiate between baseVal/animVal.
+
+        * svg/SVGAnimateElement.cpp:
+        (WebCore::SVGAnimateElement::calculateAnimatedValue):
+        * svg/SVGAnimateTransformElement.cpp:
+        (WebCore::SVGAnimateTransformElement::resetToBaseValue):
+        (WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
+        (WebCore::SVGAnimateTransformElement::applyResultsToTarget):
+        * svg/SVGAnimatedLengthList.cpp:
+        (WebCore::SVGAnimatedLengthListAnimator::constructFromCopy):
+        (WebCore):
+        * svg/SVGAnimatedLengthList.h:
+        (WebCore):
+        (SVGAnimatedLengthListAnimator):
+        * svg/SVGAnimatedType.cpp:
+        (WebCore::SVGAnimatedType::supportsAnimVal):
+        (WebCore::SVGAnimatedType::setVariantValue):
+        * svg/SVGAnimatedType.h:
+        * svg/SVGAnimationElement.cpp:
+        (WebCore::SVGAnimationElement::applyAnimatedValue):
+        * svg/properties/SVGAnimatedListPropertyTearOff.h:
+        (SVGAnimatedListPropertyTearOff):
+        (WebCore::SVGAnimatedListPropertyTearOff::baseVal):
+        (WebCore::SVGAnimatedListPropertyTearOff::animVal):
+        (WebCore::SVGAnimatedListPropertyTearOff::removeItemFromList):
+        (WebCore::SVGAnimatedListPropertyTearOff::detachListWrappers):
+        (WebCore::SVGAnimatedListPropertyTearOff::currentAnimatedValue):
+        (WebCore::SVGAnimatedListPropertyTearOff::currentBaseValue):
+        (WebCore::SVGAnimatedListPropertyTearOff::animationStarted):
+        (WebCore::SVGAnimatedListPropertyTearOff::animationEnded):
+        (WebCore::SVGAnimatedListPropertyTearOff::synchronizeWrappersIfNeeded):
+        (WebCore::SVGAnimatedListPropertyTearOff::animationValueWillChange):
+        (WebCore::SVGAnimatedListPropertyTearOff::animationValueDidChange):
+        * svg/properties/SVGAnimatedPathSegListPropertyTearOff.h:
+        (WebCore::SVGAnimatedPathSegListPropertyTearOff::baseVal):
+        (WebCore::SVGAnimatedPathSegListPropertyTearOff::animVal):
+        * svg/properties/SVGAnimatedProperty.h:
+        (WebCore::SVGAnimatedProperty::isAnimating):
+        (SVGAnimatedProperty):
+        (WebCore::SVGAnimatedProperty::animationValueWillChange):
+        (WebCore::SVGAnimatedProperty::animationValueDidChange):
+        (WebCore::SVGAnimatedProperty::~SVGAnimatedProperty):
+        (WebCore::SVGAnimatedProperty::SVGAnimatedProperty):
+        * svg/properties/SVGAnimatedPropertyTearOff.h:
+        (SVGAnimatedPropertyTearOff):
+        (WebCore::SVGAnimatedPropertyTearOff::baseVal):
+        (WebCore::SVGAnimatedPropertyTearOff::animVal):
+        (WebCore::SVGAnimatedPropertyTearOff::currentAnimatedValue):
+        (WebCore::SVGAnimatedPropertyTearOff::animationStarted):
+        (WebCore::SVGAnimatedPropertyTearOff::animationEnded):
+        (WebCore::SVGAnimatedPropertyTearOff::animationValueWillChange):
+        (WebCore::SVGAnimatedPropertyTearOff::animationValueDidChange):
+        (WebCore::SVGAnimatedPropertyTearOff::SVGAnimatedPropertyTearOff):
+        * svg/properties/SVGAnimatedTransformListPropertyTearOff.h:
+        (WebCore::SVGAnimatedTransformListPropertyTearOff::baseVal):
+        (WebCore::SVGAnimatedTransformListPropertyTearOff::animVal):
+        * svg/properties/SVGListProperty.h:
+        (WebCore::SVGListProperty::detachListWrappers):
+        (SVGListProperty):
+        (WebCore::SVGListProperty::setValuesAndWrappers):
+        (WebCore::SVGListProperty::clearValues):
+        (WebCore::SVGListProperty::clearValuesAndWrappers):
+        (WebCore::SVGListProperty::numberOfItems):
+        (WebCore::SVGListProperty::initializeValues):
+        (WebCore::SVGListProperty::initializeValuesAndWrappers):
+        (WebCore::SVGListProperty::canGetItem):
+        (WebCore::SVGListProperty::getItemValues):
+        (WebCore::SVGListProperty::getItemValuesAndWrappers):
+        (WebCore::SVGListProperty::insertItemBeforeValues):
+        (WebCore::SVGListProperty::insertItemBeforeValuesAndWrappers):
+        (WebCore::SVGListProperty::canReplaceItem):
+        (WebCore::SVGListProperty::replaceItemValues):
+        (WebCore::SVGListProperty::replaceItemValuesAndWrappers):
+        (WebCore::SVGListProperty::canRemoveItem):
+        (WebCore::SVGListProperty::removeItemValues):
+        (WebCore::SVGListProperty::removeItemValuesAndWrappers):
+        (WebCore::SVGListProperty::appendItemValues):
+        (WebCore::SVGListProperty::appendItemValuesAndWrappers):
+        (WebCore::SVGListProperty::values):
+        (WebCore::SVGListProperty::wrappers):
+        (WebCore::SVGListProperty::SVGListProperty):
+        * svg/properties/SVGListPropertyTearOff.h:
+        (SVGListPropertyTearOff):
+        (WebCore::SVGListPropertyTearOff::create):
+        (WebCore::SVGListPropertyTearOff::removeItemFromList):
+        (WebCore::SVGListPropertyTearOff::clear):
+        (WebCore::SVGListPropertyTearOff::initialize):
+        (WebCore::SVGListPropertyTearOff::insertItemBefore):
+        (WebCore::SVGListPropertyTearOff::replaceItem):
+        (WebCore::SVGListPropertyTearOff::appendItem):
+        (WebCore::SVGListPropertyTearOff::SVGListPropertyTearOff):
+        (WebCore::SVGListPropertyTearOff::commitChange):
+        * svg/properties/SVGPathSegListPropertyTearOff.cpp:
+        (WebCore::SVGPathSegListPropertyTearOff::clear):
+        (WebCore::SVGPathSegListPropertyTearOff::getItem):
+        (WebCore::SVGPathSegListPropertyTearOff::removeItem):
+        * svg/properties/SVGPathSegListPropertyTearOff.h:
+        (WebCore::SVGPathSegListPropertyTearOff::create):
+        (WebCore::SVGPathSegListPropertyTearOff::removeItemFromList):
+        (SVGPathSegListPropertyTearOff):
+        (WebCore::SVGPathSegListPropertyTearOff::initialize):
+        (WebCore::SVGPathSegListPropertyTearOff::insertItemBefore):
+        (WebCore::SVGPathSegListPropertyTearOff::replaceItem):
+        (WebCore::SVGPathSegListPropertyTearOff::appendItem):
+        (WebCore::SVGPathSegListPropertyTearOff::SVGPathSegListPropertyTearOff):
+        (WebCore::SVGPathSegListPropertyTearOff::commitChange):
+        * svg/properties/SVGPropertyInfo.h:
+        * svg/properties/SVGStaticListPropertyTearOff.h:
+        (SVGStaticListPropertyTearOff):
+        (WebCore::SVGStaticListPropertyTearOff::clear):
+        (WebCore::SVGStaticListPropertyTearOff::initialize):
+        (WebCore::SVGStaticListPropertyTearOff::getItem):
+        (WebCore::SVGStaticListPropertyTearOff::insertItemBefore):
+        (WebCore::SVGStaticListPropertyTearOff::replaceItem):
+        (WebCore::SVGStaticListPropertyTearOff::removeItem):
+        (WebCore::SVGStaticListPropertyTearOff::appendItem):
+        (WebCore::SVGStaticListPropertyTearOff::SVGStaticListPropertyTearOff):
+        (WebCore::SVGStaticListPropertyTearOff::commitChange):
+        * svg/properties/SVGTransformListPropertyTearOff.h:
+        (WebCore::SVGTransformListPropertyTearOff::create):
+        (WebCore::SVGTransformListPropertyTearOff::createSVGTransformFromMatrix):
+        (WebCore::SVGTransformListPropertyTearOff::consolidate):
+        (WebCore::SVGTransformListPropertyTearOff::SVGTransformListPropertyTearOff):
+
 2012-03-14  Chris Fleizach  <cfleizach@apple.com>
 
         AXDescription for HTML5 footer
index 9d467c1..06e4c81 100644 (file)
@@ -187,6 +187,14 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
 
     // Target element might have changed.
     m_animator->setContextElement(targetElement);
+
+    // Be sure to detach list wrappers before we modfiy their underlying value. If we'd do
+    // if after calculateAnimatedValue() ran the cached pointers in the list propery tear
+    // offs would point nowhere, and we couldn't create copies of those values anymore,
+    // while detaching. This is covered by assertions, moving this down would fire them.
+    if (SVGAnimatedProperty* animatedProperty = animatedPropertyForType(m_animator->type()))
+        animatedProperty->animationValueWillChange();
+
     m_animator->calculateAnimatedValue(percentage, repeat, m_fromType, m_toType, resultAnimationElement->m_animatedType);
 }
 
index 7a3e28e..c1bb199 100644 (file)
@@ -133,6 +133,9 @@ static PassRefPtr<SVGAnimatedTransformList> animatedTransformListFor(SVGElement*
     
 void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
 {
+    // FIXME: Once we added SVGAnimatedTransformListAnimator, this whole class is unncessary.
+    // See bug https://bugs.webkit.org/show_bug.cgi?id=80758. Once this is fixed animVal support
+    // for <animateTransform> is finished, and this class is almost empty.
     SVGElement* targetElement = this->targetElement();
     if (!targetElement || determineAnimatedPropertyType(targetElement) == AnimatedUnknown)
         return;
@@ -149,8 +152,9 @@ void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
     
     if (baseValue.isEmpty()) {
         if (RefPtr<SVGAnimatedTransformList> list = animatedTransformListFor(targetElement)) {
-            list->detachListWrappers(0);
-            list->values().clear();
+            SVGListProperty<SVGTransformList>* baseVal = static_cast<SVGListProperty<SVGTransformList>*>(list->baseVal());
+            baseVal->detachListWrappers(0);
+            baseVal->values().clear();
         }
     } else
         targetElement->setAttribute(SVGNames::transformAttr, baseValue);
@@ -158,24 +162,29 @@ void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
 
 void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement*)
 {
+    // FIXME: Once we added SVGAnimatedTransformListAnimator, this whole class is unncessary.
+    // See bug https://bugs.webkit.org/show_bug.cgi?id=80758. Once this is fixed animVal support
+    // for <animateTransform> is finished, and this class is almost empty.
     SVGElement* targetElement = this->targetElement();
     if (!targetElement || determineAnimatedPropertyType(targetElement) == AnimatedUnknown)
         return;
     RefPtr<SVGAnimatedTransformList> animatedList = animatedTransformListFor(targetElement);
     ASSERT(animatedList);
-    
+    SVGListProperty<SVGTransformList>* baseVal = static_cast<SVGListProperty<SVGTransformList>*>(animatedList->baseVal());
+    ASSERT(baseVal);
+
     if (calcMode() == CalcModeDiscrete)
         percentage = percentage < 0.5 ? 0 : 1;
 
     if (!isAdditive()) {
-        animatedList->detachListWrappers(0);
-        animatedList->values().clear();
+        baseVal->detachListWrappers(0);
+        baseVal->values().clear();
     }
     if (isAccumulated() && repeat)
         percentage += repeat;
     SVGTransform transform = SVGTransformDistance(m_fromTransform, m_toTransform).scaledDistance(percentage).addToSVGTransform(m_fromTransform);
-    animatedList->values().append(transform);
-    animatedList->wrappers().append(RefPtr<SVGPropertyTearOff<SVGTransform> >());
+    baseVal->values().append(transform);
+    baseVal->wrappers().append(RefPtr<SVGPropertyTearOff<SVGTransform> >());
 }
     
 bool SVGAnimateTransformElement::calculateFromAndToValues(const String& fromString, const String& toString)
@@ -224,7 +233,13 @@ void SVGAnimateTransformElement::applyResultsToTarget()
     RefPtr<SVGAnimatedTransformList> animatedList = animatedTransformListFor(targetElement);
     if (!animatedList)
         return;
-    SVGTransformList* transformList = &animatedList->values();
+
+    // FIXME: Once we added SVGAnimatedTransformListAnimator, this whole class is unncessary.
+    // See bug https://bugs.webkit.org/show_bug.cgi?id=80758. Once this is fixed animVal support
+    // for <animateTransform> is finished, and this class is almost empty.
+    SVGListProperty<SVGTransformList>* baseVal = static_cast<SVGListProperty<SVGTransformList>*>(animatedList->baseVal());
+    ASSERT(baseVal);
+    SVGTransformList& transformList = baseVal->values();
 
     const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
     const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
@@ -232,13 +247,13 @@ void SVGAnimateTransformElement::applyResultsToTarget()
         SVGElement* shadowTreeElement = (*it)->shadowTreeElement();
         ASSERT(shadowTreeElement);
         if (shadowTreeElement->isStyledTransformable())
-            static_cast<SVGStyledTransformableElement*>(shadowTreeElement)->setTransformBaseValue(*transformList);
+            static_cast<SVGStyledTransformableElement*>(shadowTreeElement)->setTransformBaseValue(transformList);
         else if (shadowTreeElement->hasTagName(SVGNames::textTag))
-            static_cast<SVGTextElement*>(shadowTreeElement)->setTransformBaseValue(*transformList);
+            static_cast<SVGTextElement*>(shadowTreeElement)->setTransformBaseValue(transformList);
         else if (shadowTreeElement->hasTagName(SVGNames::linearGradientTag) || shadowTreeElement->hasTagName(SVGNames::radialGradientTag))
-            static_cast<SVGGradientElement*>(shadowTreeElement)->setGradientTransformBaseValue(*transformList);
+            static_cast<SVGGradientElement*>(shadowTreeElement)->setGradientTransformBaseValue(transformList);
         else if (shadowTreeElement->hasTagName(SVGNames::patternTag))
-            static_cast<SVGPatternElement*>(shadowTreeElement)->setPatternTransformBaseValue(*transformList);
+            static_cast<SVGPatternElement*>(shadowTreeElement)->setPatternTransformBaseValue(transformList);
         if (RenderObject* renderer = shadowTreeElement->renderer()) {
             renderer->setNeedsTransformUpdate();
             RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
index 153e4f1..3a3e15a 100644 (file)
@@ -40,6 +40,12 @@ PassOwnPtr<SVGAnimatedType> SVGAnimatedLengthListAnimator::constructFromString(c
     return animateType.release();
 }
 
+PassOwnPtr<SVGAnimatedType> SVGAnimatedLengthListAnimator::constructFromCopy(SVGGenericAnimatedType* animatedType)
+{
+    ASSERT(animatedType);
+    return SVGAnimatedType::createLengthList(new SVGLengthList(*reinterpret_cast<SVGLengthList*>(animatedType)));
+}
+
 void SVGAnimatedLengthListAnimator::calculateFromAndToValues(OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, const String& fromString, const String& toString)
 {
     ASSERT(m_contextElement);
index cd43b0e..e3c2239 100644 (file)
@@ -37,6 +37,7 @@ DECLARE_ANIMATED_LIST_PROPERTY(SVGAnimatedLengthList, SVGLengthList, UpperProper
 DEFINE_ANIMATED_PROPERTY(AnimatedLengthList, OwnerType, DOMAttribute, DOMAttribute.localName(), UpperProperty, LowerProperty)
 
 class SVGAnimationElement;
+class SVGGenericAnimatedType;
 
 class SVGAnimatedLengthListAnimator : public SVGAnimatedTypeAnimator {
     
@@ -45,6 +46,7 @@ public:
     virtual ~SVGAnimatedLengthListAnimator() { }
     
     virtual PassOwnPtr<SVGAnimatedType> constructFromString(const String&);
+    virtual PassOwnPtr<SVGAnimatedType> constructFromCopy(SVGGenericAnimatedType*);
     
     virtual void calculateFromAndToValues(OwnPtr<SVGAnimatedType>& fromValue, OwnPtr<SVGAnimatedType>& toValue, const String& fromString, const String& toString);
     virtual void calculateFromAndByValues(OwnPtr<SVGAnimatedType>& fromValue, OwnPtr<SVGAnimatedType>& toValue, const String& fromString, const String& byString);
index 52e618b..3abaab9 100644 (file)
@@ -432,13 +432,13 @@ bool SVGAnimatedType::supportsAnimVal(AnimatedPropertyType type)
     // FIXME: This lists the current state of our animVal support: only SVGLength is supported for now.
     switch (type) {
     case AnimatedLength:
+    case AnimatedLengthList:
         return true;
     case AnimatedAngle:
     case AnimatedBoolean:
     case AnimatedColor:
     case AnimatedEnumeration:
     case AnimatedInteger:
-    case AnimatedLengthList:
     case AnimatedNumber:
     case AnimatedNumberList:
     case AnimatedNumberOptionalNumber:
@@ -463,12 +463,14 @@ void SVGAnimatedType::setVariantValue(SVGGenericAnimatedType* type)
     case AnimatedLength:
         *m_data.length = *reinterpret_cast<SVGLength*>(type);
         return;
+    case AnimatedLengthList:
+        *m_data.lengthList = *reinterpret_cast<SVGLengthList*>(type);
+        return;
     case AnimatedAngle:
     case AnimatedBoolean:
     case AnimatedColor:
     case AnimatedEnumeration:
     case AnimatedInteger:
-    case AnimatedLengthList:
     case AnimatedNumber:
     case AnimatedNumberList:
     case AnimatedNumberOptionalNumber:
index 1cb719b..d95ae53 100644 (file)
@@ -379,7 +379,7 @@ void SVGAnimationElement::applyAnimatedValue(SVGAnimationElement::ShouldApplyAni
         break;
     case ApplyXMLAnimation:
         if (SVGAnimatedProperty* property = findMatchingAnimatedProperty(targetElement, attributeName, animatedType->type())) {
-            property->animationValueChanged();
+            property->animationValueDidChange();
             break;
         }
 
index 8444c81..fccc04e 100644 (file)
@@ -22,6 +22,7 @@
 
 #if ENABLE(SVG)
 #include "SVGAnimatedProperty.h"
+#include "SVGAnimatedType.h"
 #include "SVGListPropertyTearOff.h"
 #include "SVGStaticListPropertyTearOff.h"
 
@@ -36,19 +37,20 @@ public:
     typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
     typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
     typedef Vector<RefPtr<ListItemTearOff> > ListWrapperCache;
+    typedef SVGListPropertyTearOff<PropertyType> ListPropertyTearOff;
 
-    SVGProperty* baseVal()
+    ListPropertyTearOff* baseVal()
     {
         if (!m_baseVal)
-            m_baseVal = SVGListPropertyTearOff<PropertyType>::create(this, BaseValRole);
-        return m_baseVal.get();
+            m_baseVal = ListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers);
+        return static_cast<ListPropertyTearOff*>(m_baseVal.get());
     }
 
-    SVGProperty* animVal()
+    ListPropertyTearOff* animVal()
     {
         if (!m_animVal)
-            m_animVal = SVGListPropertyTearOff<PropertyType>::create(this, AnimValRole);
-        return m_animVal.get();
+            m_animVal = ListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers);
+        return static_cast<ListPropertyTearOff*>(m_animVal.get());
     }
 
     virtual bool isAnimatedListTearOff() const { return true; }
@@ -57,34 +59,97 @@ public:
     {
         // This should ever be called for our baseVal, as animVal can't modify the list.
         typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff;
-        return static_pointer_cast<SVGListPropertyTearOff<PropertyType> >(m_baseVal)->removeItemFromList(static_cast<ListItemTearOff*>(property), shouldSynchronizeWrappers);
+        return static_cast<ListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(static_cast<ListItemTearOff*>(property), shouldSynchronizeWrappers);
     }
 
     void detachListWrappers(unsigned newListSize)
     {
-        // See SVGPropertyTearOff::detachWrapper() for an explaination what's happening here.
-        unsigned size = m_wrappers.size();
-        ASSERT(size == m_values.size());
-        for (unsigned i = 0; i < size; ++i) {
-            RefPtr<ListItemTearOff>& item = m_wrappers.at(i);
-            if (!item)
-                continue;
-            item->detachWrapper();
-        }
-
-        // Reinitialize the wrapper cache to be equal to the new values size, after the XML DOM changed the list.
-        if (newListSize)
-            m_wrappers.fill(0, newListSize);
-        else
-            m_wrappers.clear();
+        if (m_baseVal)
+            baseVal()->detachListWrappers(newListSize);
     }
 
-    PropertyType& values() { return m_values; }
-    ListWrapperCache& wrappers() { return m_wrappers; }
+    PropertyType& currentAnimatedValue()
+    {
+        ASSERT(m_isAnimating);
+        ASSERT(m_animVal);
+        return animVal()->values();
+    }
+
+    virtual SVGGenericAnimatedType* currentBaseValue(AnimatedPropertyType expectedPropertyType) const
+    {
+        ASSERT_UNUSED(expectedPropertyType, animatedPropertyType() == expectedPropertyType);
+        return reinterpret_cast<SVGGenericAnimatedType*>(&m_values);
+    }
+
+    virtual void animationStarted(SVGAnimatedType* animatedType)
+    {
+        ASSERT(!m_isAnimating);
+        ASSERT(animatedType);
+        ASSERT(animatedType->type() == animatedPropertyType());
+        ASSERT(m_values.size() == m_wrappers.size());
+        ASSERT(m_animatedWrappers.isEmpty());
+
+        // Switch to new passed in value type & new wrappers list. The new wrappers list must be created for the new value.
+        PropertyType* newAnimVal = reinterpret_cast<PropertyType*>(animatedType->variantValue());
+        if (!newAnimVal->isEmpty())
+            m_animatedWrappers.fill(0, newAnimVal->size());
+
+        animVal()->setValuesAndWrappers(newAnimVal, &m_animatedWrappers);
+        ASSERT(animVal()->values().size() == animVal()->wrappers().size());
+        ASSERT(animVal()->wrappers().size() == m_animatedWrappers.size());
+        m_isAnimating = true;
+    }
+
+    virtual void animationEnded()
+    {
+        ASSERT(m_isAnimating);
+        ASSERT(m_animVal);
+        ASSERT(m_values.size() == m_wrappers.size());
+        ASSERT(animVal()->values().size() == animVal()->wrappers().size());
+        ASSERT(animVal()->wrappers().size() == m_animatedWrappers.size());
+
+        animVal()->setValuesAndWrappers(&m_values, &m_wrappers);
+        ASSERT(animVal()->values().size() == animVal()->wrappers().size());
+        ASSERT(animVal()->wrappers().size() == m_wrappers.size());
+
+        m_animatedWrappers.clear();
+        m_isAnimating = false;
 
-    // FIXME: animVal support.
-    bool isAnimating() const { return false; }
-    PropertyType& currentAnimatedValue() { return m_values; }
+        ASSERT(contextElement());
+        contextElement()->svgAttributeChanged(attributeName());
+    }
+
+    void synchronizeWrappersIfNeeded()
+    {
+        // Eventually the wrapper list needs synchronization because any SVGAnimateLengthList::calculateAnimatedValue() call may
+        // mutate the length of our values() list, and thus the wrapper() cache needs synchronization, to have the same size.
+        // Also existing wrappers which point directly at elements in the existing SVGLengthList have to be detached (so a copy
+        // of them is created, so existing animVal variables in JS are kept-alive). If we'd detach them later the underlying
+        // SVGLengthList was already mutated, and our list item wrapper tear offs would point nowhere. Assertions would fire.
+        animVal()->detachListWrappers(animVal()->values().size());
+
+        ASSERT(animVal()->values().size() == animVal()->wrappers().size());
+        ASSERT(animVal()->wrappers().size() == m_animatedWrappers.size());
+    }
+
+    virtual void animationValueWillChange()
+    {
+        ASSERT(m_isAnimating);
+        ASSERT(m_animVal);
+        ASSERT(m_values.size() == m_wrappers.size());
+        synchronizeWrappersIfNeeded();
+    }
+
+    virtual void animationValueDidChange()
+    {
+        ASSERT(m_isAnimating);
+        ASSERT(m_animVal);
+        ASSERT(m_values.size() == m_wrappers.size());
+        synchronizeWrappersIfNeeded();
+
+        ASSERT(contextElement());
+        contextElement()->svgAttributeChanged(attributeName());
+    }
 
     static PassRefPtr<SVGAnimatedListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& values)
     {
@@ -103,9 +168,8 @@ protected:
 
     PropertyType& m_values;
 
-    // FIXME: The list wrapper cache is shared between baseVal/animVal. If we implement animVal,
-    // we need two seperated wrapper caches if the attribute gets animated.
     ListWrapperCache m_wrappers;
+    ListWrapperCache m_animatedWrappers;
 
     RefPtr<SVGProperty> m_baseVal;
     RefPtr<SVGProperty> m_animVal;
index 25d757b..6ed5e62 100644 (file)
@@ -34,14 +34,14 @@ public:
     SVGProperty* baseVal(SVGPathSegRole role)
     {
         if (!m_baseVal)
-            m_baseVal = SVGPathSegListPropertyTearOff::create(this, BaseValRole, role);
+            m_baseVal = SVGPathSegListPropertyTearOff::create(this, BaseValRole, role, m_values, m_wrappers);
         return m_baseVal.get();
     }
 
     SVGProperty* animVal(SVGPathSegRole role)
     {
         if (!m_animVal)
-            m_animVal = SVGPathSegListPropertyTearOff::create(this, AnimValRole, role);
+            m_animVal = SVGPathSegListPropertyTearOff::create(this, AnimValRole, role, m_values, m_wrappers);
         return m_animVal.get();
     }
 
index e6db1b9..d14b615 100644 (file)
@@ -37,6 +37,7 @@ public:
     SVGElement* contextElement() const { return m_contextElement.get(); }
     const QualifiedName& attributeName() const { return m_attributeName; }
     AnimatedPropertyType animatedPropertyType() const { return m_animatedPropertyType; }
+    bool isAnimating() const { return m_isAnimating; }
 
     void commitChange()
     {
@@ -47,9 +48,11 @@ public:
 
     virtual bool isAnimatedListTearOff() const { return false; }
 
+    // FIXME: Make these pure once SVGAnimatedStaticPropertyTearOff supports animVal as well.
     virtual void animationStarted(SVGAnimatedType*) { ASSERT_NOT_REACHED(); }
     virtual void animationEnded() { ASSERT_NOT_REACHED(); }
-    virtual void animationValueChanged() { ASSERT_NOT_REACHED(); }
+    virtual void animationValueWillChange() { ASSERT_NOT_REACHED(); }
+    virtual void animationValueDidChange() { ASSERT_NOT_REACHED(); }
     virtual SVGGenericAnimatedType* currentBaseValue(AnimatedPropertyType) const
     {
         ASSERT_NOT_REACHED();
@@ -70,6 +73,9 @@ public:
                 break;
             }
         }
+
+        // Assure that animationEnded() was called, if animationStarted() was called before.
+        ASSERT(!m_isAnimating);
     }
 
     // lookupOrCreateWrapper & helper methods.
@@ -139,6 +145,7 @@ protected:
         : m_contextElement(contextElement)
         , m_attributeName(attributeName)
         , m_animatedPropertyType(animatedPropertyType)
+        , m_isAnimating(false)
     {
     }
 
@@ -152,6 +159,9 @@ private:
     RefPtr<SVGElement> m_contextElement;
     const QualifiedName& m_attributeName;
     AnimatedPropertyType m_animatedPropertyType;
+
+protected:
+    bool m_isAnimating;
 };
 
 }
index 38d6654..0cf7890 100644 (file)
@@ -30,17 +30,19 @@ namespace WebCore {
 template<typename PropertyType>
 class SVGAnimatedPropertyTearOff : public SVGAnimatedProperty {
 public:
-    SVGProperty* baseVal()
+    typedef SVGPropertyTearOff<PropertyType> PropertyTearOff;
+
+    PropertyTearOff* baseVal()
     {
         if (!m_baseVal)
-            m_baseVal = SVGPropertyTearOff<PropertyType>::create(this, BaseValRole, m_property);
+            m_baseVal = PropertyTearOff::create(this, BaseValRole, m_property);
         return m_baseVal.get();
     }
 
-    SVGProperty* animVal()
+    PropertyTearOff* animVal()
     {
         if (!m_animVal)
-            m_animVal = SVGPropertyTearOff<PropertyType>::create(this, AnimValRole, m_property);
+            m_animVal = PropertyTearOff::create(this, AnimValRole, m_property);
         return m_animVal.get();
     }
 
@@ -50,13 +52,11 @@ public:
         return adoptRef(new SVGAnimatedPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, property));
     }
 
-    bool isAnimating() const { return m_isAnimating; }
-
     PropertyType& currentAnimatedValue()
     {
-        ASSERT(m_animVal);
         ASSERT(m_isAnimating);
-        return static_cast<SVGPropertyTearOff<PropertyType>*>(m_animVal.get())->propertyReference();
+        ASSERT(m_animVal);
+        return m_animVal->propertyReference();
     }
 
     virtual SVGGenericAnimatedType* currentBaseValue(AnimatedPropertyType expectedPropertyType) const
@@ -67,16 +67,18 @@ public:
 
     virtual void animationStarted(SVGAnimatedType* animatedType)
     {
+        ASSERT(!m_isAnimating);
         ASSERT(animatedType);
         ASSERT(animatedType->type() == animatedPropertyType());
-        static_cast<SVGPropertyTearOff<PropertyType>*>(animVal())->setValue(*reinterpret_cast<PropertyType*>(animatedType->variantValue()));
+        animVal()->setValue(*reinterpret_cast<PropertyType*>(animatedType->variantValue()));
         m_isAnimating = true;
     }
 
     virtual void animationEnded()
     {
         ASSERT(m_isAnimating);
-        static_cast<SVGPropertyTearOff<PropertyType>*>(animVal())->setValue(m_property);
+        ASSERT(m_animVal);
+        m_animVal->setValue(m_property);
         m_isAnimating = false;
 
         SVGElement* element = contextElement();
@@ -86,8 +88,18 @@ public:
         element->svgAttributeChanged(attributeName());
     }
 
-    virtual void animationValueChanged()
+    virtual void animationValueWillChange()
+    {
+        // no-op for non list types.
+        ASSERT(m_isAnimating);
+        ASSERT(m_animVal);
+    }
+
+    virtual void animationValueDidChange()
     {
+        ASSERT(m_isAnimating);
+        ASSERT(m_animVal);
+
         ASSERT(contextElement());
         contextElement()->svgAttributeChanged(attributeName());
     }
@@ -96,21 +108,12 @@ private:
     SVGAnimatedPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property)
         : SVGAnimatedProperty(contextElement, attributeName, animatedPropertyType)
         , m_property(property)
-        , m_isAnimating(false)
     {
     }
 
-#ifndef NDEBUG
-    virtual ~SVGAnimatedPropertyTearOff()
-    {
-        ASSERT(!m_isAnimating);
-    }
-#endif
-
     PropertyType& m_property;
-    bool m_isAnimating;
-    RefPtr<SVGProperty> m_baseVal;
-    RefPtr<SVGProperty> m_animVal;
+    RefPtr<PropertyTearOff> m_baseVal;
+    RefPtr<PropertyTearOff> m_animVal;
 };
 
 }
index 1a3e700..3db3ede 100644 (file)
@@ -32,14 +32,14 @@ public:
     SVGProperty* baseVal()
     {
         if (!m_baseVal)
-            m_baseVal = SVGTransformListPropertyTearOff::create(this, BaseValRole);
+            m_baseVal = SVGTransformListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers);
         return m_baseVal.get();
     }
 
     SVGProperty* animVal()
     {
         if (!m_animVal)
-            m_animVal = SVGTransformListPropertyTearOff::create(this, AnimValRole);
+            m_animVal = SVGTransformListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers);
         return m_animVal.get();
     }
 
index 0985ddb..58e0dfe 100644 (file)
@@ -52,41 +52,64 @@ public:
         return true;
     }
 
+    void detachListWrappers(unsigned newListSize)
+    {
+        // See SVGPropertyTearOff::detachWrapper() for an explaination what's happening here.
+        ASSERT(m_wrappers);
+        unsigned size = m_wrappers->size();
+        for (unsigned i = 0; i < size; ++i) {
+            if (ListItemTearOff* item = m_wrappers->at(i).get())
+                item->detachWrapper();
+        }
+
+        // Reinitialize the wrapper cache to be equal to the new values size, after the XML DOM changed the list.
+        if (newListSize)
+            m_wrappers->fill(0, newListSize);
+        else
+            m_wrappers->clear();
+    }
+
+    void setValuesAndWrappers(PropertyType* values, ListWrapperCache* wrappers)
+    {
+        // This is only used for animVal support, to switch the underlying values & wrappers
+        // to the current animated values, once animation for a list starts.
+        ASSERT(m_values);
+        ASSERT(m_wrappers);
+        ASSERT(m_role == AnimValRole);
+
+        m_values = values;
+        m_wrappers = wrappers;
+        ASSERT(m_values->size() == m_wrappers->size());
+    }
+
     // SVGList::clear()
-    void clearValues(PropertyType& values, ExceptionCode& ec)
+    void clearValues(ExceptionCode& ec)
     {
         if (!canAlterList(ec))
             return;
 
-        values.clear();
+        m_values->clear();
         commitChange();
     }
 
-    void clearValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, ExceptionCode& ec)
+    void clearValuesAndWrappers(ExceptionCode& ec)
     {
-        ASSERT(animatedList);
         if (!canAlterList(ec))
             return;
 
-        animatedList->detachListWrappers(0);
-        animatedList->values().clear();
+        detachListWrappers(0);
+        m_values->clear();
         commitChange();
     }
 
     // SVGList::numberOfItems()
-    unsigned numberOfItemsValues(PropertyType& values) const
-    {
-        return values.size();
-    }
-
-    unsigned numberOfItemsValuesAndWrappers(AnimatedListPropertyTearOff* animatedList) const
+    unsigned numberOfItems() const
     {
-        ASSERT(animatedList);
-        return animatedList->values().size();
+        return m_values->size();
     }
 
     // SVGList::initialize()
-    ListItemType initializeValues(PropertyType& values, const ListItemType& newItem, ExceptionCode& ec)
+    ListItemType initializeValues(const ListItemType& newItem, ExceptionCode& ec)
     {
         if (!canAlterList(ec))
             return ListItemType();
@@ -95,16 +118,16 @@ public:
         processIncomingListItemValue(newItem, 0);
 
         // Spec: Clears all existing current items from the list and re-initializes the list to hold the single item specified by the parameter.
-        values.clear();
-        values.append(newItem);
+        m_values->clear();
+        m_values->append(newItem);
 
         commitChange();
         return newItem;
     }
 
-    PassListItemTearOff initializeValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, ExceptionCode& ec)
+    PassListItemTearOff initializeValuesAndWrappers(PassListItemTearOff passNewItem, ExceptionCode& ec)
     {
-        ASSERT(animatedList);
+        ASSERT(m_wrappers);
         if (!canAlterList(ec))
             return 0;
 
@@ -114,30 +137,27 @@ public:
             return 0;
         }
 
-        PropertyType& values = animatedList->values();
-        ListWrapperCache& wrappers = animatedList->wrappers();
-
         RefPtr<ListItemTearOff> newItem = passNewItem;
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
 
         // Spec: If the inserted item is already in a list, it is removed from its previous list before it is inserted into this list.
         processIncomingListItemWrapper(newItem, 0);
 
         // Spec: Clears all existing current items from the list and re-initializes the list to hold the single item specified by the parameter.
-        animatedList->detachListWrappers(0);
-        values.clear();
+        detachListWrappers(0);
+        m_values->clear();
 
-        values.append(newItem->propertyReference());
-        wrappers.append(newItem);
+        m_values->append(newItem->propertyReference());
+        m_wrappers->append(newItem);
 
         commitChange();
         return newItem.release();
     }
 
     // SVGList::getItem()
-    bool canGetItem(PropertyType& values, unsigned index, ExceptionCode& ec)
+    bool canGetItem(unsigned index, ExceptionCode& ec)
     {
-        if (index >= values.size()) {
+        if (index >= m_values->size()) {
             ec = INDEX_SIZE_ERR;
             return false;
         }
@@ -145,63 +165,60 @@ public:
         return true;
     }
 
-    ListItemType getItemValues(PropertyType& values, unsigned index, ExceptionCode& ec)
+    ListItemType getItemValues(unsigned index, ExceptionCode& ec)
     {
-        if (!canGetItem(values, index, ec)) 
+        if (!canGetItem(index, ec))
             return ListItemType();
 
         // Spec: Returns the specified item from the list. The returned item is the item itself and not a copy.
-        return values.at(index);
+        return m_values->at(index);
     }
 
     PassListItemTearOff getItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, unsigned index, ExceptionCode& ec)
     {
-        ASSERT(animatedList);
-        PropertyType& values = animatedList->values();
-        if (!canGetItem(values, index, ec))
+        ASSERT(m_wrappers);
+        if (!canGetItem(index, ec))
             return 0;
 
-        ListWrapperCache& wrappers = animatedList->wrappers();
-
         // Spec: Returns the specified item from the list. The returned item is the item itself and not a copy.
         // Any changes made to the item are immediately reflected in the list.
-        ASSERT(values.size() == wrappers.size());
-        RefPtr<ListItemTearOff> wrapper = wrappers.at(index);
+        ASSERT(m_values->size() == m_wrappers->size());
+        RefPtr<ListItemTearOff> wrapper = m_wrappers->at(index);
         if (!wrapper) {
             // Create new wrapper, which is allowed to directly modify the item in the list, w/o copying and cache the wrapper in our map.
             // It is also associated with our animated property, so it can notify the SVG Element which holds the SVGAnimated*List
             // that it has been modified (and thus can call svgAttributeChanged(associatedAttributeName)).
-            wrapper = ListItemTearOff::create(animatedList, UndefinedRole, values.at(index));
-            wrappers.at(index) = wrapper;
+            wrapper = ListItemTearOff::create(animatedList, UndefinedRole, m_values->at(index));
+            m_wrappers->at(index) = wrapper;
         }
 
         return wrapper.release();
     }
 
     // SVGList::insertItemBefore()
-    ListItemType insertItemBeforeValues(PropertyType& values, const ListItemType& newItem, unsigned index, ExceptionCode& ec)
+    ListItemType insertItemBeforeValues(const ListItemType& newItem, unsigned index, ExceptionCode& ec)
     {
         if (!canAlterList(ec))
             return ListItemType();
 
         // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
-        if (index > values.size())
-            index = values.size();
+        if (index > m_values->size())
+            index = m_values->size();
 
         // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
         processIncomingListItemValue(newItem, &index);
 
         // Spec: Inserts a new item into the list at the specified position. The index of the item before which the new item is to be
         // inserted. The first item is number 0. If the index is equal to 0, then the new item is inserted at the front of the list.
-        values.insert(index, newItem);
+        m_values->insert(index, newItem);
 
         commitChange();
         return newItem;
     }
 
-    PassListItemTearOff insertItemBeforeValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+    PassListItemTearOff insertItemBeforeValuesAndWrappers(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
     {
-        ASSERT(animatedList);
+        ASSERT(m_wrappers);
         if (!canAlterList(ec))
             return 0;
 
@@ -211,37 +228,34 @@ public:
             return 0;
         }
 
-        PropertyType& values = animatedList->values();
-        ListWrapperCache& wrappers = animatedList->wrappers();
-
         // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
-        if (index > values.size())
-             index = values.size();
+        if (index > m_values->size())
+             index = m_values->size();
 
         RefPtr<ListItemTearOff> newItem = passNewItem;
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
 
         // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
         processIncomingListItemWrapper(newItem, &index);
 
         // Spec: Inserts a new item into the list at the specified position. The index of the item before which the new item is to be
         // inserted. The first item is number 0. If the index is equal to 0, then the new item is inserted at the front of the list.
-        values.insert(index, newItem->propertyReference());
+        m_values->insert(index, newItem->propertyReference());
 
         // Store new wrapper at position 'index', change its underlying value, so mutations of newItem, directly affect the item in the list.
-        wrappers.insert(index, newItem);
+        m_wrappers->insert(index, newItem);
 
         commitChange();
         return newItem.release();
     }
 
     // SVGList::replaceItem()
-    bool canReplaceItem(PropertyType& values, unsigned index, ExceptionCode& ec)
+    bool canReplaceItem(unsigned index, ExceptionCode& ec)
     {
         if (!canAlterList(ec))
             return false;
 
-        if (index >= values.size()) {
+        if (index >= m_values->size()) {
             ec = INDEX_SIZE_ERR;
             return false;
         }
@@ -249,33 +263,32 @@ public:
         return true;
     }
 
-    ListItemType replaceItemValues(PropertyType& values, const ListItemType& newItem, unsigned index, ExceptionCode& ec)
+    ListItemType replaceItemValues(const ListItemType& newItem, unsigned index, ExceptionCode& ec)
     {
-        if (!canReplaceItem(values, index, ec))
+        if (!canReplaceItem(index, ec))
             return ListItemType();
 
         // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
         // Spec: If the item is already in this list, note that the index of the item to replace is before the removal of the item.
         processIncomingListItemValue(newItem, &index);
 
-        if (values.isEmpty()) {
+        if (m_values->isEmpty()) {
             // 'newItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace.
             ec = INDEX_SIZE_ERR;
             return ListItemType();
         }
 
         // Update the value at the desired position 'index'. 
-        values.at(index) = newItem;
+        m_values->at(index) = newItem;
 
         commitChange();
         return newItem;
     }
 
-    PassListItemTearOff replaceItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+    PassListItemTearOff replaceItemValuesAndWrappers(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
     {
-        ASSERT(animatedList);
-        PropertyType& values = animatedList->values();
-        if (!canReplaceItem(values, index, ec))
+        ASSERT(m_wrappers);
+        if (!canReplaceItem(index, ec))
             return 0;
 
         // Not specified, but FF/Opera do it this way, and it's just sane.
@@ -284,41 +297,40 @@ public:
             return 0;
         }
 
-        ListWrapperCache& wrappers = animatedList->wrappers();
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
         RefPtr<ListItemTearOff> newItem = passNewItem;
 
         // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
         // Spec: If the item is already in this list, note that the index of the item to replace is before the removal of the item.
         processIncomingListItemWrapper(newItem, &index);
 
-        if (values.isEmpty()) {
-            ASSERT(wrappers.isEmpty());
+        if (m_values->isEmpty()) {
+            ASSERT(m_wrappers->isEmpty());
             // 'passNewItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace.
             ec = INDEX_SIZE_ERR;
             return 0;
         }
 
         // Detach the existing wrapper.
-        RefPtr<ListItemTearOff> oldItem = wrappers.at(index);
+        RefPtr<ListItemTearOff> oldItem = m_wrappers->at(index);
         if (oldItem)
             oldItem->detachWrapper();
 
         // Update the value and the wrapper at the desired position 'index'. 
-        values.at(index) = newItem->propertyReference();
-        wrappers.at(index) = newItem;
+        m_values->at(index) = newItem->propertyReference();
+        m_wrappers->at(index) = newItem;
 
         commitChange();
         return newItem.release();
     }
 
     // SVGList::removeItem()
-    bool canRemoveItem(PropertyType& values, unsigned index, ExceptionCode& ec)
+    bool canRemoveItem(unsigned index, ExceptionCode& ec)
     {
         if (!canAlterList(ec))
             return false;
 
-        if (index >= values.size()) {
+        if (index >= m_values->size()) {
             ec = INDEX_SIZE_ERR;
             return false;
         }
@@ -326,13 +338,13 @@ public:
         return true;
     }
 
-    ListItemType removeItemValues(PropertyType& values, unsigned index, ExceptionCode& ec)
+    ListItemType removeItemValues(unsigned index, ExceptionCode& ec)
     {
-        if (!canRemoveItem(values, index, ec))
+        if (!canRemoveItem(index, ec))
             return ListItemType();
 
-        ListItemType oldItem = values.at(index);
-        values.remove(index);
+        ListItemType oldItem = m_values->at(index);
+        m_values->remove(index);
 
         commitChange();
         return oldItem;
@@ -340,29 +352,27 @@ public:
 
     PassListItemTearOff removeItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, unsigned index, ExceptionCode& ec)
     {
-        ASSERT(animatedList);
-        PropertyType& values = animatedList->values();
-        if (!canRemoveItem(values, index, ec))
+        ASSERT(m_wrappers);
+        if (!canRemoveItem(index, ec))
             return 0;
 
-        ListWrapperCache& wrappers = animatedList->wrappers();
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
 
         // Detach the existing wrapper.
-        RefPtr<ListItemTearOff> oldItem = wrappers.at(index);
+        RefPtr<ListItemTearOff> oldItem = m_wrappers->at(index);
         if (!oldItem)
-            oldItem = ListItemTearOff::create(animatedList, UndefinedRole, values.at(index));
+            oldItem = ListItemTearOff::create(animatedList, UndefinedRole, m_values->at(index));
 
         oldItem->detachWrapper();
-        wrappers.remove(index);
-        values.remove(index);
+        m_wrappers->remove(index);
+        m_values->remove(index);
 
         commitChange();
         return oldItem.release();
     }
 
     // SVGList::appendItem()
-    ListItemType appendItemValues(PropertyType& values, const ListItemType& newItem, ExceptionCode& ec)
+    ListItemType appendItemValues(const ListItemType& newItem, ExceptionCode& ec)
     {
         if (!canAlterList(ec))
             return ListItemType();
@@ -371,15 +381,15 @@ public:
         processIncomingListItemValue(newItem, 0);
 
         // Append the value at the end of the list.
-        values.append(newItem);
+        m_values->append(newItem);
 
         commitChange();
         return newItem;
     }
 
-    PassListItemTearOff appendItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, ExceptionCode& ec)
+    PassListItemTearOff appendItemValuesAndWrappers(PassListItemTearOff passNewItem, ExceptionCode& ec)
     {
-        ASSERT(animatedList);
+        ASSERT(m_wrappers);
         if (!canAlterList(ec))
             return 0;
 
@@ -389,18 +399,15 @@ public:
             return 0;
         }
 
-        PropertyType& values = animatedList->values();
-        ListWrapperCache& wrappers = animatedList->wrappers();
-
         RefPtr<ListItemTearOff> newItem = passNewItem;
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
 
         // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
         processIncomingListItemWrapper(newItem, 0);
 
         // Append the value and wrapper at the end of the list.
-        values.append(newItem->propertyReference());
-        wrappers.append(newItem);
+        m_values->append(newItem->propertyReference());
+        m_wrappers->append(newItem);
 
         commitChange();
         return newItem.release();
@@ -408,9 +415,23 @@ public:
 
     virtual SVGPropertyRole role() const { return m_role; }
 
+    PropertyType& values()
+    {
+        ASSERT(m_values);
+        return *m_values;
+    }
+
+    ListWrapperCache& wrappers() const
+    {
+        ASSERT(m_wrappers);
+        return *m_wrappers;
+    }
+
 protected:
-    SVGListProperty(SVGPropertyRole role)
+    SVGListProperty(SVGPropertyRole role, PropertyType& values, ListWrapperCache* wrappers)
         : m_role(role)
+        , m_values(&values)
+        , m_wrappers(wrappers)
     {
     }
 
@@ -418,8 +439,9 @@ protected:
     virtual void processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify) = 0;
     virtual void processIncomingListItemWrapper(RefPtr<ListItemTearOff>& newItem, unsigned* indexToModify) = 0;
 
-private:
     SVGPropertyRole m_role;
+    PropertyType* m_values;
+    ListWrapperCache* m_wrappers;
 };
 
 }
index 5a71735..415df82 100644 (file)
@@ -29,6 +29,7 @@ template<typename PropertyType>
 class SVGListPropertyTearOff : public SVGListProperty<PropertyType> {
 public:
     typedef SVGListProperty<PropertyType> Base;
+    typedef SVGListPropertyTearOff<PropertyType> Self;
 
     typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
     typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
@@ -36,28 +37,31 @@ public:
     typedef SVGAnimatedListPropertyTearOff<PropertyType> AnimatedListPropertyTearOff;
     typedef typename SVGAnimatedListPropertyTearOff<PropertyType>::ListWrapperCache ListWrapperCache;
 
-    static PassRefPtr<SVGListPropertyTearOff<PropertyType> > create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
+    using Base::m_values;
+    using Base::m_wrappers;
+
+    static PassRefPtr<Self> create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, PropertyType& values, ListWrapperCache& wrappers)
     {
         ASSERT(animatedProperty);
-        return adoptRef(new SVGListPropertyTearOff<PropertyType>(animatedProperty, role));
+        return adoptRef(new Self(animatedProperty, role, values, wrappers));
     }
 
     int removeItemFromList(ListItemTearOff* removeItem, bool shouldSynchronizeWrappers)
     {
-        PropertyType& values = m_animatedProperty->values();
-        ListWrapperCache& wrappers = m_animatedProperty->wrappers();
+        ASSERT(m_values);
+        ASSERT(m_wrappers);
 
         // Lookup item in cache and remove its corresponding wrapper.
-        unsigned size = wrappers.size();
-        ASSERT(size == values.size());
+        unsigned size = m_wrappers->size();
+        ASSERT(size == m_values->size());
         for (unsigned i = 0; i < size; ++i) {
-            RefPtr<ListItemTearOff>& item = wrappers.at(i);
+            RefPtr<ListItemTearOff>& item = m_wrappers->at(i);
             if (item != removeItem)
                 continue;
 
             item->detachWrapper();
-            wrappers.remove(i);
-            values.remove(i);
+            m_wrappers->remove(i);
+            m_values->remove(i);
 
             if (shouldSynchronizeWrappers)
                 commitChange();
@@ -71,17 +75,12 @@ public:
     // SVGList API
     void clear(ExceptionCode& ec)
     {
-        Base::clearValuesAndWrappers(m_animatedProperty.get(), ec);
-    }
-
-    unsigned numberOfItems() const
-    {
-        return Base::numberOfItemsValuesAndWrappers(m_animatedProperty.get());
+        Base::clearValuesAndWrappers(ec);
     }
 
     PassListItemTearOff initialize(PassListItemTearOff passNewItem, ExceptionCode& ec)
     {
-        return Base::initializeValuesAndWrappers(m_animatedProperty.get(), passNewItem, ec);
+        return Base::initializeValuesAndWrappers(passNewItem, ec);
     }
 
     PassListItemTearOff getItem(unsigned index, ExceptionCode& ec)
@@ -91,12 +90,12 @@ public:
 
     PassListItemTearOff insertItemBefore(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
     {
-        return Base::insertItemBeforeValuesAndWrappers(m_animatedProperty.get(), passNewItem, index, ec);
+        return Base::insertItemBeforeValuesAndWrappers(passNewItem, index, ec);
     }
 
     PassListItemTearOff replaceItem(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
     {
-        return Base::replaceItemValuesAndWrappers(m_animatedProperty.get(), passNewItem, index, ec);
+        return Base::replaceItemValuesAndWrappers(passNewItem, index, ec);
     }
 
     PassListItemTearOff removeItem(unsigned index, ExceptionCode& ec)
@@ -106,30 +105,30 @@ public:
 
     PassListItemTearOff appendItem(PassListItemTearOff passNewItem, ExceptionCode& ec)
     {
-        return Base::appendItemValuesAndWrappers(m_animatedProperty.get(), passNewItem, ec);
+        return Base::appendItemValuesAndWrappers(passNewItem, ec);
     }
 
 protected:
-    SVGListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
-        : SVGListProperty<PropertyType>(role)
+    SVGListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, PropertyType& values, ListWrapperCache& wrappers)
+        : SVGListProperty<PropertyType>(role, values, &wrappers)
         , m_animatedProperty(animatedProperty)
     {
     }
 
     virtual void commitChange()
     {
-        PropertyType& values = m_animatedProperty->values();
-        ListWrapperCache& wrappers = m_animatedProperty->wrappers();
+        ASSERT(m_values);
+        ASSERT(m_wrappers);
 
         // Update existing wrappers, as the index in the values list has changed.
-        unsigned size = wrappers.size();
-        ASSERT(size == values.size());
+        unsigned size = m_wrappers->size();
+        ASSERT(size == m_values->size());
         for (unsigned i = 0; i < size; ++i) {
-            RefPtr<ListItemTearOff>& item = wrappers.at(i);
+            ListItemTearOff* item = m_wrappers->at(i).get();
             if (!item)
                 continue;
             item->setAnimatedProperty(m_animatedProperty.get());
-            item->setValue(values.at(i));
+            item->setValue(m_values->at(i));
         }
 
         m_animatedProperty->commitChange();
index a4eaf73..2021301 100644 (file)
@@ -31,23 +31,22 @@ namespace WebCore {
 
 void SVGPathSegListPropertyTearOff::clear(ExceptionCode& ec)
 {
-    SVGPathSegList& values = m_animatedProperty->values();
-    if (values.isEmpty())
+    ASSERT(m_values);
+    if (m_values->isEmpty())
         return;
 
-    unsigned size = values.size();
+    unsigned size = m_values->size();
     for (unsigned i = 0; i < size; ++i) {
-        ListItemType item = values.at(i);
+        ListItemType item = m_values->at(i);
         static_cast<SVGPathSegWithContext*>(item.get())->setContextAndRole(0, PathSegUndefinedRole);
     }
 
-    SVGPathSegListPropertyTearOff::Base::clearValues(values, ec);
+    SVGPathSegListPropertyTearOff::Base::clearValues(ec);
 }
 
 SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::getItem(unsigned index, ExceptionCode& ec)
 {
-    SVGPathSegList& values = m_animatedProperty->values();
-    ListItemType returnedItem = Base::getItemValues(values, index, ec);
+    ListItemType returnedItem = Base::getItemValues(index, ec);
     if (returnedItem) {
         ASSERT(static_cast<SVGPathSegWithContext*>(returnedItem.get())->contextElement() == contextElement());
         ASSERT(static_cast<SVGPathSegWithContext*>(returnedItem.get())->role() == m_pathSegRole);
@@ -57,8 +56,7 @@ SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::g
 
 SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::removeItem(unsigned index, ExceptionCode& ec)
 {
-    SVGPathSegList& values = m_animatedProperty->values();
-    SVGPathSegListPropertyTearOff::ListItemType removedItem = SVGPathSegListPropertyTearOff::Base::removeItemValues(values, index, ec);
+    SVGPathSegListPropertyTearOff::ListItemType removedItem = SVGPathSegListPropertyTearOff::Base::removeItemValues(index, ec);
     if (removedItem)
         static_cast<SVGPathSegWithContext*>(removedItem.get())->setContextAndRole(0, PathSegUndefinedRole);
     return removedItem.release();
index 94acda1..3fccebf 100644 (file)
@@ -35,23 +35,22 @@ public:
     typedef SVGPropertyTraits<SVGPathSegList>::ListItemType ListItemType;
     typedef PassRefPtr<SVGPathSeg> PassListItemType;
 
-    static PassRefPtr<SVGPathSegListPropertyTearOff> create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole)
+    static PassRefPtr<SVGPathSegListPropertyTearOff> create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole, SVGPathSegList& values, ListWrapperCache& wrappers)
     {
         ASSERT(animatedProperty);
-        return adoptRef(new SVGPathSegListPropertyTearOff(animatedProperty, role, pathSegRole));
+        return adoptRef(new SVGPathSegListPropertyTearOff(animatedProperty, role, pathSegRole, values, wrappers));
     }
 
     int removeItemFromList(const ListItemType& removeItem, bool shouldSynchronizeWrappers)
     {
-        SVGPathSegList& values = m_animatedProperty->values();
-
-        unsigned size = values.size();
+        ASSERT(m_values);
+        unsigned size = m_values->size();
         for (unsigned i = 0; i < size; ++i) {
-            ListItemType& item = values.at(i);
+            ListItemType& item = m_values->at(i);
             if (item != removeItem)
                 continue;
 
-            values.remove(i);
+            m_values->remove(i);
 
             if (shouldSynchronizeWrappers)
                 commitChange();
@@ -65,12 +64,6 @@ public:
     // SVGList API
     void clear(ExceptionCode&);
 
-    unsigned numberOfItems() const
-    {
-        SVGPathSegList& values = m_animatedProperty->values();
-        return Base::numberOfItemsValues(values);
-    }
-
     PassListItemType initialize(PassListItemType passNewItem, ExceptionCode& ec)
     {
         // Not specified, but FF/Opera do it this way, and it's just sane.
@@ -80,8 +73,7 @@ public:
         }
 
         ListItemType newItem = passNewItem;
-        SVGPathSegList& values = m_animatedProperty->values();
-        return Base::initializeValues(values, newItem, ec);
+        return Base::initializeValues(newItem, ec);
     }
 
     PassListItemType getItem(unsigned index, ExceptionCode&);
@@ -95,8 +87,7 @@ public:
         }
 
         ListItemType newItem = passNewItem;
-        SVGPathSegList& values = m_animatedProperty->values();
-        return Base::insertItemBeforeValues(values, newItem, index, ec);
+        return Base::insertItemBeforeValues(newItem, index, ec);
     }
 
     PassListItemType replaceItem(PassListItemType passNewItem, unsigned index, ExceptionCode& ec)
@@ -108,8 +99,7 @@ public:
         }
 
         ListItemType newItem = passNewItem;
-        SVGPathSegList& values = m_animatedProperty->values();
-        return Base::replaceItemValues(values, newItem, index, ec);
+        return Base::replaceItemValues(newItem, index, ec);
     }
 
     PassListItemType removeItem(unsigned index, ExceptionCode&);
@@ -123,13 +113,12 @@ public:
         }
 
         ListItemType newItem = passNewItem;
-        SVGPathSegList& values = m_animatedProperty->values();
-        return Base::appendItemValues(values, newItem, ec);
+        return Base::appendItemValues(newItem, ec);
     }
 
 private:
-    SVGPathSegListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole)
-        : SVGListProperty<SVGPathSegList>(role)
+    SVGPathSegListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole, SVGPathSegList& values, ListWrapperCache& wrappers)
+        : SVGListProperty<SVGPathSegList>(role, values, &wrappers)
         , m_animatedProperty(animatedProperty)
         , m_pathSegRole(pathSegRole)
     {
@@ -139,8 +128,8 @@ private:
 
     virtual void commitChange()
     {
-        SVGPathSegList& values = m_animatedProperty->values();
-        values.commitChange(m_animatedProperty->contextElement());
+        ASSERT(m_values);
+        m_values->commitChange(m_animatedProperty->contextElement());
     }
 
     virtual void processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify);
index a6f0f28..8635378 100644 (file)
@@ -33,6 +33,8 @@ public:
     typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
     typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
 
+    using Base::m_values;
+
     static PassRefPtr<SVGStaticListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, PropertyType& values)
     {
         ASSERT(contextElement);
@@ -42,55 +44,50 @@ public:
     // SVGList API
     void clear(ExceptionCode& ec)
     {
-        Base::clearValues(m_values, ec);
-    }
-
-    unsigned numberOfItems() const
-    {
-        return Base::numberOfItemsValues(m_values);
+        Base::clearValues(ec);
     }
 
     ListItemType initialize(const ListItemType& newItem, ExceptionCode& ec)
     {
-        return Base::initializeValues(m_values, newItem, ec);
+        return Base::initializeValues(newItem, ec);
     }
 
     ListItemType getItem(unsigned index, ExceptionCode& ec)
     {
-        return Base::getItemValues(m_values, index, ec);
+        return Base::getItemValues(index, ec);
     }
 
     ListItemType insertItemBefore(const ListItemType& newItem, unsigned index, ExceptionCode& ec)
     {
-        return Base::insertItemBeforeValues(m_values, newItem, index, ec);
+        return Base::insertItemBeforeValues(newItem, index, ec);
     }
 
     ListItemType replaceItem(const ListItemType& newItem, unsigned index, ExceptionCode& ec)
     {
-        return Base::replaceItemValues(m_values, newItem, index, ec);
+        return Base::replaceItemValues(newItem, index, ec);
     }
 
     ListItemType removeItem(unsigned index, ExceptionCode& ec)
     {
-        return Base::removeItemValues(m_values, index, ec);
+        return Base::removeItemValues(index, ec);
     }
 
     ListItemType appendItem(const ListItemType& newItem, ExceptionCode& ec)
     {
-        return Base::appendItemValues(m_values, newItem, ec);
+        return Base::appendItemValues(newItem, ec);
     }
 
 private:
     SVGStaticListPropertyTearOff(SVGElement* contextElement, PropertyType& values)
-        : SVGListProperty<PropertyType>(UndefinedRole)
+        : SVGListProperty<PropertyType>(UndefinedRole, values, 0)
         , m_contextElement(contextElement)
-        , m_values(values)
     {
     }
 
     virtual void commitChange()
     {
-        m_values.commitChange(m_contextElement.get());
+        ASSERT(m_values);
+        m_values->commitChange(m_contextElement.get());
     }
 
     virtual void processIncomingListItemValue(const ListItemType&, unsigned*)
@@ -105,7 +102,6 @@ private:
 
 private:
     RefPtr<SVGElement> m_contextElement;
-    PropertyType& m_values;
 };
 
 }
index e496c81..7ac124f 100644 (file)
@@ -32,49 +32,48 @@ public:
     typedef SVGAnimatedListPropertyTearOff<SVGTransformList> AnimatedListPropertyTearOff;
     typedef SVGAnimatedListPropertyTearOff<SVGTransformList>::ListWrapperCache ListWrapperCache;
 
-    static PassRefPtr<SVGListPropertyTearOff<SVGTransformList> > create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
+    static PassRefPtr<SVGListPropertyTearOff<SVGTransformList> > create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGTransformList& values, ListWrapperCache& wrappers)
     {
         ASSERT(animatedProperty);
-        return adoptRef(new SVGTransformListPropertyTearOff(animatedProperty, role));
+        return adoptRef(new SVGTransformListPropertyTearOff(animatedProperty, role, values, wrappers));
     }
 
     PassRefPtr<SVGPropertyTearOff<SVGTransform> > createSVGTransformFromMatrix(SVGPropertyTearOff<SVGMatrix>* matrix, ExceptionCode& ec)
     {
+        ASSERT(m_values);
         if (!matrix) {
             ec = TYPE_MISMATCH_ERR;
             return 0;
         }
-        SVGTransformList& values = m_animatedProperty->values();
-        return SVGPropertyTearOff<SVGTransform>::create(values.createSVGTransformFromMatrix(matrix->propertyReference()));
+        return SVGPropertyTearOff<SVGTransform>::create(m_values->createSVGTransformFromMatrix(matrix->propertyReference()));
     }
 
     PassRefPtr<SVGPropertyTearOff<SVGTransform> > consolidate(ExceptionCode& ec)
     {
+        ASSERT(m_values);
+        ASSERT(m_wrappers);
         if (!canAlterList(ec))
             return 0;
 
-        SVGTransformList& values = m_animatedProperty->values();
-        ListWrapperCache& wrappers = m_animatedProperty->wrappers();
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
 
         // Spec: If the list was empty, then a value of null is returned.
-        if (values.isEmpty())
+        if (m_values->isEmpty())
             return 0;
 
-        m_animatedProperty->detachListWrappers(0);
-        RefPtr<SVGPropertyTearOff<SVGTransform> > wrapper = SVGPropertyTearOff<SVGTransform>::create(values.consolidate());
-        wrappers.append(wrapper);
+        detachListWrappers(0);
+        RefPtr<SVGPropertyTearOff<SVGTransform> > wrapper = SVGPropertyTearOff<SVGTransform>::create(m_values->consolidate());
+        m_wrappers->append(wrapper);
 
-        ASSERT(values.size() == wrappers.size());
+        ASSERT(m_values->size() == m_wrappers->size());
         return wrapper.release();
     }
 
 private:
-    SVGTransformListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
-        : SVGListPropertyTearOff<SVGTransformList>(animatedProperty, role)
+    SVGTransformListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGTransformList& values, ListWrapperCache& wrappers)
+        : SVGListPropertyTearOff<SVGTransformList>(animatedProperty, role, values, wrappers)
     {
     }
-
 };
 
 }