2010-10-20 Nikolas Zimmermann <nzimmermann@rim.com>
authorzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Oct 2010 10:25:25 +0000 (10:25 +0000)
committerzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Oct 2010 10:25:25 +0000 (10:25 +0000)
        Reviewed by Dirk Schulze.

        Redesign SVGAnimatedProperty concept to share "POD type wrappers" between all bindings (-> add ObjC SVG bindings)
        https://bugs.webkit.org/show_bug.cgi?id=47905

        Tests: svg/dom/SVGLengthList-appendItem.xhtml
               svg/dom/SVGLengthList-basics.xhtml
               svg/dom/SVGLengthList-getItem.xhtml
               svg/dom/SVGLengthList-initialize.xhtml
               svg/dom/SVGLengthList-insertItemBefore.xhtml
               svg/dom/SVGLengthList-removeItem.xhtml
               svg/dom/SVGLengthList-replaceItem.xhtml
               svg/dom/SVGLengthList-xml-dom-modifications.xhtml

        Introduce a more lightweight, less intrusive way to expose SVGAnimated* DOM bindings.

        Concrete example:
        The SVG DOM defines a 'SVGAnimatedLength' object, that's used to represent the x / y / width / height attributes of a 'SVGRectElement'.
        Each 'SVGAnimatedLength' object exposes a baseVal (markup defined attribute value) and an animVal (reflects the current state during animations),
        both of type 'SVGLength'. These objects are all _live_. That means you can do:
        var foobar = rect.x.baseVal; foobar.value += 150;

        If we'd implement the SVG DOM straightforward, we'd have to store a refcounted SVGAnimatedLength object, containing two refcounted SVGLength objects
        in SVGRectElement, for each of the x/y/width/height attributes. Our solution, to reduce memory footprint and increase performance is to store
        SVGLength stack-allocated, non refcounted types in SVGRectElement for x/y/width/height, and don't implement the SVGAnimatedLength object at all.

        In the past the JS bindings had to expose wrappers for SVGAnimatedLength on their own, and wrap each SVGLength object in an object called JSSVGPODTypeWrapper<SVGLength>.
        When JS changed the 'value' of the 'SVGLength', we constructed a copy of the SVGLength object, modified it, and called rectElement->setXBaseValue(newLength).
        This is not efficient at all, as we have to construct several copies of the SVGLength object, utilize callbacks to propagate the value changes in the SVG DOM.
        Furthermore, all bindings had to expose a similar concept, otherwhise SVG DOM wouldn't work. Up until now, only JSC and V8 bindings were available, that worked properly.

        The new SVGAnimatedProperty concept removes the need for JSSVGPODTypeWrapper (and friends like JSSVGContextCache, that associated a SVGLength with its SVGRectElement).
        Instead a solution is offered, that all bindings can use simultaneously, without adding new types or special concepts like JSSVGPODTypeWrapper.

        It works like this:
        A new refcounted SVGAnimatedProperty<PropertyType> template class is available, that stores a QualifiedName to associate the SVG DOM property with a XML DOM attribute.
        It also stores a RefPtr to the SVGElement that created it.

        In SVGRectElement we still store SVGLength m_x/m_y/m_width/m_height members, and offer a new "xAnimated()" method which looks up or creates a SVGAnimatedProperty<SVGLength>
        object. The JS/V8/ObjC bindings call this method whenever someone requests "rect.x/y/width/height", and a new wrapper is created, and stored in a HashMap.

        The SVGAnimatedProperty<PropertyType> is a base class for SVGAnimatedPropertyTearOff and SVGAnimatedListPropertyTearOff, the latter is used for all types of lists (SVGLengthList).
        SVGAnimatedProperty contains two methods used in the bindings: SVGProperty* baseVal and SVGProperty* animVal. SVGProperty is a base class for SVGPropertyTearOff and
        SVGListPropertyTearOff. Upon invocation of the baseVal/animVal methods a new SVG(List)PropertyTearOff object is created and stored in a RefPtr.
        The SVGPropertyTearOff objects stores a _reference_ to the type it wraps. Concrete example:
        When calling rect.x, a SVGAnimatedPropertyTearOff<SVGLength> is created, that stores a pointer to the SVGRectElement, and a SVGNames::xAttr.
        When calling rect.x.baseVal, a SVGPropertyTearOf<SVGLength> is created, that stores a reference to the "m_x" member variable of the SVGRectElement.
        Any changes applied to the SVGLength object, through the wrapper, are immediately live, as no copies are involved anymore, nor the need to fire any callback methods.
        This is the key concept of the new tear offs, no copies, no callbacks, no virtual methods (except one, needed for lists, but it's a detail).

        The SVGAnimatedListPropertyTearOff and SVGListPropertyTearOff work the same, but for SVG*List objects. The whole SVG*List API is _removed_ from the SVG DOM classes
        like SVGLengthList. It now inherits from Vector<SVGLength>, where it used to store a Vector<RefPtr<SVGListItem<SVGLength> > >. The SVGList API (insertItemBefore, appendItem, etc.)
        is exposed through SVGListPropertyTearOff, and there's no need anymore for SVGLengthList to deal with it at all.
        SVGLengthList is live just like most other SVG DOM object. Concrete example:
        var item0 = text.x.baseVal.getItem(0); item0.value += 150;

        Previously we chose to store a refcounted SVGListItem object, which wrapped the SVGLength object, to achieve liveness. We could change a single list item from DOM
        w/o copying the whole list. The drawback is that a simple type likeSVGLengthList, was heavy to store, as it contained a list of RefPtrs around a wrapper object
        around the real object 'SVGLength'. This complexity is completly gone.

        The SVGListPropertyTearOff<SVGLengthList> stores a reference to the SVGLengthList object (eg. SVGTextElement::m_x) and maintains a list of SVGPropertyTearOff<SVGLength>
        wrappers, that are created when necessary (getItem(2), will create a wrapper around the third list item), and cached. These SVGPropertyTearOff<SVGLength> objects
        store references to the SVGLength object _in the SVGLengthList_. One has to be extra carefully, to keep those lists synchronized.
        The SVGLengthList API is fully implemented for the first time, including moving items between lists, and is extensively tested with 8 new testcases.

        This patch only changed SVGLength/SVGLengthList to the new concept. All other types remain using the old DeprecatedSVGAnimatedProperty* concept.
        This will change in follow-up patches.

        * GNUmakefile.am: Add new files from svg/properties to build.
        * WebCore.gypi: Ditto.
        * WebCore.pro: Ditto.
        * WebCore.vcproj/WebCore.vcproj: Ditto.
        * WebCore.xcodeproj/project.pbxproj: Ditto.
        * bindings/js/JSSVGLengthCustom.cpp: Adapt to context cache removal for SVGLength.
        (WebCore::JSSVGLength::value):
        (WebCore::JSSVGLength::convertToSpecifiedUnits):
        * bindings/scripts/CodeGenerator.pm: Add new isSVGNewStyleAnimatedProperty() helper method, return true for "SVGAnimatedLength" and "SVGAnimatedLengthList".
        * bindings/scripts/CodeGeneratorJS.pm: Generate new style SVG JS bindings, that don't need JSSVGContextCache / JSSVGPODTypeWrapper.
        * bindings/scripts/CodeGeneratorObjC.pm: Ditto. (+ Finally expose a working set of SVG DOM API for Objective C).
        * bindings/scripts/CodeGeneratorV8.pm: Ditto.
        * bindings/v8/custom/V8SVGLengthCustom.cpp: Adapt to context cache removal for SVGLength.
        (WebCore::V8SVGLength::valueAccessorGetter):
        (WebCore::V8SVGLength::convertToSpecifiedUnitsCallback):
        * rendering/svg/SVGTextLayoutAttributesBuilder.cpp:
        (WebCore::extractFloatValuesFromSVGLengthList): SVGLengthList is a POD type now, passed as const reference.
        * svg/DeprecatedSVGAnimatedPropertyTraits.h: Remove handling for SVGLength/SVGLengthList, those are converted to the new SVGAnimatedProperty design now.
        * svg/DeprecatedSVGAnimatedTemplate.h: Ditto.
        * svg/SVGAnimatedLength.h: Added.
        * svg/SVGAnimatedLength.idl: Mark as [SVGAnimatedProperty].
        * svg/SVGAnimatedLengthList.h: Added.
        * svg/SVGAnimatedLengthList.idl: Mark as [SVGAnimatedProperty].
        * svg/SVGCircleElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_PROPERTY_NEW/ until the transition to the new concept is finished.
        * svg/SVGCursorElement.h: Ditto.
        * svg/SVGEllipseElement.h: Ditto.
        * svg/SVGFilterElement.h: Ditto.
        * svg/SVGFilterPrimitiveStandardAttributes.h: Ditto.
        * svg/SVGForeignObjectElement.h: Ditto.
        * svg/SVGImageElement.h: Ditto.
        * svg/SVGLength.idl: Mark as [SVGProperty].
        * svg/SVGLengthList.cpp: Use Vector API (appendItem -> append). No need to ever use the SVGList API internally. SVGLengthList is a Vector<SVGLength> now.
        (WebCore::SVGLengthList::parse):
        (WebCore::SVGLengthList::valueAsString):
        * svg/SVGLengthList.h: Inherit from Vector<SVGLength> - not from the SVGList base class. It's a simple, non-refcounted POD type now.
        (WebCore::SVGLengthList::SVGLengthList):
        * svg/SVGLengthList.idl: Mark as [SVGListProperty].
        * svg/SVGLineElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_PROPERTY_NEW/ until the transition to the new concept is finished.
        * svg/SVGLinearGradientElement.h: Ditto.
        * svg/SVGMarkerElement.h: Ditto.
        * svg/SVGMaskElement.h: Ditto.
        * svg/SVGPatternElement.h: Ditto.
        * svg/SVGRadialGradientElement.h: Ditto.
        * svg/SVGRectElement.h: Ditto.
        * svg/SVGSVGElement.h: Ditto.
        * svg/SVGSVGElement.idl: Mark createSVGLength() as [SVGLiveProperty] - a wrapper for the returned object has to be created.
        * svg/SVGTextContentElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_PROPERTY_NEW/ until the transition to the new concept is finished.
        * svg/SVGTextPathElement.h: Ditto.
        * svg/SVGTextPositioningElement.cpp:
        (WebCore::SVGTextPositioningElement::SVGTextPositioningElement):
        (WebCore::SVGTextPositioningElement::parseMappedAttribute): Detach wrappers pointing to the old x/y/dx/dy list, if the underlying list changes via XML DOM.
        (WebCore::listContainsRelativeValue): Adapt to SVGLengthList interface changes, it's a POD type now.
        * svg/SVGTextPositioningElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_LIST_PROPERTY_NEW/ until the transition to the new concept is finished.
        * svg/SVGUseElement.h:
        * svg/properties/SVGAnimatedListPropertyTearOff.h: Added.
        * svg/properties/SVGAnimatedProperty.h: Added. This is the base class for SVGAnimatedPropertyTearOff and SVGAnimatedListPropertyTearOff.
        * svg/properties/SVGAnimatedPropertyDescription.h: Added. Refactored from DeprecatedSVGAnimatedProperty.h.
        * svg/properties/SVGAnimatedPropertyMacros.h: Added. These macros will be _removed_ as soon as the transition to the new concept is finished.
        * svg/properties/SVGAnimatedPropertyTearOff.h: Added.
        * svg/properties/SVGListPropertyTearOff.h: Added.
        * svg/properties/SVGProperty.h: Added. This is the base class for SVGPropertyTearOff and SVGListPropertyTearOff.
        * svg/properties/SVGPropertyTearOff.h: Added.
        * svg/properties/SVGPropertyTraits.h: Added.

2010-10-20  Nikolas Zimmermann  <nzimmermann@rim.com>

        Reviewed by Dirk Schulze.

        Redesign SVGAnimatedProperty concept to share "POD type wrappers" between all bindings (-> add ObjC SVG bindings)
        https://bugs.webkit.org/show_bug.cgi?id=47905

        Add extensive set of SVGLengthList tests, that all PASS now.

        * platform/mac-leopard/svg/dom: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.png: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum: Added.
        * platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-appendItem-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-appendItem-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-basics-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-basics-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-getItem-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-getItem-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-initialize-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-initialize-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-removeItem-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-removeItem-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-replaceItem-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-replaceItem-expected.png: Added.
        * platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum: Added.
        * platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.png: Added.
        * svg/dom/SVGLengthList-appendItem-expected.txt: Added.
        * svg/dom/SVGLengthList-appendItem.xhtml: Added.
        * svg/dom/SVGLengthList-basics-expected.txt: Added.
        * svg/dom/SVGLengthList-basics.xhtml: Added.
        * svg/dom/SVGLengthList-getItem-expected.txt: Added.
        * svg/dom/SVGLengthList-getItem.xhtml: Added.
        * svg/dom/SVGLengthList-initialize-expected.txt: Added.
        * svg/dom/SVGLengthList-initialize.xhtml: Added.
        * svg/dom/SVGLengthList-insertItemBefore-expected.txt: Added.
        * svg/dom/SVGLengthList-insertItemBefore.xhtml: Added.
        * svg/dom/SVGLengthList-removeItem-expected.txt: Added.
        * svg/dom/SVGLengthList-removeItem.xhtml: Added.
        * svg/dom/SVGLengthList-replaceItem-expected.txt: Added.
        * svg/dom/SVGLengthList-replaceItem.xhtml: Added.
        * svg/dom/SVGLengthList-xml-dom-modifications-expected.txt: Added.
        * svg/dom/SVGLengthList-xml-dom-modifications.xhtml: Added.

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

102 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.png [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-appendItem-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-appendItem.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-basics-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-basics.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-getItem-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-getItem.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-initialize-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-initialize.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-insertItemBefore-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-insertItemBefore.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-removeItem-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-removeItem.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-replaceItem-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-replaceItem.xhtml [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-xml-dom-modifications-expected.txt [new file with mode: 0644]
LayoutTests/svg/dom/SVGLengthList-xml-dom-modifications.xhtml [new file with mode: 0644]
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSSVGLengthCustom.cpp
WebCore/bindings/scripts/CodeGenerator.pm
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/bindings/scripts/CodeGeneratorObjC.pm
WebCore/bindings/scripts/CodeGeneratorV8.pm
WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp
WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
WebCore/svg/DeprecatedSVGAnimatedPropertyTraits.h
WebCore/svg/DeprecatedSVGAnimatedTemplate.h
WebCore/svg/SVGAnimatedLength.h [new file with mode: 0644]
WebCore/svg/SVGAnimatedLength.idl
WebCore/svg/SVGAnimatedLengthList.h [new file with mode: 0644]
WebCore/svg/SVGAnimatedLengthList.idl
WebCore/svg/SVGCircleElement.h
WebCore/svg/SVGCursorElement.h
WebCore/svg/SVGEllipseElement.h
WebCore/svg/SVGFilterElement.h
WebCore/svg/SVGFilterPrimitiveStandardAttributes.h
WebCore/svg/SVGForeignObjectElement.h
WebCore/svg/SVGImageElement.h
WebCore/svg/SVGLength.idl
WebCore/svg/SVGLengthList.cpp
WebCore/svg/SVGLengthList.h
WebCore/svg/SVGLengthList.idl
WebCore/svg/SVGLineElement.h
WebCore/svg/SVGLinearGradientElement.h
WebCore/svg/SVGMarkerElement.h
WebCore/svg/SVGMaskElement.h
WebCore/svg/SVGPatternElement.h
WebCore/svg/SVGRadialGradientElement.h
WebCore/svg/SVGRectElement.h
WebCore/svg/SVGSVGElement.h
WebCore/svg/SVGSVGElement.idl
WebCore/svg/SVGTextContentElement.h
WebCore/svg/SVGTextPathElement.h
WebCore/svg/SVGTextPositioningElement.cpp
WebCore/svg/SVGTextPositioningElement.h
WebCore/svg/SVGUseElement.h
WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h [new file with mode: 0644]
WebCore/svg/properties/SVGAnimatedProperty.h [new file with mode: 0644]
WebCore/svg/properties/SVGAnimatedPropertyDescription.h [new file with mode: 0644]
WebCore/svg/properties/SVGAnimatedPropertyMacros.h [new file with mode: 0644]
WebCore/svg/properties/SVGAnimatedPropertyTearOff.h [new file with mode: 0644]
WebCore/svg/properties/SVGListPropertyTearOff.h [new file with mode: 0644]
WebCore/svg/properties/SVGProperty.h [new file with mode: 0644]
WebCore/svg/properties/SVGPropertyTearOff.h [new file with mode: 0644]
WebCore/svg/properties/SVGPropertyTraits.h [new file with mode: 0644]

index a867ab5..362373f 100644 (file)
@@ -1,3 +1,62 @@
+2010-10-20  Nikolas Zimmermann  <nzimmermann@rim.com>
+
+        Reviewed by Dirk Schulze.
+
+        Redesign SVGAnimatedProperty concept to share "POD type wrappers" between all bindings (-> add ObjC SVG bindings)
+        https://bugs.webkit.org/show_bug.cgi?id=47905
+
+        Add extensive set of SVGLengthList tests, that all PASS now.
+
+        * platform/mac-leopard/svg/dom: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.png: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum: Added.
+        * platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-appendItem-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-appendItem-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-basics-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-basics-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-getItem-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-getItem-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-initialize-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-initialize-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-removeItem-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-removeItem-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-replaceItem-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-replaceItem-expected.png: Added.
+        * platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum: Added.
+        * platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.png: Added.
+        * svg/dom/SVGLengthList-appendItem-expected.txt: Added.
+        * svg/dom/SVGLengthList-appendItem.xhtml: Added.
+        * svg/dom/SVGLengthList-basics-expected.txt: Added.
+        * svg/dom/SVGLengthList-basics.xhtml: Added.
+        * svg/dom/SVGLengthList-getItem-expected.txt: Added.
+        * svg/dom/SVGLengthList-getItem.xhtml: Added.
+        * svg/dom/SVGLengthList-initialize-expected.txt: Added.
+        * svg/dom/SVGLengthList-initialize.xhtml: Added.
+        * svg/dom/SVGLengthList-insertItemBefore-expected.txt: Added.
+        * svg/dom/SVGLengthList-insertItemBefore.xhtml: Added.
+        * svg/dom/SVGLengthList-removeItem-expected.txt: Added.
+        * svg/dom/SVGLengthList-removeItem.xhtml: Added.
+        * svg/dom/SVGLengthList-replaceItem-expected.txt: Added.
+        * svg/dom/SVGLengthList-replaceItem.xhtml: Added.
+        * svg/dom/SVGLengthList-xml-dom-modifications-expected.txt: Added.
+        * svg/dom/SVGLengthList-xml-dom-modifications.xhtml: Added.
+
 2010-10-21  Alex Milowski  <alex@milowski.com>
 
         Reviewed by Kenneth Rohde Christiansen.
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.checksum
new file mode 100644 (file)
index 0000000..f7e9d80
--- /dev/null
@@ -0,0 +1 @@
+c32a469543d60365e2cfee63d5ac8500
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.png
new file mode 100644 (file)
index 0000000..9a62e91
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-appendItem-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.checksum
new file mode 100644 (file)
index 0000000..29836cb
--- /dev/null
@@ -0,0 +1 @@
+1a4765a7d918b35950d26f55b12c506d
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.png
new file mode 100644 (file)
index 0000000..59a5c27
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-basics-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.checksum
new file mode 100644 (file)
index 0000000..c93754e
--- /dev/null
@@ -0,0 +1 @@
+c3fc7ac5c956e090ab25c7f351e26727
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.png
new file mode 100644 (file)
index 0000000..99f0a16
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-getItem-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.checksum
new file mode 100644 (file)
index 0000000..b2faafd
--- /dev/null
@@ -0,0 +1 @@
+2bf40a411f28949ee4aa3d013e036d15
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.png
new file mode 100644 (file)
index 0000000..6eace08
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-initialize-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.checksum
new file mode 100644 (file)
index 0000000..e3c992b
--- /dev/null
@@ -0,0 +1 @@
+4196550a965ef1897f442c7876684476
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.png
new file mode 100644 (file)
index 0000000..0714422
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-insertItemBefore-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.checksum
new file mode 100644 (file)
index 0000000..f7e9d80
--- /dev/null
@@ -0,0 +1 @@
+c32a469543d60365e2cfee63d5ac8500
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.png
new file mode 100644 (file)
index 0000000..9a62e91
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-removeItem-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.checksum
new file mode 100644 (file)
index 0000000..f76d346
--- /dev/null
@@ -0,0 +1 @@
+90383bcd1fc15aa82e218a7af7211bd8
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.png
new file mode 100644 (file)
index 0000000..a525fe3
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-replaceItem-expected.png differ
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum
new file mode 100644 (file)
index 0000000..aad0a4e
--- /dev/null
@@ -0,0 +1 @@
+dde1550e5fe7aebc9a1b7f84bcb8279f
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.png b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.png
new file mode 100644 (file)
index 0000000..4bdf7e3
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/svg/dom/SVGLengthList-xml-dom-modifications-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.checksum
new file mode 100644 (file)
index 0000000..774b4cd
--- /dev/null
@@ -0,0 +1 @@
+0d45c8d56692b06730986dfb0bf06fc6
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.png
new file mode 100644 (file)
index 0000000..6f4dddc
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-appendItem-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.checksum
new file mode 100644 (file)
index 0000000..dc29503
--- /dev/null
@@ -0,0 +1 @@
+dd5db0914f91e560746608204b446b31
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.png
new file mode 100644 (file)
index 0000000..279a9c7
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-basics-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.checksum
new file mode 100644 (file)
index 0000000..d13a07a
--- /dev/null
@@ -0,0 +1 @@
+15825fd3c24f4627077cf2f30f707ba6
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.png
new file mode 100644 (file)
index 0000000..34f0415
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-getItem-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.checksum
new file mode 100644 (file)
index 0000000..0af73d9
--- /dev/null
@@ -0,0 +1 @@
+707990a1c45be280c6e82f5019063cc9
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.png
new file mode 100644 (file)
index 0000000..0630a73
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-initialize-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.checksum
new file mode 100644 (file)
index 0000000..3c77b4c
--- /dev/null
@@ -0,0 +1 @@
+e48750edf231e3ce99fe37a32082173d
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.png
new file mode 100644 (file)
index 0000000..2aef03a
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-insertItemBefore-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.checksum
new file mode 100644 (file)
index 0000000..774b4cd
--- /dev/null
@@ -0,0 +1 @@
+0d45c8d56692b06730986dfb0bf06fc6
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.png
new file mode 100644 (file)
index 0000000..6f4dddc
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-removeItem-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.checksum
new file mode 100644 (file)
index 0000000..86032f4
--- /dev/null
@@ -0,0 +1 @@
+c7d9d465130ce98017de0c887677c942
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.png
new file mode 100644 (file)
index 0000000..d44b216
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-replaceItem-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum b/LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.checksum
new file mode 100644 (file)
index 0000000..abfe9e1
--- /dev/null
@@ -0,0 +1 @@
+24dba52e86e10497d36a4948177b804f
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.png b/LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.png
new file mode 100644 (file)
index 0000000..6b58bf1
Binary files /dev/null and b/LayoutTests/platform/mac/svg/dom/SVGLengthList-xml-dom-modifications-expected.png differ
diff --git a/LayoutTests/svg/dom/SVGLengthList-appendItem-expected.txt b/LayoutTests/svg/dom/SVGLengthList-appendItem-expected.txt
new file mode 100644 (file)
index 0000000..dd705c0
--- /dev/null
@@ -0,0 +1,104 @@
+ABC
+ABC
+ABC
+This is a test of the SVGLengthList::appendItem() API.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Create a new SVGLength object, with value=150
+PASS newLength1.value is 150
+
+Check initial list state of text1
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 50
+PASS text1.x.baseVal.getItem(2).value is 100
+PASS text1.x.baseVal.getItem(3).value is 900
+PASS text1.x.baseVal.getItem(4).value is 1000
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check initial list state of text2
+PASS text2.x.baseVal.numberOfItems is 3
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 1000
+PASS text2.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append fourth item x=900 to the text1 x list
+PASS text1.x.baseVal.appendItem(text1.x.baseVal.getItem(3)) is text1.x.baseVal.getItem(4)
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 50
+PASS text1.x.baseVal.getItem(2).value is 100
+PASS text1.x.baseVal.getItem(3).value is 1000
+PASS text1.x.baseVal.getItem(4).value is 900
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append first item x=500 to the text1 x list
+PASS text1.x.baseVal.appendItem(text1.x.baseVal.getItem(0)) is text1.x.baseVal.getItem(4)
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 1000
+PASS text1.x.baseVal.getItem(3).value is 900
+PASS text1.x.baseVal.getItem(4).value is 500
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append 'newLength1' to the text1 x list
+PASS text1.x.baseVal.appendItem(newLength1) is text1.x.baseVal.getItem(5)
+PASS text1.x.baseVal.numberOfItems is 6
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 1000
+PASS text1.x.baseVal.getItem(3).value is 900
+PASS text1.x.baseVal.getItem(4).value is 500
+PASS text1.x.baseVal.getItem(5).value is 150
+PASS text1.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append third and fourth item of the text1 x list to the text2 x list
+PASS text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value is 1000
+PASS text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value is 900
+PASS text1.x.baseVal.numberOfItems is 4
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 500
+PASS text1.x.baseVal.getItem(3).value is 150
+PASS text1.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text2.x.baseVal.numberOfItems is 5
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 1000
+PASS text2.x.baseVal.getItem(3).value is 1000
+PASS text2.x.baseVal.getItem(4).value is 900
+PASS text2.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS newLength2.value is 150
+
+Shuffle around items in text1 and text2 list using appendItem, to get x=50,100,150,... in both lists
+PASS text1.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value is 500
+PASS text2.x.baseVal.appendItem(newLength2).value is 150
+PASS text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value is 1000
+PASS text2.x.baseVal.appendItem(text2.x.baseVal.getItem(3)).value is 900
+PASS text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value is 1000
+PASS text1.x.baseVal.numberOfItems is 4
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 150
+PASS text1.x.baseVal.getItem(3).value is 500
+PASS text1.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text2.x.baseVal.numberOfItems is 6
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 150
+PASS text2.x.baseVal.getItem(3).value is 1000
+PASS text2.x.baseVal.getItem(4).value is 900
+PASS text2.x.baseVal.getItem(5).value is 1000
+PASS text2.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+The test passes if you only see 'PASS' messages, and all three text elements on top look the same
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-appendItem.xhtml b/LayoutTests/svg/dom/SVGLengthList-appendItem.xhtml
new file mode 100644 (file)
index 0000000..5ed69ad
--- /dev/null
@@ -0,0 +1,135 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 50 100 900 1000" y="50">ABC</text>
+    <text id="text2" x="50 100 1000" y="100">ABC</text>
+    <text id="reference" x="50 100 150" y="150">ABC</text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the SVGLengthList::appendItem() API.");
+
+    var svg = document.getElementById("svg");
+    var text1 = document.getElementById("text1");
+    var text2 = document.getElementById("text2");
+
+    debug("");
+    debug("Create a new SVGLength object, with value=150");
+    var newLength1 = svg.createSVGLength();
+    newLength1.value = 150;
+    shouldBe("newLength1.value", "150");
+
+    debug("");
+    debug("Check initial list state of text1");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "50");
+    shouldBe("text1.x.baseVal.getItem(2).value", "100");
+    shouldBe("text1.x.baseVal.getItem(3).value", "900");
+    shouldBe("text1.x.baseVal.getItem(4).value", "1000");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Check initial list state of text2");
+    shouldBe("text2.x.baseVal.numberOfItems", "3");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "1000");
+    shouldThrow("text2.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Append fourth item x=900 to the text1 x list");
+    shouldBe("text1.x.baseVal.appendItem(text1.x.baseVal.getItem(3))", "text1.x.baseVal.getItem(4)");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "50");
+    shouldBe("text1.x.baseVal.getItem(2).value", "100");
+    shouldBe("text1.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(4).value", "900");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Append first item x=500 to the text1 x list");
+    shouldBe("text1.x.baseVal.appendItem(text1.x.baseVal.getItem(0))", "text1.x.baseVal.getItem(4)");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(3).value", "900");
+    shouldBe("text1.x.baseVal.getItem(4).value", "500");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Append 'newLength1' to the text1 x list");
+    shouldBe("text1.x.baseVal.appendItem(newLength1)", "text1.x.baseVal.getItem(5)");
+    shouldBe("text1.x.baseVal.numberOfItems", "6");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(3).value", "900");
+    shouldBe("text1.x.baseVal.getItem(4).value", "500");
+    shouldBe("text1.x.baseVal.getItem(5).value", "150");
+    shouldThrow("text1.x.baseVal.getItem(6)");
+
+    debug("");
+    debug("Append third and fourth item of the text1 x list to the text2 x list");
+    shouldBe("text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value", "1000");
+    shouldBe("text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value", "900");
+    shouldBe("text1.x.baseVal.numberOfItems", "4");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "500");
+    shouldBe("text1.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text1.x.baseVal.getItem(4)");
+    shouldBe("text2.x.baseVal.numberOfItems", "5");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text2.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text2.x.baseVal.getItem(4).value", "900");
+    shouldThrow("text2.x.baseVal.getItem(5)");
+
+    var newLength2 = svg.createSVGLength();
+    newLength2.value = 150;
+    shouldBe("newLength2.value", "150");
+
+    debug("");
+    debug("Shuffle around items in text1 and text2 list using appendItem, to get x=50,100,150,... in both lists");
+    shouldBe("text1.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value", "500");
+    shouldBe("text2.x.baseVal.appendItem(newLength2).value", "150");
+    shouldBe("text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value", "1000");
+    shouldBe("text2.x.baseVal.appendItem(text2.x.baseVal.getItem(3)).value", "900");
+    shouldBe("text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value", "1000");
+    shouldBe("text1.x.baseVal.numberOfItems", "4");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+    shouldBe("text1.x.baseVal.getItem(3).value", "500");
+    shouldThrow("text1.x.baseVal.getItem(4)");
+    shouldBe("text2.x.baseVal.numberOfItems", "6");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "150");
+    shouldBe("text2.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text2.x.baseVal.getItem(4).value", "900");
+    shouldBe("text2.x.baseVal.getItem(5).value", "1000");
+    shouldThrow("text2.x.baseVal.getItem(6)");
+
+    debug("");
+    debug("The test passes if you only see 'PASS' messages, and all three text elements on top look the same");
+    debug("");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-basics-expected.txt b/LayoutTests/svg/dom/SVGLengthList-basics-expected.txt
new file mode 100644 (file)
index 0000000..9dd6b5f
--- /dev/null
@@ -0,0 +1,16 @@
+ABC
+This is a test of the simple SVGLengthList API parts.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS text1.x.baseVal != text1.x.animVal is true
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1.x.animVal.numberOfItems is 3
+PASS text1.x.animVal.clear() threw exception Error: NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7.
+PASS text1.x.baseVal.clear() is undefined.
+PASS text1.x.baseVal.initialize(30) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-basics.xhtml b/LayoutTests/svg/dom/SVGLengthList-basics.xhtml
new file mode 100644 (file)
index 0000000..7b9527e
--- /dev/null
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 1000 1500" y="50">   ABC  </text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the simple SVGLengthList API parts.");
+
+    var text1 = document.getElementById("text1");
+    // Spec: The object referenced by animVal will always be distinct from the one referenced by baseVal, even when the attribute is not animated.
+    shouldBeTrue("text1.x.baseVal != text1.x.animVal");
+
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+    shouldBe("text1.x.animVal.numberOfItems", "3");
+
+    // Spec: SVGAnimatedLengthList::animVal(): "A read only SVGLengthList representing the current animated value of the given attribute"
+    // Spec: SVGLengthList: "An SVGLengthList object can be designated as read only, which means that attempts to modify the object will result in an exception being thrown, as described below."
+    shouldThrow("text1.x.animVal.clear()");
+    shouldBeUndefined("text1.x.baseVal.clear()");
+
+    // Following Mozilla here, this should throw, when given a non SVGLength argument.
+    shouldThrow("text1.x.baseVal.initialize(30)");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-getItem-expected.txt b/LayoutTests/svg/dom/SVGLengthList-getItem-expected.txt
new file mode 100644 (file)
index 0000000..2781be7
--- /dev/null
@@ -0,0 +1,21 @@
+ABC
+This is a test of the SVGLengthList::getItem() API.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Check lengths of text x item lists
+PASS text1.x.baseVal.numberOfItems is 3
+
+Test with various index parameters
+PASS text1.x.baseVal.getItem(-100) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text1.x.baseVal.getItem(-1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 150
+PASS text1.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text1.x.baseVal.getItem(100) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-getItem.xhtml b/LayoutTests/svg/dom/SVGLengthList-getItem.xhtml
new file mode 100644 (file)
index 0000000..655cd39
--- /dev/null
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="50 100 150" y="50">ABC</text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the SVGLengthList::getItem() API.");
+
+    var svg = document.getElementById("svg");
+    var text1 = document.getElementById("text1");
+
+    debug("Check lengths of text x item lists");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+
+    debug("");
+    debug("Test with various index parameters");
+    shouldThrow("text1.x.baseVal.getItem(-100)");
+    shouldThrow("text1.x.baseVal.getItem(-1)");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+    shouldThrow("text1.x.baseVal.getItem(3)");
+    shouldThrow("text1.x.baseVal.getItem(100)");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-initialize-expected.txt b/LayoutTests/svg/dom/SVGLengthList-initialize-expected.txt
new file mode 100644 (file)
index 0000000..c7ec718
--- /dev/null
@@ -0,0 +1,88 @@
+ABC
+ABC
+ABC
+ABC
+ABC
+This is a test of the SVGLengthList::initialize() API.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Check initial list state of text1
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 1000
+PASS text1.x.baseVal.getItem(2).value is 1500
+PASS text1.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check initial list state of text2
+PASS text2.x.baseVal.numberOfItems is 2
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 500
+PASS text2.x.baseVal.getItem(2) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check initial list state of text3
+PASS text3.x.baseVal.numberOfItems is 3
+PASS text3.x.baseVal.getItem(0).value is 50
+PASS text3.x.baseVal.getItem(1).value is 500
+PASS text3.x.baseVal.getItem(2).value is 50
+PASS text3.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check initial list state of text4
+PASS text4.x.baseVal.numberOfItems is 1
+PASS text4.x.baseVal.getItem(0).value is 500
+PASS text4.x.baseVal.getItem(1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Create a new SVGLength object, that will be the only x coordinate in the first text element.
+PASS newLength.value is 50
+
+Initialize SVGLengthList with 'newLength'
+PASS text1.x.baseVal.initialize(newLength) is newLength
+PASS text1.x.baseVal.getItem(0) is newLength
+
+Take the second x item '500' of the second text element, store it in 'itemInAnotherList' change it to '50'
+PASS text2.x.baseVal.getItem(1).value is 500
+PASS text2.x.baseVal.getItem(1).value is 50
+
+Override the third text elements x list with the item x=50 from the second text element, where it should be removed afterwards
+PASS text3.x.baseVal.initialize(itemInAnotherList) is itemInAnotherList
+PASS text3.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Assure that the 'itemInAnotherList' item is still live anymore, set value to 999 then back to 50
+PASS itemInAnotherList.value = 999; is 999
+PASS itemInAnotherList.value is 999
+PASS text3.x.baseVal.getItem(0).value is 999
+PASS itemInAnotherList.value = 50; is 50
+PASS itemInAnotherList.value is 50
+PASS text3.x.baseVal.getItem(0).value is 50
+
+Move item from text3 to text4
+PASS text4.x.baseVal.initialize(text3.x.baseVal.getItem(0)) is itemInAnotherList
+PASS text4.x.baseVal.getItem(0).value is 50
+PASS text3.x.baseVal.getItem(0) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Initialize text3 using setAttribute('x', '50')
+PASS text3.x.baseVal.getItem(0).value is 50
+
+Final check whether the lists all look like expected
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text3.x.baseVal.getItem(0).value is 50
+PASS text4.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.numberOfItems is 1
+PASS text2.x.baseVal.numberOfItems is 1
+PASS text3.x.baseVal.numberOfItems is 1
+PASS text4.x.baseVal.numberOfItems is 1
+PASS text1.x.baseVal.getItem(1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text2.x.baseVal.getItem(1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text3.x.baseVal.getItem(1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text4.x.baseVal.getItem(1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+The test passes if you only see 'PASS' messages, and all five text elements on top look the same
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-initialize.xhtml b/LayoutTests/svg/dom/SVGLengthList-initialize.xhtml
new file mode 100644 (file)
index 0000000..b060b2d
--- /dev/null
@@ -0,0 +1,128 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 1000 1500" y="25">   ABC  </text>
+    <text id="text2" x="50 500" y="50">   ABC  </text>
+    <text id="text3" x="50 500 50" y="75">ABC</text>
+    <text id="text4" x="500" y="100">ABC</text>
+    <text id="reference" x="50" y="125">ABC</text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the SVGLengthList::initialize() API.");
+
+    var svg = document.getElementById("svg");
+    var text1 = document.getElementById("text1");
+    var text2 = document.getElementById("text2");
+    var text3 = document.getElementById("text3");
+    var text4 = document.getElementById("text4");
+
+    debug("Check initial list state of text1");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1500");
+    shouldThrow("text1.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Check initial list state of text2");
+    shouldBe("text2.x.baseVal.numberOfItems", "2");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "500");
+    shouldThrow("text2.x.baseVal.getItem(2)");
+
+    debug("");
+    debug("Check initial list state of text3");
+    shouldBe("text3.x.baseVal.numberOfItems", "3");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+    shouldBe("text3.x.baseVal.getItem(1).value", "500");
+    shouldBe("text3.x.baseVal.getItem(2).value", "50");
+    shouldThrow("text3.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Check initial list state of text4");
+    shouldBe("text4.x.baseVal.numberOfItems", "1");
+    shouldBe("text4.x.baseVal.getItem(0).value", "500");
+    shouldThrow("text4.x.baseVal.getItem(1)");
+
+    debug("");
+    debug("Create a new SVGLength object, that will be the only x coordinate in the first text element.");
+    var newLength = svg.createSVGLength();
+    newLength.value = 50;
+    shouldBe("newLength.value", "50");
+
+    // Spec: Clears all existing current items from the list and re-initializes the list to hold the single item specified by the parameter.
+    debug("");
+    debug("Initialize SVGLengthList with 'newLength'");
+    shouldBe("text1.x.baseVal.initialize(newLength)", "newLength");
+    shouldBe("text1.x.baseVal.getItem(0)", "newLength");
+
+    debug("");
+    debug("Take the second x item '500' of the second text element, store it in 'itemInAnotherList' change it to '50'");
+    shouldBe("text2.x.baseVal.getItem(1).value", "500");
+    var itemInAnotherList = text2.x.baseVal.getItem(1);
+    itemInAnotherList.value = 50;
+    shouldBe("text2.x.baseVal.getItem(1).value", "50");
+
+    // Spec: If the inserted item is already in a list, it is removed from its previous list before it is inserted into this list.
+    //       The inserted item is the item itself and not a copy.
+    debug("");
+    debug("Override the third text elements x list with the item x=50 from the second text element, where it should be removed afterwards");
+    shouldBe("text3.x.baseVal.initialize(itemInAnotherList)", "itemInAnotherList");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldThrow("text2.x.baseVal.getItem(1)");
+
+    debug("")
+    debug("Assure that the 'itemInAnotherList' item is still live anymore, set value to 999 then back to 50");
+    shouldBe("itemInAnotherList.value = 999;", "999");
+    shouldBe("itemInAnotherList.value", "999");
+    shouldBe("text3.x.baseVal.getItem(0).value", "999");
+    shouldBe("itemInAnotherList.value = 50;", "50");
+    shouldBe("itemInAnotherList.value", "50");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+
+    debug("");
+    debug("Move item from text3 to text4");
+    shouldBe("text4.x.baseVal.initialize(text3.x.baseVal.getItem(0))", "itemInAnotherList");
+    shouldBe("text4.x.baseVal.getItem(0).value", "50");
+    shouldThrow("text3.x.baseVal.getItem(0)");
+
+    debug("");
+    debug("Initialize text3 using setAttribute('x', '50')");
+    text3.setAttribute("x", "50");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+
+    debug("");
+    debug("Final check whether the lists all look like expected");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+    shouldBe("text4.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.numberOfItems", "1");
+    shouldBe("text2.x.baseVal.numberOfItems", "1");
+    shouldBe("text3.x.baseVal.numberOfItems", "1");
+    shouldBe("text4.x.baseVal.numberOfItems", "1");
+    shouldThrow("text1.x.baseVal.getItem(1)");
+    shouldThrow("text2.x.baseVal.getItem(1)");
+    shouldThrow("text3.x.baseVal.getItem(1)");
+    shouldThrow("text4.x.baseVal.getItem(1)");
+
+    debug("");
+    debug("The test passes if you only see 'PASS' messages, and all five text elements on top look the same");
+    debug("");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-insertItemBefore-expected.txt b/LayoutTests/svg/dom/SVGLengthList-insertItemBefore-expected.txt
new file mode 100644 (file)
index 0000000..8a2e764
--- /dev/null
@@ -0,0 +1,91 @@
+ABC
+ABC
+This is a test of the SVGLengthList::insertItemBefore() API.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Create three SVGLength objects, with values=50,100,150
+PASS newLength1.value is 50
+PASS newLength2.value is 100
+PASS newLength3.value is 150
+PASS newLength1 != newLength2 is true
+PASS newLength2 != newLength3 is true
+PASS newLength3 != newLength1 is true
+PASS newLength1.value == newLength2.value - 50 is true
+PASS newLength2.value + 50 == newLength3.value is true
+
+Check initial list state
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 1000
+PASS text1.x.baseVal.getItem(2).value is 1500
+PASS text1.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Insert item 'newLength1' at the end of the list, by using a large index
+PASS text1.x.baseVal.insertItemBefore(newLength1, 1000) is newLength1
+PASS text1.x.baseVal.numberOfItems is 4
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 1000
+PASS text1.x.baseVal.getItem(2).value is 1500
+PASS text1.x.baseVal.getItem(3).value is 50
+PASS text1.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Storing getItem(0/1/2) in local variables
+
+Insert item 'newLength2' at the front of the list, by using index=0
+PASS text1.x.baseVal.insertItemBefore(newLength2, 0) is newLength2
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 100
+PASS text1.x.baseVal.getItem(1).value is 500
+PASS text1.x.baseVal.getItem(2).value is 1000
+PASS text1.x.baseVal.getItem(3).value is 1500
+PASS text1.x.baseVal.getItem(4).value is 50
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Assure that previously saved wrappers still show the old values
+PASS item0.value is 500
+PASS item1.value is 1000
+PASS item2.value is 1500
+PASS item3.value is 50
+
+Insert item 'newLength3' at position=2, between '500' and '1000'
+PASS text1.x.baseVal.insertItemBefore(newLength3, 2) is newLength3
+PASS text1.x.baseVal.numberOfItems is 6
+PASS text1.x.baseVal.getItem(0).value is 100
+PASS text1.x.baseVal.getItem(1).value is 500
+PASS text1.x.baseVal.getItem(2).value is 150
+PASS text1.x.baseVal.getItem(3).value is 1000
+PASS text1.x.baseVal.getItem(4).value is 1500
+PASS text1.x.baseVal.getItem(5).value is 50
+PASS text1.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Insert item 'newLength3' at position=1, between '100' and '500', remove it from the old position=2 afterwards.
+PASS text1.x.baseVal.insertItemBefore(newLength3, 1) is newLength3
+PASS text1.x.baseVal.numberOfItems is 6
+PASS text1.x.baseVal.getItem(0).value is 100
+PASS text1.x.baseVal.getItem(1).value is 150
+PASS text1.x.baseVal.getItem(2).value is 500
+PASS text1.x.baseVal.getItem(3).value is 1000
+PASS text1.x.baseVal.getItem(4).value is 1500
+PASS text1.x.baseVal.getItem(5).value is 50
+PASS text1.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Insert item 'newLength3' at position=0, before '100', remove it from the old position=5 afterwards.
+PASS text1.x.baseVal.insertItemBefore(newLength1, 0) is newLength1
+PASS text1.x.baseVal.numberOfItems is 6
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 150
+PASS text1.x.baseVal.getItem(3).value is 500
+PASS text1.x.baseVal.getItem(4).value is 1000
+PASS text1.x.baseVal.getItem(5).value is 1500
+PASS text1.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+The test passes if you only see 'PASS' messages, and both text elements on top look the same
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-insertItemBefore.xhtml b/LayoutTests/svg/dom/SVGLengthList-insertItemBefore.xhtml
new file mode 100644 (file)
index 0000000..99141ad
--- /dev/null
@@ -0,0 +1,135 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 1000 1500" y="50">   ABC  </text>
+    <text id="reference" x="50 100 150" y="100">   ABC  </text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the SVGLengthList::insertItemBefore() API.");
+
+    var svg = document.getElementById("svg");
+    var text1 = document.getElementById("text1");
+
+    debug("");
+    debug("Create three SVGLength objects, with values=50,100,150");
+    var newLength1 = svg.createSVGLength();
+    newLength1.value = 50;
+    shouldBe("newLength1.value", "50");
+
+    var newLength2 = svg.createSVGLength();
+    newLength2.value = 100;
+    shouldBe("newLength2.value", "100");
+
+    var newLength3 = svg.createSVGLength();
+    newLength3.value = 150;
+    shouldBe("newLength3.value", "150");
+    
+    shouldBeTrue("newLength1 != newLength2");
+    shouldBeTrue("newLength2 != newLength3");
+    shouldBeTrue("newLength3 != newLength1");
+    shouldBeTrue("newLength1.value == newLength2.value - 50");
+    shouldBeTrue("newLength2.value + 50 == newLength3.value");
+
+    debug("");
+    debug("Check initial list state");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1500");
+    shouldThrow("text1.x.baseVal.getItem(3)");
+
+    // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+    debug("");
+    debug("Insert item 'newLength1' at the end of the list, by using a large index");
+    shouldBe("text1.x.baseVal.insertItemBefore(newLength1, 1000)", "newLength1");
+    shouldBe("text1.x.baseVal.numberOfItems", "4");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1500");
+    shouldBe("text1.x.baseVal.getItem(3).value", "50");
+    shouldThrow("text1.x.baseVal.getItem(4)");
+
+    debug("");
+    debug("Storing getItem(0/1/2) in local variables");
+    var item0 = text1.x.baseVal.getItem(0);
+    var item1 = text1.x.baseVal.getItem(1);
+    var item2 = text1.x.baseVal.getItem(2);
+    var item3 = text1.x.baseVal.getItem(3);
+
+    // Spec: If the index is equal to 0, then the new item is inserted at the front of the list.
+    debug("");
+    debug("Insert item 'newLength2' at the front of the list, by using index=0");
+    shouldBe("text1.x.baseVal.insertItemBefore(newLength2, 0)", "newLength2");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "100");
+    shouldBe("text1.x.baseVal.getItem(1).value", "500");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(3).value", "1500");
+    shouldBe("text1.x.baseVal.getItem(4).value", "50");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Assure that previously saved wrappers still show the old values");
+    shouldBe("item0.value", "500");
+    shouldBe("item1.value", "1000");
+    shouldBe("item2.value", "1500");
+    shouldBe("item3.value", "50");
+
+    // Spec: The index of the item before which the new item is to be inserted.
+    debug("");
+    debug("Insert item 'newLength3' at position=2, between '500' and '1000'");
+    shouldBe("text1.x.baseVal.insertItemBefore(newLength3, 2)", "newLength3");
+    shouldBe("text1.x.baseVal.numberOfItems", "6");
+    shouldBe("text1.x.baseVal.getItem(0).value", "100");
+    shouldBe("text1.x.baseVal.getItem(1).value", "500");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+    shouldBe("text1.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(4).value", "1500");
+    shouldBe("text1.x.baseVal.getItem(5).value", "50");
+    shouldThrow("text1.x.baseVal.getItem(6)");
+
+    // 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 insert before is before the removal of the item. 
+    debug("");
+    debug("Insert item 'newLength3' at position=1, between '100' and '500', remove it from the old position=2 afterwards.");
+    shouldBe("text1.x.baseVal.insertItemBefore(newLength3, 1)", "newLength3");
+    shouldBe("text1.x.baseVal.numberOfItems", "6");
+    shouldBe("text1.x.baseVal.getItem(0).value", "100");
+    shouldBe("text1.x.baseVal.getItem(1).value", "150");
+    shouldBe("text1.x.baseVal.getItem(2).value", "500");
+    shouldBe("text1.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(4).value", "1500");
+    shouldBe("text1.x.baseVal.getItem(5).value", "50");
+    shouldThrow("text1.x.baseVal.getItem(6)");
+
+    debug("");
+    debug("Insert item 'newLength3' at position=0, before '100', remove it from the old position=5 afterwards.");
+    shouldBe("text1.x.baseVal.insertItemBefore(newLength1, 0)", "newLength1");
+    shouldBe("text1.x.baseVal.numberOfItems", "6");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+    shouldBe("text1.x.baseVal.getItem(3).value", "500");
+    shouldBe("text1.x.baseVal.getItem(4).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(5).value", "1500");
+    shouldThrow("text1.x.baseVal.getItem(6)");
+
+    debug("");
+    debug("The test passes if you only see 'PASS' messages, and both text elements on top look the same");
+    debug("");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-removeItem-expected.txt b/LayoutTests/svg/dom/SVGLengthList-removeItem-expected.txt
new file mode 100644 (file)
index 0000000..dd705c0
--- /dev/null
@@ -0,0 +1,104 @@
+ABC
+ABC
+ABC
+This is a test of the SVGLengthList::appendItem() API.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Create a new SVGLength object, with value=150
+PASS newLength1.value is 150
+
+Check initial list state of text1
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 50
+PASS text1.x.baseVal.getItem(2).value is 100
+PASS text1.x.baseVal.getItem(3).value is 900
+PASS text1.x.baseVal.getItem(4).value is 1000
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check initial list state of text2
+PASS text2.x.baseVal.numberOfItems is 3
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 1000
+PASS text2.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append fourth item x=900 to the text1 x list
+PASS text1.x.baseVal.appendItem(text1.x.baseVal.getItem(3)) is text1.x.baseVal.getItem(4)
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 50
+PASS text1.x.baseVal.getItem(2).value is 100
+PASS text1.x.baseVal.getItem(3).value is 1000
+PASS text1.x.baseVal.getItem(4).value is 900
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append first item x=500 to the text1 x list
+PASS text1.x.baseVal.appendItem(text1.x.baseVal.getItem(0)) is text1.x.baseVal.getItem(4)
+PASS text1.x.baseVal.numberOfItems is 5
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 1000
+PASS text1.x.baseVal.getItem(3).value is 900
+PASS text1.x.baseVal.getItem(4).value is 500
+PASS text1.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append 'newLength1' to the text1 x list
+PASS text1.x.baseVal.appendItem(newLength1) is text1.x.baseVal.getItem(5)
+PASS text1.x.baseVal.numberOfItems is 6
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 1000
+PASS text1.x.baseVal.getItem(3).value is 900
+PASS text1.x.baseVal.getItem(4).value is 500
+PASS text1.x.baseVal.getItem(5).value is 150
+PASS text1.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Append third and fourth item of the text1 x list to the text2 x list
+PASS text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value is 1000
+PASS text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value is 900
+PASS text1.x.baseVal.numberOfItems is 4
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 500
+PASS text1.x.baseVal.getItem(3).value is 150
+PASS text1.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text2.x.baseVal.numberOfItems is 5
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 1000
+PASS text2.x.baseVal.getItem(3).value is 1000
+PASS text2.x.baseVal.getItem(4).value is 900
+PASS text2.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS newLength2.value is 150
+
+Shuffle around items in text1 and text2 list using appendItem, to get x=50,100,150,... in both lists
+PASS text1.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value is 500
+PASS text2.x.baseVal.appendItem(newLength2).value is 150
+PASS text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value is 1000
+PASS text2.x.baseVal.appendItem(text2.x.baseVal.getItem(3)).value is 900
+PASS text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value is 1000
+PASS text1.x.baseVal.numberOfItems is 4
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 150
+PASS text1.x.baseVal.getItem(3).value is 500
+PASS text1.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text2.x.baseVal.numberOfItems is 6
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 150
+PASS text2.x.baseVal.getItem(3).value is 1000
+PASS text2.x.baseVal.getItem(4).value is 900
+PASS text2.x.baseVal.getItem(5).value is 1000
+PASS text2.x.baseVal.getItem(6) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+The test passes if you only see 'PASS' messages, and all three text elements on top look the same
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-removeItem.xhtml b/LayoutTests/svg/dom/SVGLengthList-removeItem.xhtml
new file mode 100644 (file)
index 0000000..5ed69ad
--- /dev/null
@@ -0,0 +1,135 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 50 100 900 1000" y="50">ABC</text>
+    <text id="text2" x="50 100 1000" y="100">ABC</text>
+    <text id="reference" x="50 100 150" y="150">ABC</text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the SVGLengthList::appendItem() API.");
+
+    var svg = document.getElementById("svg");
+    var text1 = document.getElementById("text1");
+    var text2 = document.getElementById("text2");
+
+    debug("");
+    debug("Create a new SVGLength object, with value=150");
+    var newLength1 = svg.createSVGLength();
+    newLength1.value = 150;
+    shouldBe("newLength1.value", "150");
+
+    debug("");
+    debug("Check initial list state of text1");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "50");
+    shouldBe("text1.x.baseVal.getItem(2).value", "100");
+    shouldBe("text1.x.baseVal.getItem(3).value", "900");
+    shouldBe("text1.x.baseVal.getItem(4).value", "1000");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Check initial list state of text2");
+    shouldBe("text2.x.baseVal.numberOfItems", "3");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "1000");
+    shouldThrow("text2.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Append fourth item x=900 to the text1 x list");
+    shouldBe("text1.x.baseVal.appendItem(text1.x.baseVal.getItem(3))", "text1.x.baseVal.getItem(4)");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "50");
+    shouldBe("text1.x.baseVal.getItem(2).value", "100");
+    shouldBe("text1.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(4).value", "900");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Append first item x=500 to the text1 x list");
+    shouldBe("text1.x.baseVal.appendItem(text1.x.baseVal.getItem(0))", "text1.x.baseVal.getItem(4)");
+    shouldBe("text1.x.baseVal.numberOfItems", "5");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(3).value", "900");
+    shouldBe("text1.x.baseVal.getItem(4).value", "500");
+    shouldThrow("text1.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Append 'newLength1' to the text1 x list");
+    shouldBe("text1.x.baseVal.appendItem(newLength1)", "text1.x.baseVal.getItem(5)");
+    shouldBe("text1.x.baseVal.numberOfItems", "6");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(3).value", "900");
+    shouldBe("text1.x.baseVal.getItem(4).value", "500");
+    shouldBe("text1.x.baseVal.getItem(5).value", "150");
+    shouldThrow("text1.x.baseVal.getItem(6)");
+
+    debug("");
+    debug("Append third and fourth item of the text1 x list to the text2 x list");
+    shouldBe("text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value", "1000");
+    shouldBe("text2.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value", "900");
+    shouldBe("text1.x.baseVal.numberOfItems", "4");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "500");
+    shouldBe("text1.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text1.x.baseVal.getItem(4)");
+    shouldBe("text2.x.baseVal.numberOfItems", "5");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "1000");
+    shouldBe("text2.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text2.x.baseVal.getItem(4).value", "900");
+    shouldThrow("text2.x.baseVal.getItem(5)");
+
+    var newLength2 = svg.createSVGLength();
+    newLength2.value = 150;
+    shouldBe("newLength2.value", "150");
+
+    debug("");
+    debug("Shuffle around items in text1 and text2 list using appendItem, to get x=50,100,150,... in both lists");
+    shouldBe("text1.x.baseVal.appendItem(text1.x.baseVal.getItem(2)).value", "500");
+    shouldBe("text2.x.baseVal.appendItem(newLength2).value", "150");
+    shouldBe("text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value", "1000");
+    shouldBe("text2.x.baseVal.appendItem(text2.x.baseVal.getItem(3)).value", "900");
+    shouldBe("text2.x.baseVal.appendItem(text2.x.baseVal.getItem(2)).value", "1000");
+    shouldBe("text1.x.baseVal.numberOfItems", "4");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+    shouldBe("text1.x.baseVal.getItem(3).value", "500");
+    shouldThrow("text1.x.baseVal.getItem(4)");
+    shouldBe("text2.x.baseVal.numberOfItems", "6");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "150");
+    shouldBe("text2.x.baseVal.getItem(3).value", "1000");
+    shouldBe("text2.x.baseVal.getItem(4).value", "900");
+    shouldBe("text2.x.baseVal.getItem(5).value", "1000");
+    shouldThrow("text2.x.baseVal.getItem(6)");
+
+    debug("");
+    debug("The test passes if you only see 'PASS' messages, and all three text elements on top look the same");
+    debug("");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-replaceItem-expected.txt b/LayoutTests/svg/dom/SVGLengthList-replaceItem-expected.txt
new file mode 100644 (file)
index 0000000..21170e2
--- /dev/null
@@ -0,0 +1,129 @@
+ABC
+ABC
+ABC
+ABC
+ABC
+This is a test of the SVGLengthList::replaceItem() API.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Create three SVGLength objects, with values=50,100,150
+PASS newLength1.value is 50
+PASS newLength2.value is 100
+PASS newLength3.value is 150
+
+Check initial list state of text1
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1.x.baseVal.getItem(0).value is 500
+PASS text1.x.baseVal.getItem(1).value is 1000
+PASS text1.x.baseVal.getItem(2).value is 1500
+PASS text1.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Replace the first three values in text1 x list with 'newLength1/2/3'
+PASS text1.x.baseVal.replaceItem(newLength1, 0) is newLength1
+PASS text1.x.baseVal.replaceItem(newLength2, 1) is newLength2
+PASS text1.x.baseVal.replaceItem(newLength3, 2) is newLength3
+PASS text1.x.baseVal.replaceItem(newLength3, -100) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text1.x.baseVal.replaceItem(newLength3, -1) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text1.x.baseVal.replaceItem(newLength3, 3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text1.x.baseVal.replaceItem(newLength3, 100) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Verify that the text1 x value list is correct
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 150
+
+Check initial list state of text2
+PASS text2.x.baseVal.numberOfItems is 4
+PASS text2.x.baseVal.getItem(0).value is 500
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 50
+PASS text2.x.baseVal.getItem(3).value is 150
+PASS text2.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Replace the first item in text2 x list with the third item in the list
+PASS text2.x.baseVal.replaceItem(text2.x.baseVal.getItem(2), 0).value is 50
+PASS text2.x.baseVal.numberOfItems is 3
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 150
+
+Check initial list state of text3
+PASS text3.x.baseVal.numberOfItems is 5
+PASS text3.x.baseVal.getItem(0).value is 50
+PASS text3.x.baseVal.getItem(1).value is 50
+PASS text3.x.baseVal.getItem(2).value is 100
+PASS text3.x.baseVal.getItem(3).value is 100
+PASS text3.x.baseVal.getItem(4).value is 150
+PASS text3.x.baseVal.getItem(5) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check initial list state of text4
+PASS text4.x.baseVal.numberOfItems is 4
+PASS text4.x.baseVal.getItem(0).value is 100
+PASS text4.x.baseVal.getItem(1).value is 50
+PASS text4.x.baseVal.getItem(2).value is 150
+PASS text4.x.baseVal.getItem(3).value is 150
+PASS text4.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Replace the first item in text4 x list with the second item in the text3 x list
+PASS text4.x.baseVal.replaceItem(text3.x.baseVal.getItem(1), 0).value is 50
+PASS text3.x.baseVal.numberOfItems is 4
+PASS text3.x.baseVal.getItem(0).value is 50
+PASS text3.x.baseVal.getItem(1).value is 100
+PASS text3.x.baseVal.getItem(2).value is 100
+PASS text3.x.baseVal.getItem(3).value is 150
+PASS text3.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS text4.x.baseVal.numberOfItems is 4
+PASS text4.x.baseVal.getItem(0).value is 50
+PASS text4.x.baseVal.getItem(1).value is 50
+PASS text4.x.baseVal.getItem(2).value is 150
+PASS text4.x.baseVal.getItem(3).value is 150
+PASS text4.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Replace the second item in text4 x list with the second item in the text4 x list
+PASS text4.x.baseVal.replaceItem(text3.x.baseVal.getItem(2), 1).value is 100
+PASS text4.x.baseVal.numberOfItems is 4
+PASS text4.x.baseVal.getItem(0).value is 50
+PASS text4.x.baseVal.getItem(1).value is 100
+PASS text4.x.baseVal.getItem(2).value is 150
+PASS text4.x.baseVal.getItem(3).value is 150
+PASS text4.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check final list state of text1
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+PASS text1.x.baseVal.getItem(2).value is 150
+PASS text1.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check final list state of text2
+PASS text2.x.baseVal.numberOfItems is 3
+PASS text2.x.baseVal.getItem(0).value is 50
+PASS text2.x.baseVal.getItem(1).value is 100
+PASS text2.x.baseVal.getItem(2).value is 150
+PASS text2.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check final list state of text3
+PASS text3.x.baseVal.numberOfItems is 3
+PASS text3.x.baseVal.getItem(0).value is 50
+PASS text3.x.baseVal.getItem(1).value is 100
+PASS text3.x.baseVal.getItem(2).value is 150
+PASS text3.x.baseVal.getItem(3) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+Check final list state of text4
+PASS text4.x.baseVal.numberOfItems is 4
+PASS text4.x.baseVal.getItem(0).value is 50
+PASS text4.x.baseVal.getItem(1).value is 100
+PASS text4.x.baseVal.getItem(2).value is 150
+PASS text4.x.baseVal.getItem(3).value is 150
+PASS text4.x.baseVal.getItem(4) threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
+
+The test passes if you only see 'PASS' messages, and all five text elements on top look the same
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-replaceItem.xhtml b/LayoutTests/svg/dom/SVGLengthList-replaceItem.xhtml
new file mode 100644 (file)
index 0000000..6451f82
--- /dev/null
@@ -0,0 +1,171 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 1000 1500" y="50">  ABC   </text>
+    <text id="text2" x="500 100 50 150" y="75"> ABC   </text>
+    <text id="text3" x="50 50 100 100 150" y="100">  ABC</text>
+    <text id="text4" x="100 50 150 150" y="125">   ABC</text>
+    <text id="reference" x="50 100 150" y="150">ABC  </text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test of the SVGLengthList::replaceItem() API.");
+
+    var svg = document.getElementById("svg");
+    var text1 = document.getElementById("text1");
+    var text2 = document.getElementById("text2");
+    var text3 = document.getElementById("text3");
+    var text4 = document.getElementById("text4");
+
+    debug("");
+    debug("Create three SVGLength objects, with values=50,100,150");
+    var newLength1 = svg.createSVGLength();
+    newLength1.value = 50;
+    shouldBe("newLength1.value", "50");
+
+    var newLength2 = svg.createSVGLength();
+    newLength2.value = 100;
+    shouldBe("newLength2.value", "100");
+
+    var newLength3 = svg.createSVGLength();
+    newLength3.value = 150;
+    shouldBe("newLength3.value", "150");
+
+    debug("");
+    debug("Check initial list state of text1");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+    shouldBe("text1.x.baseVal.getItem(0).value", "500");
+    shouldBe("text1.x.baseVal.getItem(1).value", "1000");
+    shouldBe("text1.x.baseVal.getItem(2).value", "1500");
+    shouldThrow("text1.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Replace the first three values in text1 x list with 'newLength1/2/3'");
+    shouldBe("text1.x.baseVal.replaceItem(newLength1, 0)", "newLength1");
+    shouldBe("text1.x.baseVal.replaceItem(newLength2, 1)", "newLength2");
+    shouldBe("text1.x.baseVal.replaceItem(newLength3, 2)", "newLength3");
+    shouldThrow("text1.x.baseVal.replaceItem(newLength3, -100)");
+    shouldThrow("text1.x.baseVal.replaceItem(newLength3, -1)");
+    shouldThrow("text1.x.baseVal.replaceItem(newLength3, 3)");
+    shouldThrow("text1.x.baseVal.replaceItem(newLength3, 100)");
+
+    debug("");
+    debug("Verify that the text1 x value list is correct");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+
+    debug("");
+    debug("Check initial list state of text2");
+    shouldBe("text2.x.baseVal.numberOfItems", "4");
+    shouldBe("text2.x.baseVal.getItem(0).value", "500");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "50");
+    shouldBe("text2.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text2.x.baseVal.getItem(4)");
+
+    debug("");
+    debug("Replace the first item in text2 x list with the third item in the list");
+    shouldBe("text2.x.baseVal.replaceItem(text2.x.baseVal.getItem(2), 0).value", "50");
+    shouldBe("text2.x.baseVal.numberOfItems", "3");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "150");
+
+    debug("");
+    debug("Check initial list state of text3");
+    shouldBe("text3.x.baseVal.numberOfItems", "5");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+    shouldBe("text3.x.baseVal.getItem(1).value", "50");
+    shouldBe("text3.x.baseVal.getItem(2).value", "100");
+    shouldBe("text3.x.baseVal.getItem(3).value", "100");
+    shouldBe("text3.x.baseVal.getItem(4).value", "150");
+    shouldThrow("text3.x.baseVal.getItem(5)");
+
+    debug("");
+    debug("Check initial list state of text4");
+    shouldBe("text4.x.baseVal.numberOfItems", "4");
+    shouldBe("text4.x.baseVal.getItem(0).value", "100");
+    shouldBe("text4.x.baseVal.getItem(1).value", "50");
+    shouldBe("text4.x.baseVal.getItem(2).value", "150");
+    shouldBe("text4.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text4.x.baseVal.getItem(4)");
+
+    debug("");
+    debug("Replace the first item in text4 x list with the second item in the text3 x list");
+    shouldBe("text4.x.baseVal.replaceItem(text3.x.baseVal.getItem(1), 0).value", "50");
+    shouldBe("text3.x.baseVal.numberOfItems", "4");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+    shouldBe("text3.x.baseVal.getItem(1).value", "100");
+    shouldBe("text3.x.baseVal.getItem(2).value", "100");
+    shouldBe("text3.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text3.x.baseVal.getItem(4)");
+    shouldBe("text4.x.baseVal.numberOfItems", "4");
+    shouldBe("text4.x.baseVal.getItem(0).value", "50");
+    shouldBe("text4.x.baseVal.getItem(1).value", "50");
+    shouldBe("text4.x.baseVal.getItem(2).value", "150");
+    shouldBe("text4.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text4.x.baseVal.getItem(4)");
+
+    debug("");
+    debug("Replace the second item in text4 x list with the second item in the text4 x list");
+    shouldBe("text4.x.baseVal.replaceItem(text3.x.baseVal.getItem(2), 1).value", "100");
+    shouldBe("text4.x.baseVal.numberOfItems", "4");
+    shouldBe("text4.x.baseVal.getItem(0).value", "50");
+    shouldBe("text4.x.baseVal.getItem(1).value", "100");
+    shouldBe("text4.x.baseVal.getItem(2).value", "150");
+    shouldBe("text4.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text4.x.baseVal.getItem(4)");
+
+    debug("");
+    debug("Check final list state of text1");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+    shouldBe("text1.x.baseVal.getItem(2).value", "150");
+    shouldThrow("text1.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Check final list state of text2");
+    shouldBe("text2.x.baseVal.numberOfItems", "3");
+    shouldBe("text2.x.baseVal.getItem(0).value", "50");
+    shouldBe("text2.x.baseVal.getItem(1).value", "100");
+    shouldBe("text2.x.baseVal.getItem(2).value", "150");
+    shouldThrow("text2.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Check final list state of text3");
+    shouldBe("text3.x.baseVal.numberOfItems", "3");
+    shouldBe("text3.x.baseVal.getItem(0).value", "50");
+    shouldBe("text3.x.baseVal.getItem(1).value", "100");
+    shouldBe("text3.x.baseVal.getItem(2).value", "150");
+    shouldThrow("text3.x.baseVal.getItem(3)");
+
+    debug("");
+    debug("Check final list state of text4");
+    shouldBe("text4.x.baseVal.numberOfItems", "4");
+    shouldBe("text4.x.baseVal.getItem(0).value", "50");
+    shouldBe("text4.x.baseVal.getItem(1).value", "100");
+    shouldBe("text4.x.baseVal.getItem(2).value", "150");
+    shouldBe("text4.x.baseVal.getItem(3).value", "150");
+    shouldThrow("text4.x.baseVal.getItem(4)");
+
+    debug("");
+    debug("The test passes if you only see 'PASS' messages, and all five text elements on top look the same");
+    debug("");
+
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dom/SVGLengthList-xml-dom-modifications-expected.txt b/LayoutTests/svg/dom/SVGLengthList-xml-dom-modifications-expected.txt
new file mode 100644 (file)
index 0000000..42d955e
--- /dev/null
@@ -0,0 +1,47 @@
+ABC
+ABC
+This is a test how SVGLengthList reacts to XML DOM modifications.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS text1.x.baseVal.numberOfItems is 3
+PASS text1XBaseValGetItem0.value is 500
+PASS text1XBaseValGetItem1.value is 1000
+PASS text1XBaseValGetItem2.value is 1500
+
+Setting x = x - 250 on all three items
+PASS text1XBaseValGetItem0.value is 250
+PASS text1XBaseValGetItem1.value is 750
+PASS text1XBaseValGetItem2.value is 1250
+
+Now using text.setAttribute('x', '50 100')
+
+Assure that the wrappers still point to the OLD values
+PASS text1XBaseValGetItem0.value is 250
+PASS text1XBaseValGetItem1.value is 750
+PASS text1XBaseValGetItem2.value is 1250
+
+Assure that obtaining new wrappers will give the right NEW values
+PASS text1.x.baseVal.numberOfItems is 2
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+
+Setting x = x + 100 on all old wrapper items
+
+Assure that the old wrappers can still be modified, but don't influence the new wrappers
+PASS text1XBaseValGetItem0.value is 350
+PASS text1XBaseValGetItem1.value is 850
+PASS text1XBaseValGetItem2.value is 1350
+
+Assure that the new wrappers stayed the same
+PASS text1.x.baseVal.numberOfItems is 2
+PASS text1.x.baseVal.getItem(0).value is 50
+PASS text1.x.baseVal.getItem(1).value is 100
+
+The test passes if you only see 'PASS' messages, and both elements on top look the same
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dom/SVGLengthList-xml-dom-modifications.xhtml b/LayoutTests/svg/dom/SVGLengthList-xml-dom-modifications.xhtml
new file mode 100644 (file)
index 0000000..eb457fb
--- /dev/null
@@ -0,0 +1,84 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css"/>
+<script>window.enablePixelTesting = true;</script>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <text id="text1" x="500 1000 1500" y="50">   ABC  </text>
+    <text id="reference" x="50 100" y="100">   ABC  </text>
+</svg>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+<![CDATA[
+    description("This is a test how SVGLengthList reacts to XML DOM modifications.");
+
+    var text1 = document.getElementById("text1");
+    shouldBe("text1.x.baseVal.numberOfItems", "3");
+
+    var text1XBaseValGetItem0 = text1.x.baseVal.getItem(0);
+    var text1XBaseValGetItem1 = text1.x.baseVal.getItem(1);
+    var text1XBaseValGetItem2 = text1.x.baseVal.getItem(2);
+
+    shouldBe("text1XBaseValGetItem0.value", "500");
+    shouldBe("text1XBaseValGetItem1.value", "1000");
+    shouldBe("text1XBaseValGetItem2.value", "1500");
+
+    debug("");
+    debug("Setting x = x - 250 on all three items");
+    
+    text1XBaseValGetItem0.value -= 250;
+    text1XBaseValGetItem1.value -= 250;
+    text1XBaseValGetItem2.value -= 250;
+
+    shouldBe("text1XBaseValGetItem0.value", "250");
+    shouldBe("text1XBaseValGetItem1.value", "750");
+    shouldBe("text1XBaseValGetItem2.value", "1250");
+
+    debug("");
+    debug("Now using text.setAttribute('x', '50 100')");
+    text1.setAttribute("x", "50 100");
+
+    debug("");
+    debug("Assure that the wrappers still point to the OLD values");
+    shouldBe("text1XBaseValGetItem0.value", "250");
+    shouldBe("text1XBaseValGetItem1.value", "750");
+    shouldBe("text1XBaseValGetItem2.value", "1250");
+
+    debug("");
+    debug("Assure that obtaining new wrappers will give the right NEW values");
+    shouldBe("text1.x.baseVal.numberOfItems", "2");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+
+    debug("");
+    debug("Setting x = x + 100 on all old wrapper items");
+    text1XBaseValGetItem0.value += 100;
+    text1XBaseValGetItem1.value += 100;
+    text1XBaseValGetItem2.value += 100;
+
+    debug("");
+    debug("Assure that the old wrappers can still be modified, but don't influence the new wrappers");
+    shouldBe("text1XBaseValGetItem0.value", "350");
+    shouldBe("text1XBaseValGetItem1.value", "850");
+    shouldBe("text1XBaseValGetItem2.value", "1350");
+
+    debug("");
+    debug("Assure that the new wrappers stayed the same");
+    shouldBe("text1.x.baseVal.numberOfItems", "2");
+    shouldBe("text1.x.baseVal.getItem(0).value", "50");
+    shouldBe("text1.x.baseVal.getItem(1).value", "100");
+
+    debug("");
+    debug("The test passes if you only see 'PASS' messages, and both elements on top look the same");
+    debug("");
+    successfullyParsed = true;
+]]>
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index 93cf40b..bcbb125 100644 (file)
@@ -1,3 +1,137 @@
+2010-10-20  Nikolas Zimmermann  <nzimmermann@rim.com>
+
+        Reviewed by Dirk Schulze.
+
+        Redesign SVGAnimatedProperty concept to share "POD type wrappers" between all bindings (-> add ObjC SVG bindings)
+        https://bugs.webkit.org/show_bug.cgi?id=47905
+
+        Tests: svg/dom/SVGLengthList-appendItem.xhtml
+               svg/dom/SVGLengthList-basics.xhtml
+               svg/dom/SVGLengthList-getItem.xhtml
+               svg/dom/SVGLengthList-initialize.xhtml
+               svg/dom/SVGLengthList-insertItemBefore.xhtml
+               svg/dom/SVGLengthList-removeItem.xhtml
+               svg/dom/SVGLengthList-replaceItem.xhtml
+               svg/dom/SVGLengthList-xml-dom-modifications.xhtml
+
+        Introduce a more lightweight, less intrusive way to expose SVGAnimated* DOM bindings.
+
+        Concrete example:
+        The SVG DOM defines a 'SVGAnimatedLength' object, that's used to represent the x / y / width / height attributes of a 'SVGRectElement'.
+        Each 'SVGAnimatedLength' object exposes a baseVal (markup defined attribute value) and an animVal (reflects the current state during animations),
+        both of type 'SVGLength'. These objects are all _live_. That means you can do:
+        var foobar = rect.x.baseVal; foobar.value += 150;
+
+        If we'd implement the SVG DOM straightforward, we'd have to store a refcounted SVGAnimatedLength object, containing two refcounted SVGLength objects
+        in SVGRectElement, for each of the x/y/width/height attributes. Our solution, to reduce memory footprint and increase performance is to store
+        SVGLength stack-allocated, non refcounted types in SVGRectElement for x/y/width/height, and don't implement the SVGAnimatedLength object at all.
+
+        In the past the JS bindings had to expose wrappers for SVGAnimatedLength on their own, and wrap each SVGLength object in an object called JSSVGPODTypeWrapper<SVGLength>.
+        When JS changed the 'value' of the 'SVGLength', we constructed a copy of the SVGLength object, modified it, and called rectElement->setXBaseValue(newLength).
+        This is not efficient at all, as we have to construct several copies of the SVGLength object, utilize callbacks to propagate the value changes in the SVG DOM.
+        Furthermore, all bindings had to expose a similar concept, otherwhise SVG DOM wouldn't work. Up until now, only JSC and V8 bindings were available, that worked properly.
+
+        The new SVGAnimatedProperty concept removes the need for JSSVGPODTypeWrapper (and friends like JSSVGContextCache, that associated a SVGLength with its SVGRectElement).
+        Instead a solution is offered, that all bindings can use simultaneously, without adding new types or special concepts like JSSVGPODTypeWrapper.
+
+        It works like this:
+        A new refcounted SVGAnimatedProperty<PropertyType> template class is available, that stores a QualifiedName to associate the SVG DOM property with a XML DOM attribute.
+        It also stores a RefPtr to the SVGElement that created it.
+        
+        In SVGRectElement we still store SVGLength m_x/m_y/m_width/m_height members, and offer a new "xAnimated()" method which looks up or creates a SVGAnimatedProperty<SVGLength>
+        object. The JS/V8/ObjC bindings call this method whenever someone requests "rect.x/y/width/height", and a new wrapper is created, and stored in a HashMap.
+
+        The SVGAnimatedProperty<PropertyType> is a base class for SVGAnimatedPropertyTearOff and SVGAnimatedListPropertyTearOff, the latter is used for all types of lists (SVGLengthList).
+        SVGAnimatedProperty contains two methods used in the bindings: SVGProperty* baseVal and SVGProperty* animVal. SVGProperty is a base class for SVGPropertyTearOff and
+        SVGListPropertyTearOff. Upon invocation of the baseVal/animVal methods a new SVG(List)PropertyTearOff object is created and stored in a RefPtr.
+        The SVGPropertyTearOff objects stores a _reference_ to the type it wraps. Concrete example:
+        When calling rect.x, a SVGAnimatedPropertyTearOff<SVGLength> is created, that stores a pointer to the SVGRectElement, and a SVGNames::xAttr.
+        When calling rect.x.baseVal, a SVGPropertyTearOf<SVGLength> is created, that stores a reference to the "m_x" member variable of the SVGRectElement.
+        Any changes applied to the SVGLength object, through the wrapper, are immediately live, as no copies are involved anymore, nor the need to fire any callback methods.
+        This is the key concept of the new tear offs, no copies, no callbacks, no virtual methods (except one, needed for lists, but it's a detail).
+
+        The SVGAnimatedListPropertyTearOff and SVGListPropertyTearOff work the same, but for SVG*List objects. The whole SVG*List API is _removed_ from the SVG DOM classes
+        like SVGLengthList. It now inherits from Vector<SVGLength>, where it used to store a Vector<RefPtr<SVGListItem<SVGLength> > >. The SVGList API (insertItemBefore, appendItem, etc.)
+        is exposed through SVGListPropertyTearOff, and there's no need anymore for SVGLengthList to deal with it at all.
+        SVGLengthList is live just like most other SVG DOM object. Concrete example:
+        var item0 = text.x.baseVal.getItem(0); item0.value += 150;
+
+        Previously we chose to store a refcounted SVGListItem object, which wrapped the SVGLength object, to achieve liveness. We could change a single list item from DOM
+        w/o copying the whole list. The drawback is that a simple type likeSVGLengthList, was heavy to store, as it contained a list of RefPtrs around a wrapper object
+        around the real object 'SVGLength'. This complexity is completly gone.
+
+        The SVGListPropertyTearOff<SVGLengthList> stores a reference to the SVGLengthList object (eg. SVGTextElement::m_x) and maintains a list of SVGPropertyTearOff<SVGLength>
+        wrappers, that are created when necessary (getItem(2), will create a wrapper around the third list item), and cached. These SVGPropertyTearOff<SVGLength> objects
+        store references to the SVGLength object _in the SVGLengthList_. One has to be extra carefully, to keep those lists synchronized.
+        The SVGLengthList API is fully implemented for the first time, including moving items between lists, and is extensively tested with 8 new testcases.
+
+        This patch only changed SVGLength/SVGLengthList to the new concept. All other types remain using the old DeprecatedSVGAnimatedProperty* concept.
+        This will change in follow-up patches.
+
+        * GNUmakefile.am: Add new files from svg/properties to build.
+        * WebCore.gypi: Ditto.
+        * WebCore.pro: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * bindings/js/JSSVGLengthCustom.cpp: Adapt to context cache removal for SVGLength.
+        (WebCore::JSSVGLength::value):
+        (WebCore::JSSVGLength::convertToSpecifiedUnits):
+        * bindings/scripts/CodeGenerator.pm: Add new isSVGNewStyleAnimatedProperty() helper method, return true for "SVGAnimatedLength" and "SVGAnimatedLengthList".
+        * bindings/scripts/CodeGeneratorJS.pm: Generate new style SVG JS bindings, that don't need JSSVGContextCache / JSSVGPODTypeWrapper.
+        * bindings/scripts/CodeGeneratorObjC.pm: Ditto. (+ Finally expose a working set of SVG DOM API for Objective C).
+        * bindings/scripts/CodeGeneratorV8.pm: Ditto.
+        * bindings/v8/custom/V8SVGLengthCustom.cpp: Adapt to context cache removal for SVGLength.
+        (WebCore::V8SVGLength::valueAccessorGetter):
+        (WebCore::V8SVGLength::convertToSpecifiedUnitsCallback):
+        * rendering/svg/SVGTextLayoutAttributesBuilder.cpp:
+        (WebCore::extractFloatValuesFromSVGLengthList): SVGLengthList is a POD type now, passed as const reference.
+        * svg/DeprecatedSVGAnimatedPropertyTraits.h: Remove handling for SVGLength/SVGLengthList, those are converted to the new SVGAnimatedProperty design now.
+        * svg/DeprecatedSVGAnimatedTemplate.h: Ditto.
+        * svg/SVGAnimatedLength.h: Added.
+        * svg/SVGAnimatedLength.idl: Mark as [SVGAnimatedProperty].
+        * svg/SVGAnimatedLengthList.h: Added.
+        * svg/SVGAnimatedLengthList.idl: Mark as [SVGAnimatedProperty].
+        * svg/SVGCircleElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_PROPERTY_NEW/ until the transition to the new concept is finished.
+        * svg/SVGCursorElement.h: Ditto.
+        * svg/SVGEllipseElement.h: Ditto.
+        * svg/SVGFilterElement.h: Ditto.
+        * svg/SVGFilterPrimitiveStandardAttributes.h: Ditto.
+        * svg/SVGForeignObjectElement.h: Ditto.
+        * svg/SVGImageElement.h: Ditto.
+        * svg/SVGLength.idl: Mark as [SVGProperty].
+        * svg/SVGLengthList.cpp: Use Vector API (appendItem -> append). No need to ever use the SVGList API internally. SVGLengthList is a Vector<SVGLength> now.
+        (WebCore::SVGLengthList::parse): 
+        (WebCore::SVGLengthList::valueAsString):
+        * svg/SVGLengthList.h: Inherit from Vector<SVGLength> - not from the SVGList base class. It's a simple, non-refcounted POD type now.
+        (WebCore::SVGLengthList::SVGLengthList):
+        * svg/SVGLengthList.idl: Mark as [SVGListProperty].
+        * svg/SVGLineElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_PROPERTY_NEW/ until the transition to the new concept is finished.
+        * svg/SVGLinearGradientElement.h: Ditto.
+        * svg/SVGMarkerElement.h: Ditto.
+        * svg/SVGMaskElement.h: Ditto.
+        * svg/SVGPatternElement.h: Ditto.
+        * svg/SVGRadialGradientElement.h: Ditto.
+        * svg/SVGRectElement.h: Ditto.
+        * svg/SVGSVGElement.h: Ditto.
+        * svg/SVGSVGElement.idl: Mark createSVGLength() as [SVGLiveProperty] - a wrapper for the returned object has to be created.
+        * svg/SVGTextContentElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_PROPERTY_NEW/ until the transition to the new concept is finished.
+        * svg/SVGTextPathElement.h: Ditto.
+        * svg/SVGTextPositioningElement.cpp:
+        (WebCore::SVGTextPositioningElement::SVGTextPositioningElement):
+        (WebCore::SVGTextPositioningElement::parseMappedAttribute): Detach wrappers pointing to the old x/y/dx/dy list, if the underlying list changes via XML DOM.
+        (WebCore::listContainsRelativeValue): Adapt to SVGLengthList interface changes, it's a POD type now.
+        * svg/SVGTextPositioningElement.h: s/DECLARE_ANIMATED_PROPERTY/DECLARE_ANIMATED_LIST_PROPERTY_NEW/ until the transition to the new concept is finished.
+        * svg/SVGUseElement.h:
+        * svg/properties/SVGAnimatedListPropertyTearOff.h: Added.
+        * svg/properties/SVGAnimatedProperty.h: Added. This is the base class for SVGAnimatedPropertyTearOff and SVGAnimatedListPropertyTearOff.
+        * svg/properties/SVGAnimatedPropertyDescription.h: Added. Refactored from DeprecatedSVGAnimatedProperty.h.
+        * svg/properties/SVGAnimatedPropertyMacros.h: Added. These macros will be _removed_ as soon as the transition to the new concept is finished.
+        * svg/properties/SVGAnimatedPropertyTearOff.h: Added.
+        * svg/properties/SVGListPropertyTearOff.h: Added.
+        * svg/properties/SVGProperty.h: Added. This is the base class for SVGPropertyTearOff and SVGListPropertyTearOff.
+        * svg/properties/SVGPropertyTearOff.h: Added.
+        * svg/properties/SVGPropertyTraits.h: Added.
+
 2010-10-21  Alex Milowski  <alex@milowski.com>
 
         Reviewed by Kenneth Rohde Christiansen.
index b057051..1f25500 100644 (file)
@@ -3007,7 +3007,16 @@ webcore_sources += \
        WebCore/svg/graphics/SVGImage.h \
        WebCore/svg/LinearGradientAttributes.h \
        WebCore/svg/PatternAttributes.h \
+       WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h \
+       WebCore/svg/properties/SVGAnimatedProperty.h \
+       WebCore/svg/properties/SVGAnimatedPropertyDescription.h \
+       WebCore/svg/properties/SVGAnimatedPropertyMacros.h \
        WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h \
+       WebCore/svg/properties/SVGAnimatedPropertyTearOff.h \
+       WebCore/svg/properties/SVGListPropertyTearOff.h \
+       WebCore/svg/properties/SVGProperty.h \
+       WebCore/svg/properties/SVGPropertyTearOff.h \
+       WebCore/svg/properties/SVGPropertyTraits.h \
        WebCore/svg/RadialGradientAttributes.h \
        WebCore/svg/SVGAElement.cpp \
        WebCore/svg/SVGAElement.h \
@@ -3017,6 +3026,8 @@ webcore_sources += \
        WebCore/svg/SVGAngle.h \
        WebCore/svg/SVGAnimateColorElement.cpp \
        WebCore/svg/SVGAnimateColorElement.h \
+       WebCore/svg/SVGAnimatedLength.h \
+       WebCore/svg/SVGAnimatedLengthList.h \
        WebCore/svg/SVGAnimatedPathData.cpp \
        WebCore/svg/SVGAnimatedPathData.h \
        WebCore/svg/SVGAnimatedPoints.cpp \
index 166c4d1..705a430 100644 (file)
             'svg/graphics/SVGImage.cpp',
             'svg/graphics/SVGImage.h',
             'svg/properties/SVGAnimatedPropertySynchronizer.h',
+            'svg/properties/SVGAnimatedListPropertyTearOff.h',
+            'svg/properties/SVGAnimatedProperty.h',
+            'svg/properties/SVGAnimatedPropertyDescription.h',
+            'svg/properties/SVGAnimatedPropertyMacros.h',
+            'svg/properties/SVGAnimatedPropertySynchronizer.h',
+            'svg/properties/SVGAnimatedPropertyTearOff.h',
+            'svg/properties/SVGListPropertyTearOff.h',
+            'svg/properties/SVGProperty.h',
+            'svg/properties/SVGPropertyTearOff.h',
+            'svg/properties/SVGPropertyTraits.h',
             'svg/ColorDistance.cpp',
             'svg/ColorDistance.h',
             'svg/DeprecatedSVGAnimatedProperty.h',
             'svg/SVGAnimateMotionElement.h',
             'svg/SVGAnimateTransformElement.cpp',
             'svg/SVGAnimateTransformElement.h',
+            'svg/SVGAnimatedLength.h',
+            'svg/SVGAnimatedLengthList.h',
             'svg/SVGAnimatedPathData.cpp',
             'svg/SVGAnimatedPathData.h',
             'svg/SVGAnimatedPoints.cpp',
index b73061e..b6ac4ae 100644 (file)
@@ -2343,11 +2343,22 @@ HEADERS += \
     svg/graphics/filters/SVGFilterBuilder.h \
     svg/graphics/filters/SVGFilter.h \
     svg/graphics/SVGImage.h \
+    svg/properties/SVGAnimatedListPropertyTearOff.h \
+    svg/properties/SVGAnimatedProperty.h \
+    svg/properties/SVGAnimatedPropertyDescription.h \
+    svg/properties/SVGAnimatedPropertyMacros.h \
     svg/properties/SVGAnimatedPropertySynchronizer.h \
+    svg/properties/SVGAnimatedPropertyTearOff.h \
+    svg/properties/SVGListPropertyTearOff.h \
+    svg/properties/SVGProperty.h \
+    svg/properties/SVGPropertyTearOff.h \
+    svg/properties/SVGPropertyTraits.h \
     svg/SVGAElement.h \
     svg/SVGAltGlyphElement.h \
     svg/SVGAngle.h \
     svg/SVGAnimateColorElement.h \
+    svg/SVGAnimatedLength.h \
+    svg/SVGAnimatedLengthList.h \
     svg/SVGAnimatedPathData.h \
     svg/SVGAnimatedPoints.h \
     svg/SVGAnimateElement.h \
index 0642a0b..fd9421c 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\svg\SVGAnimatedLength.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\svg\SVGAnimatedLengthList.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\svg\SVGAnimatedPathData.h"\r
                                >\r
                        </File>\r
                                Name="properties"\r
                                >\r
                                <File\r
+                               RelativePath="..\svg\properties\SVGAnimatedListPropertyTearOff.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGAnimatedProperty.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGAnimatedPropertyDescription.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGAnimatedPropertyMacros.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                RelativePath="..\svg\properties\SVGAnimatedPropertySynchronizer.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGAnimatedPropertyTearOff.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGListPropertyTearOff.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGProperty.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGPropertyTearOff.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                               RelativePath="..\svg\properties\SVGPropertyTraits.h"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                </Filter>\r
                <Filter\r
index bc612df..5bc440b 100644 (file)
                088451160F267B63007F139E /* WMLInputElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 088451140F267B63007F139E /* WMLInputElement.h */; };
                0885067F11DA045B00182B98 /* PaintInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0885067D11DA045B00182B98 /* PaintInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0885068011DA045B00182B98 /* PaintPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0885067E11DA045B00182B98 /* PaintPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E04126EF1DB00978F7A /* SVGAnimatedListPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0DFB126EF1DB00978F7A /* SVGAnimatedListPropertyTearOff.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E05126EF1DB00978F7A /* SVGAnimatedProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0DFC126EF1DB00978F7A /* SVGAnimatedProperty.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E06126EF1DB00978F7A /* SVGAnimatedPropertyDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0DFD126EF1DB00978F7A /* SVGAnimatedPropertyDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E07126EF1DB00978F7A /* SVGAnimatedPropertyMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0DFE126EF1DB00978F7A /* SVGAnimatedPropertyMacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E08126EF1DB00978F7A /* SVGAnimatedPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0DFF126EF1DB00978F7A /* SVGAnimatedPropertyTearOff.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E09126EF1DB00978F7A /* SVGListPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0E00126EF1DB00978F7A /* SVGListPropertyTearOff.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E0A126EF1DB00978F7A /* SVGProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0E01126EF1DB00978F7A /* SVGProperty.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E0B126EF1DB00978F7A /* SVGPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0E02126EF1DB00978F7A /* SVGPropertyTearOff.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               088A0E0C126EF1DB00978F7A /* SVGPropertyTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 088A0E03126EF1DB00978F7A /* SVGPropertyTraits.h */; settings = {ATTRIBUTES = (Private, ); }; };
                088C2F7912390081003D65CE /* SVGTextLayoutAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 088C2F7512390080003D65CE /* SVGTextLayoutAttributes.cpp */; };
                088C2F7A12390081003D65CE /* SVGTextLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 088C2F7612390080003D65CE /* SVGTextLayoutAttributes.h */; };
                088C97120ECB6D92000534BA /* WMLNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CA3AB490E556F2400E9C0C0 /* WMLNames.cpp */; };
                088C976D0ECB6E29000534BA /* WMLPageState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0893E4660ECB68F400A28563 /* WMLPageState.h */; };
                088C976E0ECB6E29000534BA /* WMLPElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6B99350E52E37300487BB7 /* WMLPElement.cpp */; };
                088C976F0ECB6E29000534BA /* WMLPElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6B99360E52E37300487BB7 /* WMLPElement.h */; };
+               089021A9126EF5DE0092D5EA /* SVGAnimatedLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 089021A8126EF5DE0092D5EA /* SVGAnimatedLength.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               089021AD126EF5E90092D5EA /* SVGAnimatedLengthList.h in Headers */ = {isa = PBXBuildFile; fileRef = 089021AC126EF5E90092D5EA /* SVGAnimatedLengthList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                089582550E857A7E00F82C83 /* ImageLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 089582530E857A7E00F82C83 /* ImageLoader.cpp */; };
                089582560E857A7E00F82C83 /* ImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 089582540E857A7E00F82C83 /* ImageLoader.h */; };
                0897C14C0ED2EBA500AE06DB /* WMLBRElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0897C14A0ED2EBA400AE06DB /* WMLBRElement.cpp */; };
                088451140F267B63007F139E /* WMLInputElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLInputElement.h; sourceTree = "<group>"; };
                0885067D11DA045B00182B98 /* PaintInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PaintInfo.h; sourceTree = "<group>"; };
                0885067E11DA045B00182B98 /* PaintPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PaintPhase.h; sourceTree = "<group>"; };
+               088A0DFB126EF1DB00978F7A /* SVGAnimatedListPropertyTearOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedListPropertyTearOff.h; sourceTree = "<group>"; };
+               088A0DFC126EF1DB00978F7A /* SVGAnimatedProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedProperty.h; sourceTree = "<group>"; };
+               088A0DFD126EF1DB00978F7A /* SVGAnimatedPropertyDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertyDescription.h; sourceTree = "<group>"; };
+               088A0DFE126EF1DB00978F7A /* SVGAnimatedPropertyMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertyMacros.h; sourceTree = "<group>"; };
+               088A0DFF126EF1DB00978F7A /* SVGAnimatedPropertyTearOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertyTearOff.h; sourceTree = "<group>"; };
+               088A0E00126EF1DB00978F7A /* SVGListPropertyTearOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGListPropertyTearOff.h; sourceTree = "<group>"; };
+               088A0E01126EF1DB00978F7A /* SVGProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGProperty.h; sourceTree = "<group>"; };
+               088A0E02126EF1DB00978F7A /* SVGPropertyTearOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPropertyTearOff.h; sourceTree = "<group>"; };
+               088A0E03126EF1DB00978F7A /* SVGPropertyTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPropertyTraits.h; sourceTree = "<group>"; };
                088C2F7512390080003D65CE /* SVGTextLayoutAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGTextLayoutAttributes.cpp; sourceTree = "<group>"; };
                088C2F7612390080003D65CE /* SVGTextLayoutAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGTextLayoutAttributes.h; sourceTree = "<group>"; };
+               089021A8126EF5DE0092D5EA /* SVGAnimatedLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedLength.h; sourceTree = "<group>"; };
+               089021AC126EF5E90092D5EA /* SVGAnimatedLengthList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedLengthList.h; sourceTree = "<group>"; };
                0893E4650ECB68F400A28563 /* WMLPageState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLPageState.cpp; sourceTree = "<group>"; };
                0893E4660ECB68F400A28563 /* WMLPageState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLPageState.h; sourceTree = "<group>"; };
                089582530E857A7E00F82C83 /* ImageLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageLoader.cpp; sourceTree = "<group>"; };
                081CDFBD126ECFE800D215CA /* properties */ = {
                        isa = PBXGroup;
                        children = (
+                               088A0DFB126EF1DB00978F7A /* SVGAnimatedListPropertyTearOff.h */,
+                               088A0DFC126EF1DB00978F7A /* SVGAnimatedProperty.h */,
+                               088A0DFD126EF1DB00978F7A /* SVGAnimatedPropertyDescription.h */,
+                               088A0DFE126EF1DB00978F7A /* SVGAnimatedPropertyMacros.h */,
                                081CDFBE126ECFE800D215CA /* SVGAnimatedPropertySynchronizer.h */,
+                               088A0DFF126EF1DB00978F7A /* SVGAnimatedPropertyTearOff.h */,
+                               088A0E00126EF1DB00978F7A /* SVGListPropertyTearOff.h */,
+                               088A0E01126EF1DB00978F7A /* SVGProperty.h */,
+                               088A0E02126EF1DB00978F7A /* SVGPropertyTearOff.h */,
+                               088A0E03126EF1DB00978F7A /* SVGPropertyTraits.h */,
                        );
                        path = properties;
                        sourceTree = "<group>";
                                B22277E70D00BF1F0071B782 /* SVGAnimatedBoolean.idl */,
                                B22277E80D00BF1F0071B782 /* SVGAnimatedEnumeration.idl */,
                                B22277E90D00BF1F0071B782 /* SVGAnimatedInteger.idl */,
+                               089021A8126EF5DE0092D5EA /* SVGAnimatedLength.h */,
                                B22277EA0D00BF1F0071B782 /* SVGAnimatedLength.idl */,
+                               089021AC126EF5E90092D5EA /* SVGAnimatedLengthList.h */,
                                B22277EB0D00BF1F0071B782 /* SVGAnimatedLengthList.idl */,
                                B22277EC0D00BF1F0071B782 /* SVGAnimatedNumber.idl */,
                                B22277ED0D00BF1F0071B782 /* SVGAnimatedNumberList.idl */,
                                081CDFB9126ECFDB00D215CA /* DeprecatedSVGAnimatedPropertyTraits.h in Headers */,
                                081CDFBA126ECFDB00D215CA /* DeprecatedSVGAnimatedTemplate.h in Headers */,
                                081CDFBF126ECFE800D215CA /* SVGAnimatedPropertySynchronizer.h in Headers */,
+                               088A0E04126EF1DB00978F7A /* SVGAnimatedListPropertyTearOff.h in Headers */,
+                               088A0E05126EF1DB00978F7A /* SVGAnimatedProperty.h in Headers */,
+                               088A0E06126EF1DB00978F7A /* SVGAnimatedPropertyDescription.h in Headers */,
+                               088A0E07126EF1DB00978F7A /* SVGAnimatedPropertyMacros.h in Headers */,
+                               088A0E08126EF1DB00978F7A /* SVGAnimatedPropertyTearOff.h in Headers */,
+                               088A0E09126EF1DB00978F7A /* SVGListPropertyTearOff.h in Headers */,
+                               088A0E0A126EF1DB00978F7A /* SVGProperty.h in Headers */,
+                               088A0E0B126EF1DB00978F7A /* SVGPropertyTearOff.h in Headers */,
+                               088A0E0C126EF1DB00978F7A /* SVGPropertyTraits.h in Headers */,
+                               089021A9126EF5DE0092D5EA /* SVGAnimatedLength.h in Headers */,
+                               089021AD126EF5E90092D5EA /* SVGAnimatedLengthList.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXProject;
                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
                        compatibilityVersion = "Xcode 2.4";
-                       developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
index c7cfdb0..cb5e879 100644 (file)
 #if ENABLE(SVG)
 #include "JSSVGLength.h"
 
+#include "SVGAnimatedProperty.h"
+
 using namespace JSC;
 
 namespace WebCore {
 
 JSValue JSSVGLength::value(ExecState* exec) const
 {
-    JSSVGPODTypeWrapper<SVGLength>* imp = impl();
-    SVGElement* context = JSSVGContextCache::svgContextForDOMObject(const_cast<JSSVGLength*>(this));
-
-    SVGLength podImp(*imp);
-    return jsNumber(exec, podImp.value(context));
+    SVGLength& podImp = impl()->propertyReference();
+    return jsNumber(exec, podImp.value(impl()->contextElement()));
 }
 
 JSValue JSSVGLength::convertToSpecifiedUnits(ExecState* exec)
 {
-    JSSVGPODTypeWrapper<SVGLength>* imp = impl();
-    SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this);
-
-    SVGLength podImp(*imp);
-    podImp.convertToSpecifiedUnits(exec->argument(0).toInt32(exec), context);
+    SVGLength& podImp = impl()->propertyReference();
+    podImp.convertToSpecifiedUnits(exec->argument(0).toInt32(exec), impl()->contextElement());
 
-    imp->commitChange(podImp, this);
+    impl()->commitChange();
     return jsUndefined();
 }
 
index ec762b6..cbf0cbd 100644 (file)
@@ -50,11 +50,13 @@ my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1
                          "Date" => 1);
 
 my %podTypeHash = ("SVGNumber" => 1, "SVGTransform" => 1);
-my %podTypesWithWritablePropertiesHash = ("SVGAngle" => 1, "SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1);
+my %podTypesWithWritablePropertiesHash = ("SVGAngle" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1);
 my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1);
 
 my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1, "SVGPaintType" => 1);
 
+my %svgNewStyleAnimatedTypeHash = ("SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1);
+
 my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1,
                            "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1,
                            "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1,
@@ -327,6 +329,16 @@ sub IsNonPointerType
     return 0;
 }
 
+# FIXME: This method will go away once all SVG animated properties are converted to the new scheme.
+sub IsSVGNewStyleAnimatedType
+{
+    my $object = shift;
+    my $type = shift;
+
+    return 1 if $svgNewStyleAnimatedTypeHash{$type};
+    return 0;
+}
+
 sub IsSVGAnimatedType
 {
     my $object = shift;
index fe29b80..0b56f13 100644 (file)
@@ -330,7 +330,9 @@ sub IsSVGTypeNeedingContextParameter
 
     return 0 unless $implClassName =~ /SVG/;
     return 0 if $implClassName =~ /Element/;
-    my @noContextNeeded = ("SVGPaint", "SVGColor", "SVGDocument", "SVGZoomEvent");
+    return 0 if $codeGenerator->IsSVGNewStyleAnimatedType($implClassName);
+
+    my @noContextNeeded = ("SVGLength", "SVGLengthList", "SVGPaint", "SVGColor", "SVGDocument", "SVGZoomEvent");
     foreach (@noContextNeeded) {
         return 0 if $implClassName eq $_;
     }
@@ -672,12 +674,36 @@ sub GenerateHeader
     $headerIncludes{"SVGElement.h"} = 1 if $className =~ /^JSSVG/;
 
     # Get correct pass/store types respecting PODType flag
-    my $podType = $dataNode->extendedAttributes->{"PODType"};
-    my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
+    my $implType = $implClassName;
 
-    $headerIncludes{"$podType.h"} = 1 if $podType and $podType ne "float";
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};    
+    if ($svgPropertyType) {
+        $implType = "SVGPropertyTearOff<$svgPropertyType> ";
+        $headerIncludes{"SVGAnimatedProperty.h"} = 1;
+        $headerIncludes{"SVGPropertyTearOff.h"} = 1;
+        $headerIncludes{"$svgPropertyType.h"} = 1 if $svgPropertyType ne "float";
+    }
 
-    $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1 if $podType;
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};    
+    if ($svgListPropertyType) {
+        $implType = "SVGListPropertyTearOff<$svgListPropertyType> ";
+        $headerIncludes{"SVGAnimatedProperty.h"} = 1;
+        $headerIncludes{"SVGListPropertyTearOff.h"} = 1;
+        $headerIncludes{"$svgListPropertyType.h"} = 1;
+    }
+
+    # FIXME: Old style SVG JS bindings, will vanish soon.
+    my $podType = $dataNode->extendedAttributes->{"PODType"};
+    if ($podType) {
+        $implType = "JSSVGPODTypeWrapper<$podType> ";
+        $headerIncludes{"$podType.h"} = 1 if $podType ne "float";
+        $headerIncludes{"JSSVGPODTypeWrapper.h"} = 1;
+    }
+
+    my $svgPropertyOrPodType;
+    $svgPropertyOrPodType = $podType if $podType;
+    $svgPropertyOrPodType = $svgPropertyType if $svgPropertyType;
+    $svgPropertyOrPodType = $svgListPropertyType if $svgListPropertyType;
 
     my $numConstants = @{$dataNode->constants};
     my $numAttributes = @{$dataNode->attributes};
@@ -685,8 +711,11 @@ sub GenerateHeader
 
     push(@headerContent, "\nnamespace WebCore {\n\n");
 
+    my $svgAnimatedPropertyType = $dataNode->extendedAttributes->{"SVGAnimatedProperty"};   
+    $headerIncludes{"$implClassName.h"} = 1 if $svgAnimatedPropertyType;
+
     # Implementation class forward declaration
-    AddClassForwardIfNeeded($implClassName) unless $podType;
+    AddClassForwardIfNeeded($implClassName) unless $svgPropertyOrPodType or $svgAnimatedPropertyType;
     AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
 
     # Class declaration
@@ -875,8 +904,6 @@ sub GenerateHeader
     }
 
     if (!$hasParent) {
-        # Extra space after JSSVGPODTypeWrapper<> to make RefPtr<Wrapper<> > compile.
-        my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
         push(@headerContent, "    $implType* impl() const { return m_impl.get(); }\n\n");
         push(@headerContent, "private:\n");
         push(@headerContent, "    RefPtr<$implType> m_impl;\n");
@@ -936,7 +963,9 @@ sub GenerateHeader
 
     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {
         if ($podType) {
-            push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, JSSVGPODTypeWrapper<$podType>*, SVGElement*);\n");
+            push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement*);\n");
+        } elsif ($svgPropertyType) {
+            push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*);\n");
         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
             push(@headerContent, "JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, $implType*, SVGElement* context);\n");
         } else {
@@ -944,12 +973,13 @@ sub GenerateHeader
         }
     }
     if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
+
         if ($podType) {
             push(@headerContent, "$podType to${interfaceName}(JSC::JSValue);\n");
         } elsif ($interfaceName eq "NodeFilter") {
             push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue);\n");
         } else {
-            push(@headerContent, "$implClassName* to${interfaceName}(JSC::JSValue);\n");
+            push(@headerContent, "$implType* to${interfaceName}(JSC::JSValue);\n");
         }
     }
     if ($usesToJSNewlyCreated{$interfaceName}) {
@@ -1415,8 +1445,22 @@ sub GenerateImplementation
     push(@implContent, "};\n\n");
 
     # Get correct pass/store types respecting PODType flag
+    my $implType = $implClassName;
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};    
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};    
     my $podType = $dataNode->extendedAttributes->{"PODType"};
-    my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
+    if ($svgPropertyType) {
+        $implType = "SVGPropertyTearOff<$svgPropertyType> ";
+    } elsif ($svgListPropertyType) {
+        $implType = "SVGListPropertyTearOff<$svgListPropertyType> ";
+    } elsif ($podType) {
+        $implType = "JSSVGPODTypeWrapper<$podType> ";
+    }
+
+    my $svgPropertyOrPodType;
+    $svgPropertyOrPodType = $podType if $podType;
+    $svgPropertyOrPodType = $svgPropertyType if $svgPropertyType;
+    $svgPropertyOrPodType = $svgListPropertyType if $svgListPropertyType;
 
     # Constructor
     if ($interfaceName eq "DOMWindow") {
@@ -1540,7 +1584,7 @@ sub GenerateImplementation
                 push(@implContent, "    ${className}* castedThis = static_cast<$className*>(asObject(slotBase));\n");
 
                 my $implClassNameForValueConversion = "";
-                if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
+                if (!$svgPropertyOrPodType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
                     $implClassNameForValueConversion = $implClassName;
                 }
 
@@ -1592,9 +1636,13 @@ sub GenerateImplementation
                         push(@implContent, "    if (JSValue cachedValue = castedThis->getAnonymousValue(" . $className . "::" . $attribute->signature->name . "Slot))\n");
                         push(@implContent, "        return cachedValue;\n");
                     }
-                    if ($podType) {
-                        push(@implContent, "    $podType imp(*castedThis->impl());\n");
-                        if ($podType eq "float") { # Special case for JSSVGNumber
+
+                    if ($svgListPropertyType) {
+                        push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "castedThis->impl()->$implGetterFunctionName()", "castedThis") . ";\n");
+                    } elsif ($svgPropertyOrPodType) {
+                        push(@implContent, "    $svgPropertyOrPodType imp(*castedThis->impl());\n") if $podType;
+                        push(@implContent, "    $svgPropertyOrPodType& imp = castedThis->impl()->propertyReference();\n") if !$podType;
+                        if ($svgPropertyOrPodType eq "float") { # Special case for JSSVGNumber
                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "castedThis") . ";\n");
                         } else {
                             push(@implContent, "    JSValue result =  " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "castedThis") . ";\n");
@@ -1605,7 +1653,12 @@ sub GenerateImplementation
                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
                         if ($codeGenerator->IsSVGAnimatedType($type)) {
                             push(@implContent, "    RefPtr<$type> obj = $jsType;\n");
-                            push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);\n");
+
+                            if ($codeGenerator->IsSVGNewStyleAnimatedType($type)) {
+                                push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get());\n");
+                            } else {
+                                push(@implContent, "    JSValue result =  toJS(exec, castedThis->globalObject(), obj.get(), imp);\n");
+                            }
                         } else {
                             push(@implContent, "    JSValue result = $jsType;\n");
                         }
@@ -1616,8 +1669,8 @@ sub GenerateImplementation
 
                 } else {
                     push(@implContent, "    ExceptionCode ec = 0;\n");                    
-                    if ($podType) {
-                        push(@implContent, "    $podType imp(*castedThis->impl());\n");
+                    if ($svgPropertyOrPodType) {
+                        push(@implContent, "    $svgPropertyOrPodType imp(*castedThis->impl());\n");
                         push(@implContent, "    JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "castedThis") . ";\n");
                     } else {
                         push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
@@ -1749,14 +1802,16 @@ sub GenerateImplementation
                         } else {
                             push(@implContent, "    $className* castedThis = static_cast<$className*>(thisObject);\n");
                             push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");
-                            if ($podType) {
-                                push(@implContent, "    $podType podImp(*imp);\n");
-                                if ($podType eq "float") { # Special case for JSSVGNumber
+                            if ($svgPropertyOrPodType) {
+                                push(@implContent, "    $svgPropertyOrPodType podImp(*imp);\n") if $podType;
+                                push(@implContent, "    $svgPropertyOrPodType& podImp = imp->propertyReference();\n") if !$podType;
+                                if ($svgPropertyOrPodType eq "float") { # Special case for JSSVGNumber
                                     push(@implContent, "    podImp = " . JSValueToNative($attribute->signature, "value") . ";\n");
                                 } else {
                                     push(@implContent, "    podImp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n");
                                 }
-                                push(@implContent, "    imp->commitChange(podImp, castedThis);\n");
+                                push(@implContent, "    imp->commitChange(podImp, castedThis);\n") if $podType;
+                                push(@implContent, "    imp->commitChange();\n") if $svgPropertyType;
                             } else {
                                 my $nativeValue = JSValueToNative($attribute->signature, "value");
                                 my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
@@ -1848,7 +1903,7 @@ sub GenerateImplementation
             # classes, we directly forward the calls to JSSVGPODListCustom, which centralizes the otherwise
             # duplicated code for the JSSVG*List classes mentioned above.
             my $svgPODListType;
-            if ($implClassName =~ /SVG.*List/) {
+            if ($implClassName =~ /SVG.*List/ and !$svgListPropertyType) {
                 $svgPODListType = $implClassName;
                 $svgPODListType =~ s/List$//;
                 $svgPODListType = "" unless $codeGenerator->IsPodType($svgPODListType);
@@ -1867,7 +1922,8 @@ sub GenerateImplementation
                                  . ">(castedThis, exec, to" . $svgPODListType . "));\n");
             } else {
                 push(@implContent, "    $implType* imp = static_cast<$implType*>(castedThis->impl());\n");
-                push(@implContent, "    $podType podImp(*imp);\n") if $podType;
+                push(@implContent, "    $svgPropertyOrPodType podImp(*imp);\n") if $podType;
+                push(@implContent, "    $svgPropertyOrPodType& podImp = imp->propertyReference();\n") if !$podType and $svgPropertyType;
 
                 my $numParameters = @{$function->parameters};
 
@@ -1906,8 +1962,7 @@ sub GenerateImplementation
                 } else {
                     my $argsIndex = 0;
                     my $paramIndex = 0;
-                    my $functionString = ($podType ? "podImp." : "imp->") . $functionImplementationName . "(";
-
+                    my $functionString = (($svgPropertyOrPodType and !$svgListPropertyType) ? "podImp." : "imp->") . $functionImplementationName . "(";
                     my $hasOptionalArguments = 0;
 
                     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
@@ -1948,7 +2003,7 @@ sub GenerateImplementation
                                 $hasOptionalArguments = 1;
                             }
                             push(@implContent, "    if (argsCount <= $argsIndex) {\n");
-                            GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $podType, $implClassName);
+                            GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2, $podType, $svgPropertyType, $implClassName);
                             push(@implContent, "    }\n\n");
                         }
 
@@ -2032,7 +2087,7 @@ sub GenerateImplementation
                     }
 
                     push(@implContent, "\n");
-                    GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $podType, $implClassName);
+                    GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    ", $podType, $svgPropertyType, $implClassName);
                 }
             }
             push(@implContent, "}\n\n");
@@ -2091,16 +2146,18 @@ sub GenerateImplementation
     }
 
     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
-        if ($podType) {
-            push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n");
-        } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
+        if ($svgPropertyType) {
+            push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n");
+        } elsif ($podType or IsSVGTypeNeedingContextParameter($implClassName)) {
             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object, SVGElement* context)\n");
         } else {
             push(@implContent, "JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, $implType* object)\n");
         }
         push(@implContent, "{\n");
-        if ($podType) {
-            push(@implContent, "    return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, globalObject, object, context);\n");
+        if ($svgPropertyType) {
+            push(@implContent, "    return getDOMObjectWrapper<$className, $implType>(exec, globalObject, object);\n");
+        } elsif ($podType) {
+            push(@implContent, "    return getDOMObjectWrapper<$className, $implType>(exec, globalObject, object, context);\n");
         } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
             push(@implContent, "    return getDOMObjectWrapper<$className>(exec, globalObject, object, context);\n");
         } else {
@@ -2112,18 +2169,15 @@ sub GenerateImplementation
     if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
         if ($podType) {
             push(@implContent, "$podType to${interfaceName}(JSC::JSValue value)\n");
+            push(@implContent, "{\n");
+            push(@implContent, "    return value.inherits(&${className}::s_info) ? ($podType) *static_cast<$className*>(asObject(value))->impl() : $podType()");
         } else {
-            push(@implContent, "$implClassName* to${interfaceName}(JSC::JSValue value)\n");
+            push(@implContent, "$implType* to${interfaceName}(JSC::JSValue value)\n");
+            push(@implContent, "{\n");
+            push(@implContent, "    return value.inherits(&${className}::s_info) ? static_cast<$className*>(asObject(value))->impl() : 0");
         }
 
-        push(@implContent, "{\n");
-
-        push(@implContent, "    return value.inherits(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : ");
-        if ($podType and $podType ne "float") {
-            push(@implContent, "$podType();\n}\n");
-        } else {
-            push(@implContent, "0;\n}\n");
-        }
+        push(@implContent, ";\n}\n");
     }
 
     push(@implContent, "\n}\n");
@@ -2298,6 +2352,7 @@ sub GenerateImplementationFunctionCall()
     my $paramIndex = shift;
     my $indent = shift;
     my $podType = shift;
+    my $svgPropertyType = shift;
     my $implClassName = shift;
 
     if ($function->signature->extendedAttributes->{"CustomArgumentHandling"}) {
@@ -2316,6 +2371,7 @@ sub GenerateImplementationFunctionCall()
         push(@implContent, $indent . "$functionString;\n");
         push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
         push(@implContent, $indent . "imp->commitChange(podImp, castedThis);\n") if $podType;
+        push(@implContent, $indent . "imp->commitChange();\n") if $svgPropertyType;
         push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n");
     } else {
         push(@implContent, "\n" . $indent . "JSC::JSValue result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThis") . ";\n");
@@ -2358,7 +2414,7 @@ my %nativeType = (
     "SerializedScriptValue" => "RefPtr<SerializedScriptValue>",
     "IDBKey" => "RefPtr<IDBKey>",
     "SVGAngle" => "SVGAngle",
-    "SVGLength" => "SVGLength",
+    "SVGLength" => "SVGPropertyTearOff<SVGLength>*",
     "SVGMatrix" => "AffineTransform",
     "SVGNumber" => "float",
     "SVGPaintType" => "SVGPaint::SVGPaintType",
@@ -2509,6 +2565,12 @@ sub NativeToJSValue
         } else {
             return "toJS(exec, $globalObject, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), JSSVGContextCache::svgContextForDOMObject(castedThis));"
         }
+    } 
+
+    my $svgLivePropertyType = $signature->extendedAttributes->{"SVGLiveProperty"};
+    if ($svgLivePropertyType) {
+        $implIncludes{"JS$type.h"} = 1;
+        return "toJS(exec, $globalObject, SVGPropertyTearOff<$type>::create($value).get())";
     }
 
     if ($type eq "CSSStyleDeclaration") {
@@ -2550,6 +2612,15 @@ sub NativeToJSValue
         return "toJSNewlyCreated(exec, $globalObject, WTF::getPtr($value))";
     }
 
+    # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked.
+    if ($codeGenerator->IsSVGNewStyleAnimatedType($implClassName)) {
+        if ($implClassName =~ /List$/) {
+            $value = "static_cast<SVGListPropertyTearOff<$type>*>($value)";
+        } else {
+            $value = "static_cast<SVGPropertyTearOff<$type>*>($value)";
+        }
+    }
+
     return "toJS(exec, $globalObject, WTF::getPtr($value))";
 }
 
index 96f0446..0732627 100644 (file)
@@ -587,6 +587,12 @@ sub AddIncludesForType
         return;
     }
 
+    if ($codeGenerator->IsSVGNewStyleAnimatedType($type)) {
+        $implIncludes{"${type}.h"} = 1;
+        $implIncludes{"DOM${type}Internal.h"} = 1;
+        return;
+    }
+
     if ($codeGenerator->IsSVGAnimatedType($type)) {
         $implIncludes{"DeprecatedSVGAnimatedTemplate.h"} = 1;
         $implIncludes{"DOM${type}Internal.h"} = 1;
@@ -967,11 +973,32 @@ sub GenerateHeader
     unless ($isProtocol) {
         # Generate internal interfaces
         my $podType = $dataNode->extendedAttributes->{"PODType"};
+        my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};
+        my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};
+        my $podTypeWithNamespace;
+        my $svgPropertyTypeWithNamespace;
+        my $svgListPropertyTypeWithNamespace;
+        my $implClassName = GetImplClassName($interfaceName);
+        my $implClassNameWithNamespace = "WebCore::" . $implClassName;
 
+        my $implType = $implClassNameWithNamespace;
+        if ($podType) {
+            $podTypeWithNamespace = ($podType eq "float") ? "$podType" : "WebCore::$podType";
+        } elsif ($svgPropertyType) {
+            $implType = "WebCore::SVGPropertyTearOff<$implType>";
+            $svgPropertyTypeWithNamespace = ($svgPropertyType eq "float") ? "$svgPropertyType" : "WebCore::$svgPropertyType";
+        } elsif ($svgListPropertyType) {
+            $implType = "WebCore::SVGListPropertyTearOff<$implType>";
+            $svgListPropertyTypeWithNamespace = "WebCore::$svgListPropertyType";
+        }
         # Generate interface definitions. 
         @internalHeaderContent = split("\r", $implementationLicenseTemplate);
 
         push(@internalHeaderContent, "\n#import <WebCore/$className.h>\n\n");
+        push(@internalHeaderContent, "#import <WebCore/SVGAnimatedProperty.h>\n\n") if $svgPropertyType or $svgListPropertyType;
+        push(@internalHeaderContent, "#import <WebCore/SVGPropertyTearOff.h>\n\n") if $svgPropertyType;
+        push(@internalHeaderContent, "#import <WebCore/SVGListPropertyTearOff.h>\n\n") if $svgListPropertyType;
         push(@internalHeaderContent, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
 
         if ($interfaceName eq "Node") {
@@ -980,15 +1007,19 @@ sub GenerateHeader
 
         my $startedNamespace = 0;
 
-        my $implClassName = GetImplClassName($interfaceName);
-
-        if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
+        if ($codeGenerator->IsSVGNewStyleAnimatedType($interfaceName)) {
+            push(@internalHeaderContent, "#import <WebCore/$implClassName.h>\n\n");
+        } elsif ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
             push(@internalHeaderContent, "#import <WebCore/DeprecatedSVGAnimatedTemplate.h>\n\n");
         } else {
             push(@internalHeaderContent, "namespace WebCore {\n");
             $startedNamespace = 1;
             if ($podType and $podType ne "float") {
                 push(@internalHeaderContent, "    class $podType;\n");
+            } elsif ($svgPropertyType and $svgPropertyType ne "float") {
+                push(@internalHeaderContent, "    class $svgPropertyType;\n");
+            } elsif ($svgListPropertyType) {
+                push(@internalHeaderContent, "    class $svgListPropertyType;\n");
             } elsif ($interfaceName eq "Node") {
                 push(@internalHeaderContent, "    class EventTarget;\n    class Node;\n");
             } else {
@@ -998,27 +1029,15 @@ sub GenerateHeader
         }
 
         if ($podType) {
-            if ($podType eq "float") {
-                push(@internalHeaderContent, "float core($className *);\n");
-            } else {
-                push(@internalHeaderContent, "WebCore::$podType core($className *);\n");
-            }
+            push(@internalHeaderContent, "$podTypeWithNamespace core($className *);\n");
+            push(@internalHeaderContent, "$className *kit($podTypeWithNamespace);\n");
         } else {
-            push(@internalHeaderContent, "WebCore::$implClassName* core($className *);\n");
-        }
-
-        if ($podType) {
-            if ($podType eq "float") {
-                push(@internalHeaderContent, "$className *kit($podType);\n");
-            } else {
-                push(@internalHeaderContent, "$className *kit(WebCore::$podType);\n");
-            }
-        } else {
-            push(@internalHeaderContent, "$className *kit(WebCore::$implClassName*);\n");
+            push(@internalHeaderContent, "$implType* core($className *);\n");
+            push(@internalHeaderContent, "$className *kit($implType*);\n");
         }
 
         if ($dataNode->extendedAttributes->{Polymorphic}) {
-            push(@internalHeaderContent, "Class kitClass(WebCore::$implClassName*);\n");
+            push(@internalHeaderContent, "Class kitClass($implType*);\n");
         }
 
         if ($interfaceName eq "Node") {
@@ -1052,10 +1071,21 @@ sub GenerateImplementation
     my $numFunctions = @{$dataNode->functions};
 
     my $podType = $dataNode->extendedAttributes->{"PODType"};
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};
     my $podTypeWithNamespace;
+    my $svgPropertyTypeWithNamespace;
+    my $svgListPropertyTypeWithNamespace;
+    my $implType = $implClassNameWithNamespace;
 
     if ($podType) {
         $podTypeWithNamespace = ($podType eq "float") ? "$podType" : "WebCore::$podType";
+    } elsif ($svgPropertyType) {
+        $implType = "WebCore::SVGPropertyTearOff<$implType>";
+        $svgPropertyTypeWithNamespace = ($svgPropertyType eq "float") ? "$svgPropertyType" : "WebCore::$svgPropertyType";
+    } elsif ($svgListPropertyType) {
+        $implType = "WebCore::SVGListPropertyTearOff<$implType>";
+        $svgListPropertyTypeWithNamespace = "WebCore::$svgListPropertyType";
     }
 
     # - Add default header template.
@@ -1086,7 +1116,7 @@ sub GenerateImplementation
 
     $implIncludes{"DOMSVGPathSegInternal.h"} = 1 if $interfaceName =~ /^SVGPathSeg.+/;
 
-    if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
+    if ($codeGenerator->IsSVGAnimatedType($interfaceName) and !$codeGenerator->IsSVGNewStyleAnimatedType($interfaceName)) {
         $implIncludes{"DeprecatedSVGAnimatedTemplate.h"} = 1;
     } elsif ($interfaceName =~ /(\w+)(Abs|Rel)$/) {
         $implIncludes{"$1.h"} = 1;
@@ -1106,7 +1136,7 @@ sub GenerateImplementation
     if ($podType) {
         push(@implContent, "#define IMPL reinterpret_cast<$podTypeWithNamespace*>(_internal)\n\n");
     } elsif ($parentImplClassName eq "Object") {
-        push(@implContent, "#define IMPL reinterpret_cast<$implClassNameWithNamespace*>(_internal)\n\n");
+        push(@implContent, "#define IMPL reinterpret_cast<$implType*>(_internal)\n\n");
     } else {
         my $baseClassWithNamespace = "WebCore::$baseClass";
         push(@implContent, "#define IMPL static_cast<$implClassNameWithNamespace*>(reinterpret_cast<$baseClassWithNamespace*>(_internal))\n\n");
@@ -1196,15 +1226,20 @@ sub GenerateImplementation
             my $getterContentHead = "IMPL->$getterExpressionPrefix";
             my $getterContentTail = ")";
 
-            # Special case for DOMSVGNumber
-            if ($podType and $podType eq "float") {
-                $getterContentHead = "*IMPL";
-                $getterContentTail = "";
-            }
+            my $svgAnimatedPropertyType = $dataNode->extendedAttributes->{"SVGAnimatedProperty"};
+            if ($svgPropertyType) {
+                $getterContentHead = "$getterExpressionPrefix";
 
-            # TODO: Handle special case for DOMSVGLength
-            if ($podType and $podType eq "SVGLength" and $attributeName eq "value") {
-                $getterContentHead = "IMPL->value(0 /* FIXME */";
+                # TODO: Handle special case for DOMSVGLength. We do need Custom code support for this.
+                if ($svgPropertyType eq "SVGLength" and $attributeName eq "value") {
+                    $getterContentHead = "value(0 /* FIXME */";
+                }
+            } else {
+                # Special case for DOMSVGNumber
+                if ($podType and $podType eq "float") {
+                    $getterContentHead = "*IMPL";
+                    $getterContentTail = "";
+                }
             }
 
             my $attributeTypeSansPtr = $attributeType;
@@ -1247,6 +1282,15 @@ sub GenerateImplementation
             } elsif ($codeGenerator->IsPodType($idlType) or $idlType eq "Date") {
                 $getterContentHead = "kit($getterContentHead";
                 $getterContentTail .= ")";
+            } elsif ($svgPropertyType) {
+                $getterContentHead = "IMPL->propertyReference().$getterContentHead";
+            } elsif ($svgAnimatedPropertyType) {
+                if ($idlType =~ /List$/) {
+                    $getterContentHead = "kit(static_cast<WebCore::SVGListPropertyTearOff<WebCore::$idlType>*>($getterContentHead)";
+                } else {
+                    $getterContentHead = "kit(static_cast<WebCore::SVGPropertyTearOff<WebCore::$idlType>*>($getterContentHead)";
+                }
+                $getterContentTail .= ")";
             } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") {
                 $getterContentHead = "kit($getterContentHead";
                 $getterContentTail .= ")";
@@ -1322,7 +1366,15 @@ sub GenerateImplementation
                     $arg = "core(" . $arg . ")";
                 }
 
-                if ($podType) {
+                if ($svgPropertyType) {
+                    $getterContentHead = "$getterExpressionPrefix";
+                    push(@implContent, "    $svgPropertyTypeWithNamespace& podImpl = IMPL->propertyReference();\n");
+                    push(@implContent, "    podImpl.$coreSetterName($arg);\n");
+                    push(@implContent, "    IMPL->commitChange();\n");
+                } elsif ($svgListPropertyType) {
+                    $getterContentHead = "$getterExpressionPrefix";
+                    push(@implContent, "    IMPL->$coreSetterName($arg);\n");
+                } elsif ($podType) {
                     # Special case for DOMSVGNumber
                     if ($podType eq "float") {
                         push(@implContent, "    *IMPL = $arg;\n");
@@ -1447,10 +1499,18 @@ sub GenerateImplementation
             # FIXME! We need [Custom] support for ObjC, to move these hacks into DOMSVGLength/MatrixCustom.mm
             my $svgMatrixRotateFromVector = ($podType and $podType eq "AffineTransform" and $functionName eq "rotateFromVector");
             my $svgMatrixInverse = ($podType and $podType eq "AffineTransform" and $functionName eq "inverse");
-            my $svgLengthConvertToSpecifiedUnits = ($podType and $podType eq "SVGLength" and $functionName eq "convertToSpecifiedUnits");
+            my $svgLengthConvertToSpecifiedUnits = ($svgPropertyType and $svgPropertyType eq "SVGLength" and $functionName eq "convertToSpecifiedUnits");
 
             push(@parameterNames, "ec") if $raisesExceptions and !($svgMatrixRotateFromVector || $svgMatrixInverse);
-            my $content = $caller . "->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterNames) . ")"; 
+            push(@parameterNames, "0 /* FIXME */") if $svgLengthConvertToSpecifiedUnits; 
+            my $content = $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterNames) . ")"; 
+
+            if ($svgPropertyType) {
+                push(@functionContent, "    $svgPropertyTypeWithNamespace& podImpl = IMPL->propertyReference();\n");
+                $content = "podImpl.$content;\n    IMPL->commitChange()"; 
+            } else {
+                $content = $caller . "->$content";
+            }
 
             if ($svgMatrixRotateFromVector) {
                 # Special case with rotateFromVector & SVGMatrix        
@@ -1466,8 +1526,6 @@ sub GenerateImplementation
                 push(@functionContent, "        ec = WebCore::SVGException::SVG_MATRIX_NOT_INVERTABLE;\n");
                 push(@functionContent, "    $exceptionRaiseOnError\n");
                 push(@functionContent, "    return kit($content);\n");
-            } elsif ($svgLengthConvertToSpecifiedUnits) {
-                push(@functionContent, "    IMPL->convertToSpecifiedUnits(inUnitType, 0 /* FIXME */);\n");
             } elsif ($returnType eq "void") {
                 # Special case 'void' return type.
                 if ($raisesExceptions) {
@@ -1496,7 +1554,10 @@ sub GenerateImplementation
                 $content = "foo";
             } else {
                 if (ConversionNeeded($function->signature->type)) {
-                    if ($codeGenerator->IsPodType($function->signature->type)) {
+                    my $svgLiveProperty = $function->signature->extendedAttributes->{"SVGLiveProperty"};
+                    if ($svgLiveProperty) {
+                        $content = "kit(WebCore::SVGPropertyTearOff<WebCore::" . $function->signature->type . ">::create($content).get())";
+                    } elsif ($codeGenerator->IsPodType($function->signature->type)) {
                         $content = "kit($content)";
                     } else {
                         $content = "kit(WTF::getPtr($content))";
@@ -1549,30 +1610,28 @@ sub GenerateImplementation
 
     # Generate internal interfaces
     if ($podType) {
-        my $prefixedPodType = $podType eq "float" ? $podType : "WebCore::$podType";
-        push(@implContent, "\n$prefixedPodType core($className *wrapper)\n");
+        push(@implContent, "\n$podTypeWithNamespace core($className *wrapper)\n");
         push(@implContent, "{\n");
-        push(@implContent, "    return wrapper ? *reinterpret_cast<$prefixedPodType*>(wrapper->_internal) : $prefixedPodType();\n");
+        push(@implContent, "    return wrapper ? *reinterpret_cast<$podTypeWithNamespace*>(wrapper->_internal) : $podTypeWithNamespace();\n");
         push(@implContent, "}\n\n");
     } else {
-        push(@implContent, "\nWebCore::$implClassName* core($className *wrapper)\n");
+        push(@implContent, "\n$implType* core($className *wrapper)\n");
         push(@implContent, "{\n");
-        push(@implContent, "    return wrapper ? reinterpret_cast<WebCore::$implClassName*>(wrapper->_internal) : 0;\n");
+        push(@implContent, "    return wrapper ? reinterpret_cast<$implType*>(wrapper->_internal) : 0;\n");
         push(@implContent, "}\n\n");
     }
 
     if ($podType) {
         # FIXME: Implement caching.
-        my $prefixedPodType = $podType eq "float" ? $podType : "WebCore::$podType";
-        push(@implContent, "$className *kit($prefixedPodType value)\n");
+        push(@implContent, "$className *kit($podTypeWithNamespace value)\n");
         push(@implContent, "{\n");
         push(@implContent, "    $assertMainThread;\n");
         push(@implContent, "    $className *wrapper = [[$className alloc] _init];\n");
-        push(@implContent, "    wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(new $prefixedPodType(value));\n");
+        push(@implContent, "    wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(new $podTypeWithNamespace(value));\n");
         push(@implContent, "    return [wrapper autorelease];\n");
         push(@implContent, "}\n");
     } elsif ($parentImplClassName eq "Object") {        
-        push(@implContent, "$className *kit(WebCore::$implClassName* value)\n");
+        push(@implContent, "$className *kit($implType* value)\n");
         push(@implContent, "{\n");
         push(@implContent, "    $assertMainThread;\n");
         push(@implContent, "    if (!value)\n");
@@ -1592,7 +1651,7 @@ sub GenerateImplementation
         push(@implContent, "    return [wrapper autorelease];\n");
         push(@implContent, "}\n");
     } else {
-        push(@implContent, "$className *kit(WebCore::$implClassName* value)\n");
+        push(@implContent, "$className *kit($implType* value)\n");
         push(@implContent, "{\n");
         push(@implContent, "    $assertMainThread;\n");
         push(@implContent, "    return static_cast<$className*>(kit(static_cast<WebCore::$baseClass*>(value)));\n");
index 91ffeaa..751e350 100644 (file)
@@ -179,6 +179,8 @@ sub AddIncludesForType
 sub AddIncludesForSVGAnimatedType
 {
     my $type = shift;
+    return if $codeGenerator->IsSVGNewStyleAnimatedType($type);
+
     $type =~ s/SVGAnimated//;
 
     if ($type eq "Point" or $type eq "Rect") {
@@ -228,9 +230,14 @@ sub GenerateHeader
 
     # Get correct pass/store types respecting PODType flag
     my $podType = $dataNode->extendedAttributes->{"PODType"};
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};
 
     my %headerInclues = ();
     $headerIncludes{"$podType.h"} = 1 if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
+    $headerIncludes{"$svgPropertyType.h"} = 1 if $svgPropertyType and $svgPropertyType ne "float";
+    $headerIncludes{"$svgListPropertyType.h"} = 1 if $svgListPropertyType;
+    $headerIncludes{"SVGAnimatedProperty.h"} = 1 if $svgPropertyType or $svgListPropertyType;
     $headerIncludes{"wtf/text/StringHash.h"} = 1;
     $headerIncludes{"WrapperTypeInfo.h"} = 1;
     $headerIncludes{"V8DOMWrapper.h"} = 1;
@@ -245,16 +252,12 @@ sub GenerateHeader
     push(@headerContent, "#include <wtf/HashMap.h>\n");
     
     push(@headerContent, "\nnamespace WebCore {\n");
-    if ($podType) {
-        push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n");
-    }
+    push(@headerContent, "\ntemplate<typename PODType> class V8SVGPODTypeWrapper;\n") if $podType;
+    push(@headerContent, "\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType;
+    push(@headerContent, "\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n") if $svgListPropertyType;
     push(@headerContent, "\nclass $className {\n");
 
-    my $nativeType = GetNativeTypeForConversions($interfaceName);
-    if ($podType) {
-        $nativeType = "V8SVGPODTypeWrapper<${nativeType} >";
-    }
-
+    my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
     my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
     my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
     my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
@@ -450,7 +453,7 @@ sub GetHeaderClassInclude
         $className =~ s/Abs|Rel//;
     }
     return "" if (AvoidInclusionOfType($className));
-    return "DeprecatedSVGAnimatedTemplate.h" if ($codeGenerator->IsSVGAnimatedType($className));
+    return "DeprecatedSVGAnimatedTemplate.h" if $codeGenerator->IsSVGAnimatedType($className) and !$codeGenerator->IsSVGNewStyleAnimatedType($className); 
     return "${className}.h";
 }
 
@@ -680,6 +683,8 @@ sub GenerateNormalAttrGetter
 
     my $nativeType = GetNativeTypeFromSignature($attribute->signature, -1);
     my $isPodType = IsPodType($implClassName);
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};
     my $skipContext = 0;
 
     if ($isPodType) {
@@ -687,6 +692,9 @@ sub GenerateNormalAttrGetter
         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
     }
 
+    $implIncludes{"SVGPropertyTearOff.h"} = 1 if $svgPropertyType;;
+    $implIncludes{"SVGListPropertyTearOff.h"} = 1 if $svgListPropertyType;
+
     # Special case: SVGZoomEvent's attributes are all read-only
     if ($implClassName eq "SVGZoomEvent") {
         $attrIsPodType = 0;
@@ -727,7 +735,17 @@ END
 END
         }
 
-    } elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
+    } elsif ($svgPropertyType) {
+        push(@implContentDecls, <<END);
+    SVGPropertyTearOff<$svgPropertyType>* wrapper = V8${implClassName}::toNative(info.Holder());
+    $svgPropertyType& impInstance = wrapper->propertyReference();
+    $svgPropertyType* imp = &impInstance;
+END
+    } elsif ($svgListPropertyType) {
+        push(@implContentDecls, <<END);
+    SVGListPropertyTearOff<$svgListPropertyType>* imp = V8${implClassName}::toNative(info.Holder());
+END
+    }  elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
         if ($interfaceName eq "DOMWindow") {
             push(@implContentDecls, <<END);
     v8::Handle<v8::Object> holder = info.Holder();
@@ -883,7 +901,14 @@ END
         }
     }
 
-    if ($attrIsPodType) {
+    if ($codeGenerator->IsSVGNewStyleAnimatedType($implClassName)) {
+        $implIncludes{"V8${attrType}.h"} = 1;
+        if ($implClassName =~ /List$/) {
+            push(@implContentDecls, "    return toV8(static_cast<SVGListPropertyTearOff<$attrType>*>($result));\n");
+         } else {
+            push(@implContentDecls, "    return toV8(static_cast<SVGPropertyTearOff<$attrType>*>($result));\n");
+         }
+    } elsif ($attrIsPodType) {
         $implIncludes{"V8${attrType}.h"} = 1;
         push(@implContentDecls, "    return toV8(wrapper.release().get());\n");
     } else {
@@ -912,6 +937,8 @@ sub GenerateNormalAttrSetter
     push(@implContentDecls, "    INC_STATS(\"DOM.$implClassName.$attrName._set\");\n");
 
     my $isPodType = IsPodType($implClassName);
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"};
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"};
 
     if ($isPodType) {
         $implClassName = GetNativeType($implClassName);
@@ -919,7 +946,16 @@ sub GenerateNormalAttrSetter
         push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = V8SVGPODTypeWrapper<$implClassName>::toNative(info.Holder());\n");
         push(@implContentDecls, "    $implClassName impInstance = *wrapper;\n");
         push(@implContentDecls, "    $implClassName* imp = &impInstance;\n");
-
+    } elsif ($svgPropertyType) {
+        push(@implContentDecls, <<END);
+    SVGPropertyTearOff<$svgPropertyType>* wrapper = V8${implClassName}::toNative(info.Holder());
+    $svgPropertyType& impInstance = wrapper->propertyReference();
+    $svgPropertyType* imp = &impInstance;
+END
+    } elsif ($svgListPropertyType) {
+        push(@implContentDecls, <<END);
+    SVGListPropertyTearOff<$svgListPropertyType>* imp = V8${implClassName}::toNative(info.Holder());
+END
     } elsif ($attrExt->{"v8OnProto"}) {
       if ($interfaceName eq "DOMWindow") {
         push(@implContentDecls, <<END);
@@ -1013,6 +1049,8 @@ END
 
     if ($isPodType) {
         push(@implContentDecls, "    wrapper->commitChange(*imp, V8Proxy::svgContext(wrapper));\n");
+    } elsif ($svgPropertyType) {
+        push(@implContentDecls, "    wrapper->commitChange();\n");
     } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
         $implIncludes{"SVGElement.h"} = 1;
 
@@ -1024,7 +1062,7 @@ END
         push(@implContentDecls, "    if (SVGElement* context = V8Proxy::svgContext($currentObject))\n");
         push(@implContentDecls, "        context->svgAttributeChanged(imp->associatedAttributeName());\n");
     }
-
+    
     push(@implContentDecls, "    return;\n");
     push(@implContentDecls, "}\n\n");  # end of setter
     push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString;
@@ -1213,11 +1251,22 @@ END
         }
     }
 
+    my $svgPropertyType = $dataNode->extendedAttributes->{"SVGProperty"}; 
+    my $svgListPropertyType = $dataNode->extendedAttributes->{"SVGListProperty"}; 
+
     if (IsPodType($implClassName)) {
         my $nativeClassName = GetNativeType($implClassName);
         push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* impWrapper = V8SVGPODTypeWrapper<$nativeClassName>::toNative(args.Holder());\n");
         push(@implContentDecls, "    $nativeClassName impInstance = *impWrapper;\n");
         push(@implContentDecls, "    $nativeClassName* imp = &impInstance;\n");
+    } elsif ($svgPropertyType) {
+        my $nativeClassName = GetNativeType($implClassName);
+        push(@implContentDecls, "    $nativeClassName wrapper = V8${svgPropertyType}::toNative(args.Holder());\n");
+        push(@implContentDecls, "    $svgPropertyType& impInstance = wrapper->propertyReference();\n");
+        push(@implContentDecls, "    $svgPropertyType* imp = &impInstance;\n");
+    } elsif ($svgListPropertyType) {
+        my $nativeClassName = GetNativeType($implClassName);
+        push(@implContentDecls, "    $nativeClassName imp = V8${svgListPropertyType}::toNative(args.Holder());\n");
     } elsif (!$function->signature->extendedAttributes->{"ClassMethod"}) {
         push(@implContentDecls, <<END);
     ${implClassName}* imp = V8${implClassName}::toNative(args.Holder());
@@ -2130,10 +2179,7 @@ END
 END
     }
 
-    my $nativeType = GetNativeTypeForConversions($interfaceName);
-    if ($dataNode->extendedAttributes->{"PODType"}) {
-        $nativeType = "V8SVGPODTypeWrapper<${nativeType}>";
-    }
+    my $nativeType = GetNativeTypeForConversions($dataNode, $interfaceName);
     push(@implContent, <<END);
 
     // Custom toString template
@@ -2538,7 +2584,7 @@ sub GetDomMapFunction
     return "getDOMSVGElementInstanceMap()" if $type eq "SVGElementInstance";
     return "getDOMNodeMap()" if ($dataNode && IsNodeSubType($dataNode));
     # Only use getDOMSVGObjectWithContextMap() for non-node svg objects
-    return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/;
+    return "getDOMSVGObjectWithContextMap()" if $type =~ /SVG/ and $type ne "SVGLength" and $type ne "SVGLengthList" and not $codeGenerator->IsSVGNewStyleAnimatedType($type);
     return "" if $type eq "DOMImplementation";
     return "getActiveDOMObjectMap()" if IsActiveDomType($type);
     return "getDOMObjectMap()";
@@ -2562,11 +2608,16 @@ sub IsActiveDomType
 
 sub GetNativeTypeForConversions
 {
+    my $dataNode = shift;
     my $type = shift;
-    return "FloatRect" if $type eq "SVGRect";
-    return "FloatPoint" if $type eq "SVGPoint";
-    return "AffineTransform" if $type eq "SVGMatrix";
-    return "float" if $type eq "SVGNumber";
+
+    $type = "FloatRect" if $type eq "SVGRect";
+    $type = "FloatPoint" if $type eq "SVGPoint";
+    $type = "AffineTransform" if $type eq "SVGMatrix";
+    $type = "float" if $type eq "SVGNumber";
+    $type = "V8SVGPODTypeWrapper<$type>" if $dataNode->extendedAttributes->{"PODType"};
+    $type = "SVGPropertyTearOff<$type>" if $dataNode->extendedAttributes->{"SVGProperty"};
+    $type = "SVGListPropertyTearOff<$type>" if $dataNode->extendedAttributes->{"SVGListProperty"};
     return $type;
 }
 
@@ -2724,6 +2775,13 @@ sub GenerateFunctionCallString()
         $result .= GenerateSVGStaticPodTypeWrapper($returnType, $return) . ";\n";
         $return = "wrapper";
     }
+    
+    my $svgLivePropertyType = $function->signature->extendedAttributes->{"SVGLiveProperty"};
+    if ($svgLivePropertyType) {
+        $implIncludes{"V8$returnType.h"} = 1;
+        $implIncludes{"SVGPropertyTearOff.h"} = 1;
+        return $indent . "return toV8(SVGPropertyTearOff<$returnType>::create($return).get());\n";
+    }
 
     my $generatedSVGContextRetrieval = 0;
     # If the return type needs an SVG context, output it
@@ -2750,6 +2808,8 @@ sub GenerateFunctionCallString()
         }
 
         $result .= $indent . "impWrapper->commitChange(impInstance, context);\n";
+    } elsif ($dataNode->extendedAttributes->{"SVGProperty"}) {
+        $result .= $indent . "wrapper->commitChange();\n";
     }
 
     if ($returnsPodType) {
@@ -2842,8 +2902,9 @@ sub GetNativeType
     return "FloatPoint" if $type eq "SVGPoint";
     return "AffineTransform" if $type eq "SVGMatrix";
     return "SVGTransform" if $type eq "SVGTransform";
-    return "SVGLength" if $type eq "SVGLength";
     return "SVGAngle" if $type eq "SVGAngle";
+    return "RefPtr<SVGPropertyTearOff<SVGLength> >" if $type eq "SVGLength";
+    return "SVGListPropertyTearOff<SVGLengthList>*" if $type eq "SVGLengthList";
     return "float" if $type eq "SVGNumber";
     return "SVGPreserveAspectRatio" if $type eq "SVGPreserveAspectRatio";
     return "SVGPaint::SVGPaintType" if $type eq "SVGPaintType";
@@ -2896,7 +2957,6 @@ sub BasicTypeCanFailConversion
     my $type = GetTypeFromSignature($signature);
 
     return 1 if $type eq "SVGAngle";
-    return 1 if $type eq "SVGLength";
     return 1 if $type eq "SVGMatrix";
     return 1 if $type eq "SVGPoint";
     return 1 if $type eq "SVGPreserveAspectRatio";
@@ -3278,8 +3338,9 @@ sub IsSVGTypeNeedingContextParameter
 {
     my $implClassName = shift;
 
+    return 0 if $codeGenerator->IsSVGNewStyleAnimatedType($implClassName);
     if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
-        return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
+        return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/ or $implClassName =~ /SVGLength/ or $implClassName =~/SVGLengthList/;
     }
 
     return 0;
index 0dae6af..3582a36 100644 (file)
 #if ENABLE(SVG)
 #include "V8SVGLength.h"
 
-#include "SVGLength.h"
+#include "SVGPropertyTearOff.h"
 #include "V8Binding.h"
-#include "V8SVGPODTypeWrapper.h"
-#include "V8Proxy.h"
 
 namespace WebCore {
 
 v8::Handle<v8::Value> V8SVGLength::valueAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
 {
     INC_STATS("DOM.SVGLength.value");
-    V8SVGPODTypeWrapper<SVGLength>* wrapper = V8SVGPODTypeWrapper<SVGLength>::toNative(info.Holder());
-    SVGLength imp = *wrapper;
-    return v8::Number::New(imp.value(V8Proxy::svgContext(wrapper)));
+    SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder());
+    SVGLength& imp = wrapper->propertyReference();
+    return v8::Number::New(imp.value(wrapper->contextElement()));
 }
 
 v8::Handle<v8::Value> V8SVGLength::convertToSpecifiedUnitsCallback(const v8::Arguments& args)
 {
     INC_STATS("DOM.SVGLength.convertToSpecifiedUnits");
-    V8SVGPODTypeWrapper<SVGLength>* wrapper = V8SVGPODTypeWrapper<SVGLength>::toNative(args.Holder());
-    SVGLength imp = *wrapper;
-    SVGElement* context = V8Proxy::svgContext(wrapper);
-    imp.convertToSpecifiedUnits(toInt32(args[0]), context);
-    wrapper->commitChange(imp, context);
+    SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(args.Holder());
+    SVGLength& imp = wrapper->propertyReference();
+    imp.convertToSpecifiedUnits(toInt32(args[0]), wrapper->contextElement());
+    wrapper->commitChange();
     return v8::Undefined();
 }
 
index c3f4b6a..2474a5c 100644 (file)
@@ -57,20 +57,17 @@ void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextSubtree(RenderS
     propagateLayoutAttributes(textRoot, atCharacter, lastCharacter);
 }
 
-static inline void extractFloatValuesFromSVGLengthList(SVGElement* lengthContext, SVGLengthList* list, Vector<float>& floatValues, unsigned textContentLength)
+static inline void extractFloatValuesFromSVGLengthList(SVGElement* lengthContext, const SVGLengthList& list, Vector<float>& floatValues, unsigned textContentLength)
 {
     ASSERT(lengthContext);
-    ASSERT(list);
 
-    unsigned length = list->numberOfItems();
+    unsigned length = list.size();
     if (length > textContentLength)
         length = textContentLength;
     floatValues.reserveCapacity(length);
 
-    ExceptionCode ec = 0;
     for (unsigned i = 0; i < length; ++i) {
-        SVGLength length = list->getItem(i, ec);
-        ASSERT(!ec);
+        const SVGLength& length = list.at(i);
         floatValues.append(length.value(lengthContext));
     }
 }
index a660198..7d8d017 100644 (file)
@@ -25,8 +25,6 @@
 #include "FloatRect.h"
 #include "PlatformString.h"
 #include "SVGAngle.h"
-#include "SVGLength.h"
-#include "SVGLengthList.h"
 #include "SVGNumberList.h"
 #include "SVGPreserveAspectRatio.h"
 #include "SVGTransformList.h"
@@ -84,30 +82,6 @@ struct DeprecatedSVGAnimatedPropertyTraits<long> : public Noncopyable {
     static String toString(PassType type) { return String::number(type); }
 };
 
-// SVGAnimatedLength
-template<>
-struct DeprecatedSVGAnimatedPropertyTraits<SVGLength> : public Noncopyable {
-    typedef const SVGLength& PassType;
-    typedef SVGLength ReturnType;
-    typedef SVGLength StoredType;
-
-    static ReturnType null() { return SVGLength(); }
-    static ReturnType toReturnType(const StoredType& type) { return type; }
-    static String toString(PassType type) { return type.valueAsString(); }
-};
-
-// SVGAnimatedLengthList
-template<>
-struct DeprecatedSVGAnimatedPropertyTraits<SVGLengthList*> : public Noncopyable {
-    typedef SVGLengthList* PassType;
-    typedef SVGLengthList* ReturnType;
-    typedef RefPtr<SVGLengthList> StoredType;
-
-    static ReturnType null() { return 0; }
-    static ReturnType toReturnType(const StoredType& type) { return type.get(); }
-    static String toString(PassType type) { return type ? type->valueAsString() : String(); }
-};
-
 // SVGAnimatedNumber
 template<>
 struct DeprecatedSVGAnimatedPropertyTraits<float> : public Noncopyable {
index 8e29f50..4f33999 100644 (file)
@@ -30,7 +30,6 @@ namespace WebCore {
    
     class SVGAngle;
     class SVGElement;
-    class SVGLengthList;
     class SVGNumberList;
     class SVGPreserveAspectRatio;
     class SVGTransformList;
@@ -160,8 +159,6 @@ namespace WebCore {
     typedef DeprecatedSVGAnimatedTemplate<bool> SVGAnimatedBoolean;
     typedef DeprecatedSVGAnimatedTemplate<int> SVGAnimatedEnumeration;
     typedef DeprecatedSVGAnimatedTemplate<long> SVGAnimatedInteger;
-    typedef DeprecatedSVGAnimatedTemplate<SVGLength> SVGAnimatedLength;
-    typedef DeprecatedSVGAnimatedTemplate<SVGLengthList*> SVGAnimatedLengthList;
     typedef DeprecatedSVGAnimatedTemplate<float> SVGAnimatedNumber;
     typedef DeprecatedSVGAnimatedTemplate<SVGNumberList*> SVGAnimatedNumberList; 
     typedef DeprecatedSVGAnimatedTemplate<SVGPreserveAspectRatio> SVGAnimatedPreserveAspectRatio;
diff --git a/WebCore/svg/SVGAnimatedLength.h b/WebCore/svg/SVGAnimatedLength.h
new file mode 100644 (file)
index 0000000..0504fd7
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedLength_h
+#define SVGAnimatedLength_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedPropertyTearOff.h"
+#include "SVGLength.h"
+
+namespace WebCore {
+
+typedef SVGAnimatedPropertyTearOff<SVGLength> SVGAnimatedLength;
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
index 7ace261..a0e2182 100644 (file)
@@ -25,7 +25,7 @@
 
 module svg {
 
-    interface [Conditional=SVG] SVGAnimatedLength {
+    interface [Conditional=SVG, SVGAnimatedProperty] SVGAnimatedLength {
         readonly attribute SVGLength baseVal;
         readonly attribute SVGLength animVal;
     };
diff --git a/WebCore/svg/SVGAnimatedLengthList.h b/WebCore/svg/SVGAnimatedLengthList.h
new file mode 100644 (file)
index 0000000..fcd8197
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedLengthList_h
+#define SVGAnimatedLengthList_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedListPropertyTearOff.h"
+#include "SVGLengthList.h"
+
+namespace WebCore {
+
+typedef SVGAnimatedListPropertyTearOff<SVGLengthList> SVGAnimatedLengthList;
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
index a68724a..b94797e 100644 (file)
@@ -25,7 +25,7 @@
 
 module svg {
 
-    interface [Conditional=SVG] SVGAnimatedLengthList {
+    interface [Conditional=SVG, SVGAnimatedProperty] SVGAnimatedLengthList {
         readonly attribute SVGLengthList baseVal;
         readonly attribute SVGLengthList animVal;
     };
index 4eb9262..1e80ab6 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGCircleElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledTransformableElement.h"
@@ -49,9 +51,9 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::cxAttr, SVGLength, Cx, cx)
-        DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::cyAttr, SVGLength, Cy, cy)
-        DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::rAttr, SVGLength, R, r)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGCircleElement, SVGNames::cxAttr, SVGLength, Cx, cx)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGCircleElement, SVGNames::cyAttr, SVGLength, Cy, cy)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGCircleElement, SVGNames::rAttr, SVGLength, R, r)
 
         // SVGExternalResourcesRequired
         DECLARE_ANIMATED_PROPERTY(SVGCircleElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired)
index ce4d129..c52e7f1 100644 (file)
@@ -22,7 +22,8 @@
 #define SVGCursorElement_h
 
 #if ENABLE(SVG)
-#include "SVGLength.h"
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGElement.h"
 #include "SVGTests.h"
 #include "SVGURIReference.h"
@@ -53,8 +54,8 @@ namespace WebCore {
 
         virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGCursorElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGCursorElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGCursorElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGCursorElement, SVGNames::yAttr, SVGLength, Y, y)
 
         // SVGURIReference
         DECLARE_ANIMATED_PROPERTY(SVGCursorElement, XLinkNames::hrefAttr, String, Href, href)
index cad329e..1d72f75 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGEllipseElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledTransformableElement.h"
@@ -49,10 +51,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::cxAttr, SVGLength, Cx, cx)
-        DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::cyAttr, SVGLength, Cy, cy)
-        DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::rxAttr, SVGLength, Rx, rx)
-        DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::ryAttr, SVGLength, Ry, ry)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGEllipseElement, SVGNames::cxAttr, SVGLength, Cx, cx)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGEllipseElement, SVGNames::cyAttr, SVGLength, Cy, cy)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGEllipseElement, SVGNames::rxAttr, SVGLength, Rx, rx)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGEllipseElement, SVGNames::ryAttr, SVGLength, Ry, ry)
 
         // SVGExternalResourcesRequired
         DECLARE_ANIMATED_PROPERTY(SVGEllipseElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired)
index c228fe7..57e5ff8 100644 (file)
@@ -24,6 +24,8 @@
 #define SVGFilterElement_h
 
 #if ENABLE(SVG) && ENABLE(FILTERS)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "RenderObject.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
@@ -61,10 +63,10 @@ private:
 
     DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::filterUnitsAttr, int, FilterUnits, filterUnits)
     DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::primitiveUnitsAttr, int, PrimitiveUnits, primitiveUnits)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::xAttr, SVGLength, X, x)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::yAttr, SVGLength, Y, y)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::widthAttr, SVGLength, Width, width)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterElement, SVGNames::heightAttr, SVGLength, Height, height)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterElement, SVGNames::xAttr, SVGLength, X, x)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterElement, SVGNames::yAttr, SVGLength, Y, y)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterElement, SVGNames::widthAttr, SVGLength, Width, width)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterElement, SVGNames::heightAttr, SVGLength, Height, height)
     DECLARE_ANIMATED_PROPERTY_MULTIPLE_WRAPPERS(SVGFilterElement, SVGNames::filterResAttr, SVGFilterResXIdentifier, long, FilterResX, filterResX)
     DECLARE_ANIMATED_PROPERTY_MULTIPLE_WRAPPERS(SVGFilterElement, SVGNames::filterResAttr, SVGFilterResYIdentifier, long, FilterResY, filterResY)
 
index 0ffa1c9..6202888 100644 (file)
@@ -24,6 +24,8 @@
 #if ENABLE(SVG) && ENABLE(FILTERS)
 #include "FilterEffect.h"
 #include "RenderSVGResource.h"
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGFilterBuilder.h"
 #include "SVGFilterElement.h"
 #include "SVGNames.h"
@@ -60,10 +62,10 @@ private:
 
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
 
-    DECLARE_ANIMATED_PROPERTY(SVGFilterPrimitiveStandardAttributes, SVGNames::xAttr, SVGLength, X, x)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterPrimitiveStandardAttributes, SVGNames::yAttr, SVGLength, Y, y)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterPrimitiveStandardAttributes, SVGNames::widthAttr, SVGLength, Width, width)
-    DECLARE_ANIMATED_PROPERTY(SVGFilterPrimitiveStandardAttributes, SVGNames::heightAttr, SVGLength, Height, height)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterPrimitiveStandardAttributes, SVGNames::xAttr, SVGLength, X, x)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterPrimitiveStandardAttributes, SVGNames::yAttr, SVGLength, Y, y)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterPrimitiveStandardAttributes, SVGNames::widthAttr, SVGLength, Width, width)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGFilterPrimitiveStandardAttributes, SVGNames::heightAttr, SVGLength, Height, height)
     DECLARE_ANIMATED_PROPERTY(SVGFilterPrimitiveStandardAttributes, SVGNames::resultAttr, String, Result, result)
 };
 
index a587134..872ed18 100644 (file)
@@ -21,6 +21,8 @@
 #define SVGForeignObjectElement_h
 
 #if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGTests.h"
 #include "SVGLangSpace.h"
 #include "SVGURIReference.h"
@@ -50,10 +52,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGForeignObjectElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGForeignObjectElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGForeignObjectElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGForeignObjectElement, SVGNames::heightAttr, SVGLength, Height, height)
 
         // SVGURIReference
         DECLARE_ANIMATED_PROPERTY(SVGForeignObjectElement, XLinkNames::hrefAttr, String, Href, href)
index 9024415..ac93529 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGImageElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGImageLoader.h"
@@ -64,10 +66,10 @@ namespace WebCore {
         virtual bool selfHasRelativeLengths() const;
         virtual void willMoveToNewOwnerDocument();
 
-        DECLARE_ANIMATED_PROPERTY(SVGImageElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGImageElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGImageElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGImageElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGImageElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGImageElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGImageElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGImageElement, SVGNames::heightAttr, SVGLength, Height, height)
         DECLARE_ANIMATED_PROPERTY(SVGImageElement, SVGNames::preserveAspectRatioAttr, SVGPreserveAspectRatio, PreserveAspectRatio, preserveAspectRatio)
 
         // SVGURIReference
index d1cb572..ed0199b 100644 (file)
@@ -22,7 +22,7 @@
 
 module svg {
 
-    interface [Conditional=SVG, PODType=SVGLength] SVGLength { 
+    interface [Conditional=SVG, SVGProperty=SVGLength] SVGLength { 
         // Length Unit Types
         const unsigned short SVG_LENGTHTYPE_UNKNOWN    = 0;
         const unsigned short SVG_LENGTHTYPE_NUMBER     = 1;
index 2149e04..3ab7c1a 100644 (file)
 #include "SVGLengthList.h"
 
 #include "SVGParserUtilities.h"
+#include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
-SVGLengthList::SVGLengthList(const QualifiedName& attributeName)
-    : SVGPODList<SVGLength>(attributeName)
-{
-}
-
 void SVGLengthList::parse(const String& value, SVGLengthMode mode)
 {
-    ExceptionCode ec = 0;
-    clear(ec);
+    clear();
 
     const UChar* ptr = value.characters();
     const UChar* end = ptr + value.length();
@@ -48,25 +43,24 @@ void SVGLengthList::parse(const String& value, SVGLengthMode mode)
         SVGLength length(mode);
         if (!length.setValueAsString(String(start, ptr - start)))
             return;
-        appendItem(length, ec);
+        append(length);
         skipOptionalSpacesOrDelimiter(ptr, end);
     }
 }
 
 String SVGLengthList::valueAsString() const
 {
-    String result;
+    StringBuilder builder;
 
-    ExceptionCode ec = 0;
-    for (unsigned int i = 0; i < numberOfItems(); ++i) {
+    unsigned size = this->size();
+    for (unsigned i = 0; i < size; ++i) {
         if (i > 0)
-            result += ", ";
+            builder.append(", ");
 
-        result += getItem(i, ec).valueAsString();
-        ASSERT(ec == 0);
+        builder.append(at(i).valueAsString());
     }
 
-    return result;
+    return builder.toString();
 }
 
 }
index 27b958f..8b08557 100644 (file)
 
 #if ENABLE(SVG)
 #include "SVGLength.h"
-#include "SVGList.h"
+#include <wtf/Vector.h>
 
 namespace WebCore {
 
-    class SVGLengthList : public SVGPODList<SVGLength> {
-    public:
-        static PassRefPtr<SVGLengthList> create(const QualifiedName& attributeName) { return adoptRef(new SVGLengthList(attributeName)); }
+class SVGLengthList : public Vector<SVGLength> {
+public:
+    SVGLengthList() { }
 
-        void parse(const String& value, SVGLengthMode);
-        String valueAsString() const;
-
-    private:
-        SVGLengthList(const QualifiedName&);
-    };
+    void parse(const String& value, SVGLengthMode); 
+    String valueAsString() const;
+};
 
 } // namespace WebCore
 
index a5771d2..73a8d21 100644 (file)
@@ -26,7 +26,7 @@
 
 module svg {
 
-    interface [Conditional=SVG] SVGLengthList { 
+    interface [Conditional=SVG, SVGListProperty=SVGLengthList] SVGLengthList { 
         readonly attribute unsigned long numberOfItems;
 
         void clear()
index 55a268c..f10deb2 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGLineElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledTransformableElement.h"
@@ -53,10 +55,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::x1Attr, SVGLength, X1, x1)
-        DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::y1Attr, SVGLength, Y1, y1)
-        DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::x2Attr, SVGLength, X2, x2)
-        DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::y2Attr, SVGLength, Y2, y2)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLineElement, SVGNames::x1Attr, SVGLength, X1, x1)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLineElement, SVGNames::y1Attr, SVGLength, Y1, y1)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLineElement, SVGNames::x2Attr, SVGLength, X2, x2)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLineElement, SVGNames::y2Attr, SVGLength, Y2, y2)
 
         // SVGExternalResourcesRequired
         DECLARE_ANIMATED_PROPERTY(SVGLineElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired)
index 86bebf3..4ebe9f6 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGLinearGradientElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGGradientElement.h"
 
 namespace WebCore {
@@ -47,10 +49,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::x1Attr, SVGLength, X1, x1)
-        DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::y1Attr, SVGLength, Y1, y1)
-        DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::x2Attr, SVGLength, X2, x2)
-        DECLARE_ANIMATED_PROPERTY(SVGLinearGradientElement, SVGNames::y2Attr, SVGLength, Y2, y2)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLinearGradientElement, SVGNames::x1Attr, SVGLength, X1, x1)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLinearGradientElement, SVGNames::y1Attr, SVGLength, Y1, y1)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLinearGradientElement, SVGNames::x2Attr, SVGLength, X2, x2)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGLinearGradientElement, SVGNames::y2Attr, SVGLength, Y2, y2)
     };
 
 } // namespace WebCore
index 7782739..8b21ff5 100644 (file)
@@ -24,6 +24,8 @@
 #if ENABLE(SVG)
 #include "RenderObject.h"
 #include "SVGAngle.h"
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGFitToViewBox.h"
 #include "SVGLangSpace.h"
@@ -74,10 +76,10 @@ private:
 
     virtual bool selfHasRelativeLengths() const;
 
-    DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::refXAttr, SVGLength, RefX, refX)
-    DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::refYAttr, SVGLength, RefY, refY)
-    DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::markerWidthAttr, SVGLength, MarkerWidth, markerWidth)
-    DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::markerHeightAttr, SVGLength, MarkerHeight, markerHeight)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGMarkerElement, SVGNames::refXAttr, SVGLength, RefX, refX)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGMarkerElement, SVGNames::refYAttr, SVGLength, RefY, refY)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGMarkerElement, SVGNames::markerWidthAttr, SVGLength, MarkerWidth, markerWidth)
+    DECLARE_ANIMATED_PROPERTY_NEW(SVGMarkerElement, SVGNames::markerHeightAttr, SVGLength, MarkerHeight, markerHeight)
     DECLARE_ANIMATED_PROPERTY(SVGMarkerElement, SVGNames::markerUnitsAttr, int, MarkerUnits, markerUnits)
     DECLARE_ANIMATED_PROPERTY_MULTIPLE_WRAPPERS(SVGMarkerElement, SVGNames::orientAttr, SVGOrientTypeAttrIdentifier, int, OrientType, orientType)
     DECLARE_ANIMATED_PROPERTY_MULTIPLE_WRAPPERS(SVGMarkerElement, SVGNames::orientAttr, SVGOrientAngleAttrIdentifier, SVGAngle, OrientAngle, orientAngle)
index c951beb..de77696 100644 (file)
@@ -22,6 +22,8 @@
 
 #if ENABLE(SVG)
 #include "RenderObject.h"
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledLocatableElement.h"
@@ -57,10 +59,10 @@ namespace WebCore {
 
         DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::maskUnitsAttr, int, MaskUnits, maskUnits)
         DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::maskContentUnitsAttr, int, MaskContentUnits, maskContentUnits)
-        DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGMaskElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGMaskElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGMaskElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGMaskElement, SVGNames::heightAttr, SVGLength, Height, height)
 
         // SVGExternalResourcesRequired
         DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired)
index a93c54c..51352fc 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGPatternElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGFitToViewBox.h"
 #include "SVGLangSpace.h"
@@ -62,10 +64,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGPatternElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGPatternElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGPatternElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGPatternElement, SVGNames::heightAttr, SVGLength, Height, height)
         DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::patternUnitsAttr, int, PatternUnits, patternUnits)
         DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::patternContentUnitsAttr, int, PatternContentUnits, patternContentUnits)
         DECLARE_ANIMATED_PROPERTY(SVGPatternElement, SVGNames::patternTransformAttr, SVGTransformList*, PatternTransform, patternTransform)
index 61333af..f223514 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGRadialGradientElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGGradientElement.h"
 
 namespace WebCore {
@@ -47,11 +49,11 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::cxAttr, SVGLength, Cx, cx)
-        DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::cyAttr, SVGLength, Cy, cy)
-        DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::rAttr, SVGLength, R, r)
-        DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::fxAttr, SVGLength, Fx, fx)
-        DECLARE_ANIMATED_PROPERTY(SVGRadialGradientElement, SVGNames::fyAttr, SVGLength, Fy, fy)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRadialGradientElement, SVGNames::cxAttr, SVGLength, Cx, cx)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRadialGradientElement, SVGNames::cyAttr, SVGLength, Cy, cy)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRadialGradientElement, SVGNames::rAttr, SVGLength, R, r)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRadialGradientElement, SVGNames::fxAttr, SVGLength, Fx, fx)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRadialGradientElement, SVGNames::fyAttr, SVGLength, Fy, fy)
     };
 
 } // namespace WebCore
index 668366b..ba448c5 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGRectElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledTransformableElement.h"
@@ -49,12 +51,12 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::heightAttr, SVGLength, Height, height)
-        DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::rxAttr, SVGLength, Rx, rx)
-        DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::ryAttr, SVGLength, Ry, ry)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRectElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRectElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRectElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRectElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRectElement, SVGNames::rxAttr, SVGLength, Rx, rx)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGRectElement, SVGNames::ryAttr, SVGLength, Ry, ry)
 
         // SVGExternalResourcesRequired
         DECLARE_ANIMATED_PROPERTY(SVGRectElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired)
index b5b10b1..8a9f653 100644 (file)
@@ -22,8 +22,9 @@
 #define SVGSVGElement_h
 
 #if ENABLE(SVG)
-
 #include "IntSize.h"
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGFitToViewBox.h"
 #include "SVGLangSpace.h"
@@ -136,10 +137,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGSVGElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGSVGElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGSVGElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGSVGElement, SVGNames::heightAttr, SVGLength, Height, height)
 
         // SVGExternalResourcesRequired
         DECLARE_ANIMATED_PROPERTY(SVGSVGElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired)
index bcf9236..fc920bf 100644 (file)
@@ -73,7 +73,7 @@ module svg {
         void deselectAll();
 
         SVGNumber createSVGNumber();
-        SVGLength createSVGLength();
+        [SVGLiveProperty] SVGLength createSVGLength();
         SVGAngle createSVGAngle();
         SVGPoint createSVGPoint();
         SVGMatrix createSVGMatrix();
index a63e27a..015b857 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGTextContentElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledElement.h"
@@ -69,7 +71,7 @@ namespace WebCore {
     private:
         virtual bool isTextContent() const { return true; }
 
-        DECLARE_ANIMATED_PROPERTY(SVGTextContentElement, SVGNames::textLengthAttr, SVGLength, TextLength, textLength)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGTextContentElement, SVGNames::textLengthAttr, SVGLength, TextLength, textLength)
         DECLARE_ANIMATED_PROPERTY(SVGTextContentElement, SVGNames::lengthAdjustAttr, int, LengthAdjust, lengthAdjust)
 
         // SVGExternalResourcesRequired
index b87dfa5..0c8ef16 100644 (file)
@@ -67,7 +67,7 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGTextPathElement, SVGNames::startOffsetAttr, SVGLength, StartOffset, startOffset)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGTextPathElement, SVGNames::startOffsetAttr, SVGLength, StartOffset, startOffset)
         DECLARE_ANIMATED_PROPERTY(SVGTextPathElement, SVGNames::methodAttr, int, Method, method)
         DECLARE_ANIMATED_PROPERTY(SVGTextPathElement, SVGNames::spacingAttr, int, Spacing, spacing)
     
index cbc324d..d64dd1f 100644 (file)
@@ -34,25 +34,33 @@ namespace WebCore {
 
 SVGTextPositioningElement::SVGTextPositioningElement(const QualifiedName& tagName, Document* document)
     : SVGTextContentElement(tagName, document)
-    , m_x(SVGLengthList::create(SVGNames::xAttr))
-    , m_y(SVGLengthList::create(SVGNames::yAttr))
-    , m_dx(SVGLengthList::create(SVGNames::dxAttr))
-    , m_dy(SVGLengthList::create(SVGNames::dyAttr))
     , m_rotate(SVGNumberList::create(SVGNames::rotateAttr))
 {
 }
 
 void SVGTextPositioningElement::parseMappedAttribute(Attribute* attr)
 {
-    if (attr->name() == SVGNames::xAttr)
-        xBaseValue()->parse(attr->value(), LengthModeWidth);
-    else if (attr->name() == SVGNames::yAttr)
-        yBaseValue()->parse(attr->value(), LengthModeHeight);
-    else if (attr->name() == SVGNames::dxAttr)
-        dxBaseValue()->parse(attr->value(), LengthModeWidth);
-    else if (attr->name() == SVGNames::dyAttr)
-        dyBaseValue()->parse(attr->value(), LengthModeHeight);
-    else if (attr->name() == SVGNames::rotateAttr)
+    if (attr->name() == SVGNames::xAttr) {
+        SVGLengthList newList;
+        newList.parse(attr->value(), LengthModeWidth);
+        detachAnimatedXListWrappers(newList.size());
+        xBaseValue() = newList;
+    } else if (attr->name() == SVGNames::yAttr) {
+        SVGLengthList newList;
+        newList.parse(attr->value(), LengthModeHeight);
+        detachAnimatedYListWrappers(newList.size());
+        yBaseValue() = newList;
+    } else if (attr->name() == SVGNames::dxAttr) {
+        SVGLengthList newList;
+        newList.parse(attr->value(), LengthModeWidth);
+        detachAnimatedDxListWrappers(newList.size());
+        dxBaseValue() = newList;
+    } else if (attr->name() == SVGNames::dyAttr) {
+        SVGLengthList newList;
+        newList.parse(attr->value(), LengthModeHeight);
+        detachAnimatedDyListWrappers(newList.size());
+        dyBaseValue() = newList;
+    } else if (attr->name() == SVGNames::rotateAttr)
         rotateBaseValue()->parse(attr->value());
     else
         SVGTextContentElement::parseMappedAttribute(attr);
@@ -144,17 +152,11 @@ void SVGTextPositioningElement::synchronizeProperty(const QualifiedName& attrNam
         synchronizeRotate();
 }
 
-static inline bool listContainsRelativeValue(SVGLengthList* list)
+static inline bool listContainsRelativeValue(const SVGLengthList& list)
 {
-    if (!list)
-        return false;
-
-    ExceptionCode ec = 0;
-    int length = list->numberOfItems();
-    for (int i = 0; i < length; ++i) {
-        SVGLength length(list->getItem(i, ec));
-        ASSERT(!ec);
-
+    unsigned size = list.size();
+    for (unsigned i = 0; i < size; ++i) {
+        const SVGLength& length = list.at(i);
         if (length.isRelative())
             return true;
     }
@@ -200,7 +202,6 @@ SVGTextPositioningElement* SVGTextPositioningElement::elementFromRenderer(Render
     return static_cast<SVGTextPositioningElement*>(node);
 }
 
-
 }
 
 #endif // ENABLE(SVG)
index 41de9f3..1fb1c3c 100644 (file)
@@ -42,10 +42,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::xAttr, SVGLengthList*, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::yAttr, SVGLengthList*, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::dxAttr, SVGLengthList*, Dx, dx)
-        DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::dyAttr, SVGLengthList*, Dy, dy)
+        DECLARE_ANIMATED_LIST_PROPERTY_NEW(SVGTextPositioningElement, SVGNames::xAttr, SVGLengthList, X, x)
+        DECLARE_ANIMATED_LIST_PROPERTY_NEW(SVGTextPositioningElement, SVGNames::yAttr, SVGLengthList, Y, y)
+        DECLARE_ANIMATED_LIST_PROPERTY_NEW(SVGTextPositioningElement, SVGNames::dxAttr, SVGLengthList, Dx, dx)
+        DECLARE_ANIMATED_LIST_PROPERTY_NEW(SVGTextPositioningElement, SVGNames::dyAttr, SVGLengthList, Dy, dy)
         DECLARE_ANIMATED_PROPERTY(SVGTextPositioningElement, SVGNames::rotateAttr, SVGNumberList*, Rotate, rotate)
     };
 
index b8ba71d..fea8034 100644 (file)
@@ -22,6 +22,8 @@
 #define SVGUseElement_h
 
 #if ENABLE(SVG)
+#include "SVGAnimatedLength.h"
+#include "SVGAnimatedPropertyMacros.h"
 #include "SVGExternalResourcesRequired.h"
 #include "SVGLangSpace.h"
 #include "SVGStyledTransformableElement.h"
@@ -79,10 +81,10 @@ namespace WebCore {
 
         virtual bool selfHasRelativeLengths() const;
 
-        DECLARE_ANIMATED_PROPERTY(SVGUseElement, SVGNames::xAttr, SVGLength, X, x)
-        DECLARE_ANIMATED_PROPERTY(SVGUseElement, SVGNames::yAttr, SVGLength, Y, y)
-        DECLARE_ANIMATED_PROPERTY(SVGUseElement, SVGNames::widthAttr, SVGLength, Width, width)
-        DECLARE_ANIMATED_PROPERTY(SVGUseElement, SVGNames::heightAttr, SVGLength, Height, height)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGUseElement, SVGNames::xAttr, SVGLength, X, x)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGUseElement, SVGNames::yAttr, SVGLength, Y, y)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGUseElement, SVGNames::widthAttr, SVGLength, Width, width)
+        DECLARE_ANIMATED_PROPERTY_NEW(SVGUseElement, SVGNames::heightAttr, SVGLength, Height, height)
 
         // SVGURIReference
         DECLARE_ANIMATED_PROPERTY(SVGUseElement, XLinkNames::hrefAttr, String, Href, href)
diff --git a/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h b/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h
new file mode 100644 (file)
index 0000000..f4ae3e4
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedListPropertyTearOff_h
+#define SVGAnimatedListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedProperty.h"
+#include "SVGAnimatedPropertyDescription.h"
+#include "SVGListPropertyTearOff.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGPropertyTearOff;
+
+template<typename PropertyType>
+class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty {
+public:
+    SVGProperty* baseVal()
+    {
+        if (!m_baseVal)
+            m_baseVal = SVGListPropertyTearOff<PropertyType>::create(this, BaseValRole, m_property);
+        return m_baseVal.get();
+    }
+
+    SVGProperty* animVal()
+    {
+        if (!m_animVal)
+            m_animVal = SVGListPropertyTearOff<PropertyType>::create(this, AnimValRole, m_property);
+        return m_animVal.get();
+    }
+
+    // FIXME: No animVal support.
+    void setBaseVal(const PropertyType& property) { m_property = property; }
+    void setAnimVal(const PropertyType&) { }
+
+    virtual int removeItemFromList(SVGProperty* property, bool shouldSynchronizeWrappers)
+    {
+        // FIXME: No animVal support.
+        if (!m_baseVal)
+            return -1;
+
+        typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff;
+        return static_pointer_cast<SVGListPropertyTearOff<PropertyType> >(m_baseVal)->removeItemFromList(static_cast<ListItemTearOff*>(property), shouldSynchronizeWrappers);
+    }
+
+    void detachListWrappers(unsigned newListSize)
+    {
+        if (m_baseVal)
+            static_pointer_cast<SVGListPropertyTearOff<PropertyType> >(m_baseVal)->detachListWrappers(newListSize);
+        if (m_animVal)
+            static_pointer_cast<SVGListPropertyTearOff<PropertyType> >(m_animVal)->detachListWrappers(newListSize);
+    }
+
+private:
+    friend class SVGAnimatedProperty;
+
+    static PassRefPtr<SVGAnimatedListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& property)
+    {
+        ASSERT(contextElement);
+        return adoptRef(new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, property));
+    }
+
+    SVGAnimatedListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& property)
+        : SVGAnimatedProperty(contextElement, attributeName)
+        , m_property(property)
+    {
+    }
+
+private:
+    PropertyType& m_property;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedListPropertyTearOff_h
diff --git a/WebCore/svg/properties/SVGAnimatedProperty.h b/WebCore/svg/properties/SVGAnimatedProperty.h
new file mode 100644 (file)
index 0000000..5276163
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedProperty_h
+#define SVGAnimatedProperty_h
+
+#if ENABLE(SVG)
+#include "QualifiedName.h"
+#include "SVGAnimatedPropertyDescription.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class SVGElement;
+class SVGProperty;
+
+class SVGAnimatedProperty : public RefCounted<SVGAnimatedProperty> {
+public:
+    SVGElement* contextElement() const { return m_contextElement.get(); }
+    const QualifiedName& attributeName() const { return m_attributeName; }
+
+    virtual int removeItemFromList(SVGProperty*, bool)
+    {
+        ASSERT_NOT_REACHED();
+        return -1;
+    }
+
+    // Caching facilities.
+    typedef HashMap<SVGAnimatedPropertyDescription, RefPtr<SVGAnimatedProperty>, SVGAnimatedPropertyDescriptionHash, SVGAnimatedPropertyDescriptionHashTraits> Cache;
+
+    virtual ~SVGAnimatedProperty()
+    {
+        // Remove wrapper from cache.
+        Cache* cache = animatedPropertyCache();
+        const Cache::const_iterator end = cache->end();
+        for (Cache::const_iterator it = cache->begin(); it != end; ++it) {
+            if (it->second == this) {
+                cache->remove(it->first);
+                break;
+            }
+        }
+    }
+
+    template<typename TearOffType, typename PropertyType>
+    static PassRefPtr<TearOffType> lookupOrCreateWrapper(SVGElement* element, const QualifiedName& attributeName, PropertyType& property)
+    {
+        SVGAnimatedPropertyDescription key(element, attributeName.localName());
+        RefPtr<SVGAnimatedProperty> wrapper = animatedPropertyCache()->get(key);
+        if (!wrapper) {
+            wrapper = TearOffType::create(element, attributeName, property);
+            animatedPropertyCache()->set(key, wrapper);
+        }
+
+        return static_pointer_cast<TearOffType>(wrapper).release();
+    }
+
+    template<typename TearOffType>
+    static TearOffType* lookupWrapper(SVGElement* element, const QualifiedName& attributeName)
+    {
+        SVGAnimatedPropertyDescription key(element, attributeName.localName());
+        return static_pointer_cast<TearOffType>(animatedPropertyCache()->get(key)).get();
+    }
+
+protected:
+    SVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName)
+        : m_contextElement(contextElement)
+        , m_attributeName(attributeName)
+    {
+    }
+
+    RefPtr<SVGProperty> m_baseVal;
+    RefPtr<SVGProperty> m_animVal;
+
+private:
+    static Cache* animatedPropertyCache()
+    {
+        static Cache* s_cache = new Cache;                
+        return s_cache;
+    }
+
+    RefPtr<SVGElement> m_contextElement;
+    const QualifiedName& m_attributeName;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedProperty_h
diff --git a/WebCore/svg/properties/SVGAnimatedPropertyDescription.h b/WebCore/svg/properties/SVGAnimatedPropertyDescription.h
new file mode 100644 (file)
index 0000000..9895054
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedPropertyDescription_h
+#define SVGAnimatedPropertyDescription_h
+
+#if ENABLE(SVG)
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class SVGElement;
+
+struct SVGAnimatedPropertyDescription {            
+    // Empty value
+    SVGAnimatedPropertyDescription()
+        : m_element(0)
+        , m_attributeName(0)
+    {
+    }
+
+    // Deleted value
+    SVGAnimatedPropertyDescription(WTF::HashTableDeletedValueType)
+        : m_element(reinterpret_cast<SVGElement*>(-1))
+    {
+    }
+
+    bool isHashTableDeletedValue() const
+    {
+        return m_element == reinterpret_cast<SVGElement*>(-1);
+    }
+
+    SVGAnimatedPropertyDescription(SVGElement* element, const AtomicString& attributeName)
+        : m_element(element)
+        , m_attributeName(attributeName.impl())
+    {
+        ASSERT(m_element);
+        ASSERT(m_attributeName);
+    }
+
+    bool operator==(const SVGAnimatedPropertyDescription& other) const
+    {
+        return m_element == other.m_element && m_attributeName == other.m_attributeName;
+    }
+
+    SVGElement* m_element;
+    AtomicStringImpl* m_attributeName;
+};
+
+struct SVGAnimatedPropertyDescriptionHash {
+    static unsigned hash(const SVGAnimatedPropertyDescription& key)
+    {
+        return StringImpl::computeHash(reinterpret_cast<const UChar*>(&key), sizeof(SVGAnimatedPropertyDescription) / sizeof(UChar));
+    }
+
+    static bool equal(const SVGAnimatedPropertyDescription& a, const SVGAnimatedPropertyDescription& b)
+    {
+        return a == b;
+    }
+
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+struct SVGAnimatedPropertyDescriptionHashTraits : WTF::GenericHashTraits<SVGAnimatedPropertyDescription> {
+    static const bool emptyValueIsZero = true;
+
+    static void constructDeletedValue(SVGAnimatedPropertyDescription& slot)
+    {
+        new (&slot) SVGAnimatedPropertyDescription(WTF::HashTableDeletedValue);
+    }
+
+    static bool isDeletedValue(const SVGAnimatedPropertyDescription& value)
+    {
+        return value.isHashTableDeletedValue();
+    }
+};
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedPropertyDescription_h
diff --git a/WebCore/svg/properties/SVGAnimatedPropertyMacros.h b/WebCore/svg/properties/SVGAnimatedPropertyMacros.h
new file mode 100644 (file)
index 0000000..81cba71
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedPropertyMacros_h
+#define SVGAnimatedPropertyMacros_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedListPropertyTearOff.h"
+#include "SVGAnimatedPropertySynchronizer.h"
+#include "SVGAnimatedPropertyTearOff.h"
+#include "SVGPropertyTraits.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+struct SVGSynchronizableAnimatedProperty {
+    SVGSynchronizableAnimatedProperty()
+        : value(SVGPropertyTraits<PropertyType>::initialValue())
+        , shouldSynchronize(false)
+    {
+    }
+
+    template<typename ConstructorParameter1>
+    SVGSynchronizableAnimatedProperty(const ConstructorParameter1& value1)
+        : value(value1)
+        , shouldSynchronize(false)
+    {
+    }
+
+    template<typename ConstructorParameter1, typename ConstructorParameter2>
+    SVGSynchronizableAnimatedProperty(const ConstructorParameter1& value1, const ConstructorParameter2& value2)
+        : value(value1, value2)
+        , shouldSynchronize(false)
+    {
+    }
+
+    PropertyType value;
+    bool shouldSynchronize : 1;
+};
+
+// FIXME: These macros should be removed, after the transition to the new SVGAnimatedProperty concept is finished.
+#define DECLARE_ANIMATED_PROPERTY_NEW_SHARED(OwnerType, DOMAttribute, TearOffType, PropertyType, UpperProperty, LowerProperty) \
+public: \
+PropertyType& LowerProperty() const \
+{ \
+    return m_##LowerProperty.value; \
+} \
+\
+PropertyType& LowerProperty##BaseValue() const \
+{ \
+    return m_##LowerProperty.value; \
+} \
+\
+void set##UpperProperty##BaseValue(const PropertyType& type) \
+{ \
+    m_##LowerProperty.value = type; \
+    invalidateSVGAttributes(); \
+} \
+\
+void synchronize##UpperProperty() \
+{ \
+    if (!m_##LowerProperty.shouldSynchronize) \
+         return; \
+    AtomicString value(SVGPropertyTraits<PropertyType>::toString(LowerProperty##BaseValue())); \
+    SVGAnimatedPropertySynchronizer<IsDerivedFromSVGElement<OwnerType>::value>::synchronize(this, DOMAttribute, value); \
+} \
+\
+PassRefPtr<TearOffType> LowerProperty##Animated() \
+{ \
+    m_##LowerProperty.shouldSynchronize = true; \
+    return SVGAnimatedProperty::lookupOrCreateWrapper<TearOffType, PropertyType>(this, DOMAttribute, m_##LowerProperty.value); \
+} \
+private: \
+    mutable SVGSynchronizableAnimatedProperty<PropertyType> m_##LowerProperty;
+
+#define DECLARE_ANIMATED_PROPERTY_NEW(OwnerType, DOMAttribute, PropertyType, UpperProperty, LowerProperty) \
+DECLARE_ANIMATED_PROPERTY_NEW_SHARED(OwnerType, DOMAttribute, SVGAnimatedPropertyTearOff<PropertyType>, PropertyType, UpperProperty, LowerProperty)
+
+#define DECLARE_ANIMATED_LIST_PROPERTY_NEW(OwnerType, DOMAttribute, PropertyType, UpperProperty, LowerProperty) \
+DECLARE_ANIMATED_PROPERTY_NEW_SHARED(OwnerType, DOMAttribute, SVGAnimatedListPropertyTearOff<PropertyType>, PropertyType, UpperProperty, LowerProperty) \
+\
+void detachAnimated##UpperProperty##ListWrappers(unsigned newListSize) \
+{ \
+    SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGAnimatedListPropertyTearOff<PropertyType> >(this, DOMAttribute); \
+    if (!wrapper) \
+        return; \
+    static_cast<SVGAnimatedListPropertyTearOff<PropertyType>*>(wrapper)->detachListWrappers(newListSize); \
+}
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedPropertyMacros_h
diff --git a/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h b/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h
new file mode 100644 (file)
index 0000000..02ce371
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGAnimatedPropertyTearOff_h
+#define SVGAnimatedPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedProperty.h"
+#include "SVGAnimatedPropertyDescription.h"
+#include "SVGPropertyTearOff.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGAnimatedPropertyTearOff : public SVGAnimatedProperty {
+public:
+    SVGProperty* baseVal()
+    {
+        if (!m_baseVal)
+            m_baseVal = SVGPropertyTearOff<PropertyType>::create(this, BaseValRole, m_property);
+        return m_baseVal.get();
+    }
+
+    SVGProperty* animVal()
+    {
+        if (!m_animVal)
+            m_animVal = SVGPropertyTearOff<PropertyType>::create(this, AnimValRole, m_property);
+        return m_animVal.get();
+    }
+
+    // FIXME: No animVal support.
+    void setBaseVal(const PropertyType& property) { m_property = property; }
+    void setAnimVal(const PropertyType&) { }
+
+private:
+    friend class SVGAnimatedProperty;
+
+    static PassRefPtr<SVGAnimatedPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& property)
+    {
+        ASSERT(contextElement);
+        return adoptRef(new SVGAnimatedPropertyTearOff<PropertyType>(contextElement, attributeName, property));
+    }
+
+    SVGAnimatedPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& property)
+        : SVGAnimatedProperty(contextElement, attributeName)
+        , m_property(property)
+    {
+    }
+
+private:
+    PropertyType& m_property;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedPropertyTearOff_h
diff --git a/WebCore/svg/properties/SVGListPropertyTearOff.h b/WebCore/svg/properties/SVGListPropertyTearOff.h
new file mode 100644 (file)
index 0000000..f861074
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGListPropertyTearOff_h
+#define SVGListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "ExceptionCode.h"
+#include "SVGAnimatedProperty.h"
+#include "SVGPropertyTearOff.h"
+#include "SVGPropertyTraits.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGAnimatedListPropertyTearOff;
+
+template<typename PropertyType>
+class SVGListPropertyTearOff : public SVGProperty {
+public:
+    typedef SVGListPropertyTearOff<PropertyType> Self;
+
+    typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
+    typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
+    typedef PassRefPtr<ListItemTearOff> PassListItemTearOff;
+    typedef Vector<RefPtr<ListItemTearOff> > ListWrapperCache;
+
+    static PassRefPtr<Self> create(SVGAnimatedProperty* animatedProperty, SVGPropertyRole role, PropertyType& values)
+    {
+        ASSERT(animatedProperty);
+        return adoptRef(new Self(animatedProperty, role, values));
+    }
+
+    int removeItemFromList(ListItemTearOff* removeItem, bool shouldSynchronizeWrappers)
+    {
+        // Lookup item in cache and remove its corresponding wrapper.
+        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 != removeItem)
+                continue;
+
+            item->detachWrapper();
+            m_wrappers.remove(i);
+            m_values.remove(i);
+
+            if (shouldSynchronizeWrappers)
+                commitChange();
+
+            return i;
+        }
+
+        return -1;
+    }
+
+    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();
+    }
+
+    // SVGList API
+    void clear(ExceptionCode& ec)
+    {
+        if (m_role == AnimValRole) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return;
+        }
+
+        detachListWrappers(0);
+        m_values.clear();
+    }
+
+    unsigned numberOfItems() const
+    {
+        return m_values.size();
+    }
+
+    PassListItemTearOff initialize(PassListItemTearOff passNewItem, ExceptionCode& ec)
+    {
+        if (m_role == AnimValRole) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return 0;
+        }
+
+        // Not specified, but FF/Opera do it this way, and it's just sane.
+        if (!passNewItem) {
+            ec = TYPE_MISMATCH_ERR;
+            return 0;
+        }
+
+        RefPtr<ListItemTearOff> newItem = passNewItem;
+        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.
+        removeItemFromListIfNeeded(newItem.get(), 0);
+
+        // Spec: Clears all existing current items from the list and re-initializes the list to hold the single item specified by the parameter.
+        detachListWrappers(0);
+        m_values.clear();
+        
+        m_values.append(newItem->propertyReference());
+        m_wrappers.append(newItem);
+
+        commitChange();
+        return newItem.release();
+    }
+
+    PassListItemTearOff getItem(unsigned index, ExceptionCode& ec)
+    {
+        if (index >= m_values.size()) {
+            ec = INDEX_SIZE_ERR;
+            return 0;
+        }
+
+        // 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(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(m_animatedProperty.get(), UndefinedRole, m_values.at(index));
+            m_wrappers.at(index) = wrapper;
+        }
+
+        return wrapper.release();
+    }
+
+    PassListItemTearOff insertItemBefore(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+    {
+        if (m_role == AnimValRole) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return 0;
+        }
+
+        // Not specified, but FF/Opera do it this way, and it's just sane.
+        if (!passNewItem) {
+            ec = TYPE_MISMATCH_ERR;
+            return 0;
+        }
+
+        // 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 > m_values.size())
+             index = m_values.size();
+
+        RefPtr<ListItemTearOff> newItem = passNewItem;
+        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.
+        removeItemFromListIfNeeded(newItem.get(), &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.
+        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.
+        m_wrappers.insert(index, newItem);
+
+        commitChange();
+        return newItem.release();
+    }
+
+    PassListItemTearOff replaceItem(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+    {
+        if (m_role == AnimValRole) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return 0;
+        }
+
+        if (index >= m_values.size()) {
+            ec = INDEX_SIZE_ERR;
+            return 0;
+        }
+
+        // Not specified, but FF/Opera do it this way, and it's just sane.
+        if (!passNewItem) {
+            ec = TYPE_MISMATCH_ERR;
+            return 0;
+        }
+
+        RefPtr<ListItemTearOff> newItem = passNewItem;
+        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.
+        // 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.
+        removeItemFromListIfNeeded(newItem.get(), &index);
+
+        // Detach the existing wrapper.
+        RefPtr<ListItemTearOff>& oldItem = m_wrappers.at(index);
+        if (oldItem)
+            oldItem->detachWrapper();
+
+        // Update the value and the wrapper at the desired position 'index'. 
+        m_values.at(index) = newItem->propertyReference();
+        m_wrappers.at(index) = newItem;
+
+        commitChange();
+        return newItem.release();
+    }
+
+    PassListItemTearOff removeItem(unsigned index, ExceptionCode& ec)
+    {
+        if (m_role == AnimValRole) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return 0;
+        }
+
+        if (index >= m_values.size()) {
+            ec = INDEX_SIZE_ERR;
+            return 0;
+        }
+
+        ASSERT(m_values.size() == m_wrappers.size());
+
+        // Detach the existing wrapper.
+        RefPtr<ListItemTearOff>& oldItem = m_wrappers.at(index);
+        if (oldItem) {
+            oldItem->detachWrapper();
+            m_wrappers.remove(index);
+        }
+
+        m_values.remove(index);
+
+        commitChange();
+        return oldItem.release();
+    }
+
+    PassListItemTearOff appendItem(PassListItemTearOff passNewItem, ExceptionCode& ec)
+    {
+        if (m_role == AnimValRole) {
+            ec = NO_MODIFICATION_ALLOWED_ERR;
+            return 0;
+        }
+
+        // Not specified, but FF/Opera do it this way, and it's just sane.
+        if (!passNewItem) {
+            ec = TYPE_MISMATCH_ERR;
+            return 0;
+        }
+
+        RefPtr<ListItemTearOff> newItem = passNewItem;
+        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.
+        removeItemFromListIfNeeded(newItem.get(), 0);
+
+        // Append the value and wrapper at the end of the list.
+        m_values.append(newItem->propertyReference());
+        m_wrappers.append(newItem);
+
+        commitChange();
+        return newItem.release();
+    }
+
+private:
+    SVGListPropertyTearOff(SVGAnimatedProperty* animatedProperty, SVGPropertyRole role, PropertyType& values)
+        : m_animatedProperty(animatedProperty)
+        , m_role(role)
+        , m_values(values)
+    {
+        if (!values.isEmpty())
+            m_wrappers.fill(0, values.size());
+    }
+
+    void commitChange()
+    {
+        // Update existing wrappers, as the index in the m_values list has changed.
+        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->setAnimatedProperty(m_animatedProperty.get());
+            item->setValue(m_values.at(i));
+        }
+
+        ASSERT(m_animatedProperty);
+        SVGElement* contextElement = m_animatedProperty->contextElement();
+        ASSERT(contextElement);
+        contextElement->invalidateSVGAttributes();
+        contextElement->svgAttributeChanged(m_animatedProperty->attributeName());
+    }
+
+    void removeItemFromListIfNeeded(ListItemTearOff* newItem, unsigned* indexToModify)
+    {
+        // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+        SVGAnimatedProperty* animatedPropertyOfItem = newItem->animatedProperty();
+        if (!animatedPropertyOfItem)
+            return;
+
+        // 'newItem' is already living in another list. If it's not our list, synchronize the other lists wrappers after the removal.
+        bool livesInOtherList = animatedPropertyOfItem != m_animatedProperty;
+        int removedIndex = animatedPropertyOfItem->removeItemFromList(newItem, livesInOtherList);
+        ASSERT(removedIndex != -1);
+
+        if (!indexToModify)
+            return;
+
+        // If the item lived in our list, adjust the insertion index.
+        if (!livesInOtherList) {
+            unsigned& index = *indexToModify;
+            // Spec: If the item is already in this list, note that the index of the item to (replace|insert before) is before the removal of the item.
+            if (static_cast<unsigned>(removedIndex) < index)
+                --index;
+        }
+    }
+
+private:
+    // Back pointer to the animated property that created us
+    // For example (text.x.baseVal): m_animatedProperty points to the 'x' SVGAnimatedLengthList object
+    RefPtr<SVGAnimatedProperty> m_animatedProperty;
+
+    // The role of this property (baseVal or animVal)
+    SVGPropertyRole m_role;
+
+    // For the example above (text.x.baseVal): A reference to the SVGLengthList& stored in the SVGTextElement, which we can directly modify
+    PropertyType& m_values;
+
+    // A list of wrappers, which is always in sync between m_values.
+    ListWrapperCache m_wrappers;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGListPropertyTearOff_h
diff --git a/WebCore/svg/properties/SVGProperty.h b/WebCore/svg/properties/SVGProperty.h
new file mode 100644 (file)
index 0000000..43167b7
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGProperty_h
+#define SVGProperty_h
+
+#if ENABLE(SVG)
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+enum SVGPropertyRole {
+    UndefinedRole,
+    BaseValRole,
+    AnimValRole
+};
+
+class SVGProperty : public RefCounted<SVGProperty> {
+public:
+    virtual ~SVGProperty() { }
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGProperty_h
diff --git a/WebCore/svg/properties/SVGPropertyTearOff.h b/WebCore/svg/properties/SVGPropertyTearOff.h
new file mode 100644 (file)
index 0000000..1f85a48
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGPropertyTearOff_h
+#define SVGPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGElement.h"
+#include "SVGProperty.h"
+
+namespace WebCore {
+
+class SVGAnimatedProperty;
+
+template<typename PropertyType>
+class SVGPropertyTearOff : public SVGProperty {
+public:
+    typedef SVGPropertyTearOff<PropertyType> Self;
+
+    // Used for [SVGAnimatedProperty] types (for example: SVGAnimatedLength::baseVal()).
+    // Also used for list tear offs (for example: text.x.baseVal.getItem(0)).
+    static PassRefPtr<Self> create(SVGAnimatedProperty* animatedProperty, SVGPropertyRole, PropertyType& value)
+    {
+        ASSERT(animatedProperty);
+        return adoptRef(new Self(animatedProperty, value));
+    }
+
+    // Used for [SVGLiveProperty] types (for example: SVGSVGElement::createSVGLength()).
+    static PassRefPtr<Self> create(const PropertyType& initialValue)
+    {
+        return adoptRef(new Self(initialValue));
+    }
+
+    PropertyType& propertyReference() { return *m_value; }
+    SVGAnimatedProperty* animatedProperty() const { return m_animatedProperty.get(); }
+
+    virtual int removeItemFromList(SVGAnimatedProperty*) { return -1; }
+
+    // Used only by the list tear offs!
+    void setValue(PropertyType& value)
+    {
+        if (m_valueIsCopy)
+            delete m_value;
+        m_valueIsCopy = false;
+        m_value = &value;
+    }
+
+    void setAnimatedProperty(SVGAnimatedProperty* animatedProperty) { m_animatedProperty = animatedProperty; }
+
+    void commitChange()
+    {
+        if (!m_animatedProperty || m_valueIsCopy)
+            return;
+        SVGElement* contextElement = m_animatedProperty->contextElement();
+        ASSERT(contextElement);
+        contextElement->invalidateSVGAttributes();
+        contextElement->svgAttributeChanged(m_animatedProperty->attributeName());
+    }
+
+    SVGElement* contextElement() const
+    {
+        if (!m_animatedProperty || m_valueIsCopy)
+            return 0;
+        return m_animatedProperty->contextElement();
+    }
+
+    void detachWrapper()
+    {
+        // Switch from a live value, to a non-live value.
+        // For example: <text x="50"/>
+        // var item = text.x.baseVal.getItem(0);
+        // text.setAttribute("x", "100");
+        // item.value still has to report '50' and it has to be possible to modify 'item'
+        // w/o changing the "new item" (with x=100) in the text element.
+        // Whenever the XML DOM modifies the "x" attribute, all existing wrappers are detached, using this function.
+        ASSERT(!m_valueIsCopy);
+        m_value = new PropertyType(*m_value);
+        m_valueIsCopy = true;
+    }
+
+private:
+    SVGPropertyTearOff(SVGAnimatedProperty* animatedProperty, PropertyType& value)
+        : m_animatedProperty(animatedProperty)
+        , m_value(&value)
+        , m_valueIsCopy(false)
+    {
+        // Using operator & is completly fine, as SVGAnimatedProperty owns this reference,
+        // and we're guaranteed to live as long as SVGAnimatedProperty does.
+    }
+
+    SVGPropertyTearOff(const PropertyType& initialValue)
+        : m_animatedProperty(0)
+        , m_value(new PropertyType(initialValue))
+        , m_valueIsCopy(true)
+    {
+    }
+
+    virtual ~SVGPropertyTearOff()
+    {
+        if (m_valueIsCopy)
+            delete m_value;
+    }
+
+    RefPtr<SVGAnimatedProperty> m_animatedProperty;
+    PropertyType* m_value;
+    bool m_valueIsCopy : 1;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGPropertyTearOff_h
diff --git a/WebCore/svg/properties/SVGPropertyTraits.h b/WebCore/svg/properties/SVGPropertyTraits.h
new file mode 100644 (file)
index 0000000..e728810
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SVGPropertyTraits_h
+#define SVGPropertyTraits_h
+
+#if ENABLE(SVG)
+#include "SVGLength.h"
+#include "SVGLengthList.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+struct SVGPropertyTraits { };
+
+// SVGAnimatedLength
+template<>
+struct SVGPropertyTraits<SVGLength> {
+    static SVGLength& initialValue()
+    {
+        DEFINE_STATIC_LOCAL(SVGLength, s_initialValue, ());
+        s_initialValue = SVGLength();
+        return s_initialValue;
+    }
+
+    static String toString(const SVGLength& type) { return type.valueAsString(); }
+};
+
+// SVGAnimatedLengthList
+template<>
+struct SVGPropertyTraits<SVGLengthList> {
+    typedef SVGLength ListItemType;
+
+    static SVGLengthList& initialValue()
+    {
+        DEFINE_STATIC_LOCAL(SVGLengthList, s_initialValue, ());
+        s_initialValue = SVGLengthList();
+        return s_initialValue;
+    }
+
+    static String toString(const SVGLengthList& type) { return type.valueAsString(); }
+};
+
+}
+
+#endif
+#endif