summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/svg/properties
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/svg/properties
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/svg/properties')
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h116
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h72
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedProperty.h105
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h100
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h151
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h60
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h71
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h73
-rw-r--r--Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h64
-rw-r--r--Source/WebCore/svg/properties/SVGListProperty.h428
-rw-r--r--Source/WebCore/svg/properties/SVGListPropertyTearOff.h190
-rw-r--r--Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp111
-rw-r--r--Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h160
-rw-r--r--Source/WebCore/svg/properties/SVGProperty.h45
-rw-r--r--Source/WebCore/svg/properties/SVGPropertyTearOff.h130
-rw-r--r--Source/WebCore/svg/properties/SVGPropertyTraits.h65
-rw-r--r--Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h114
-rw-r--r--Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h67
-rw-r--r--Source/WebCore/svg/properties/SVGStaticPropertyWithParentTearOff.h72
-rw-r--r--Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h83
20 files changed, 2277 insertions, 0 deletions
diff --git a/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h
new file mode 100644
index 0000000..40d3888
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h
@@ -0,0 +1,116 @@
+/*
+ * 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 "SVGListPropertyTearOff.h"
+#include "SVGStaticListPropertyTearOff.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGPropertyTearOff;
+
+template<typename PropertyType>
+class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty {
+public:
+ typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
+ typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
+ typedef Vector<RefPtr<ListItemTearOff> > ListWrapperCache;
+
+ SVGProperty* baseVal()
+ {
+ if (!m_baseVal)
+ m_baseVal = SVGListPropertyTearOff<PropertyType>::create(this, BaseValRole);
+ return m_baseVal.get();
+ }
+
+ SVGProperty* animVal()
+ {
+ if (!m_animVal)
+ m_animVal = SVGListPropertyTearOff<PropertyType>::create(this, AnimValRole);
+ return m_animVal.get();
+ }
+
+ virtual bool isAnimatedListTearOff() const { return true; }
+
+ int removeItemFromList(SVGProperty* property, bool shouldSynchronizeWrappers)
+ {
+ // This should ever be called for our baseVal, as animVal can't modify the list.
+ typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff;
+ return static_pointer_cast<SVGListPropertyTearOff<PropertyType> >(m_baseVal)->removeItemFromList(static_cast<ListItemTearOff*>(property), shouldSynchronizeWrappers);
+ }
+
+ 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();
+ }
+
+ PropertyType& values() { return m_values; }
+ ListWrapperCache& wrappers() { return m_wrappers; }
+
+private:
+ friend class SVGAnimatedProperty;
+
+ static PassRefPtr<SVGAnimatedListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& values)
+ {
+ ASSERT(contextElement);
+ return adoptRef(new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, values));
+ }
+
+protected:
+ SVGAnimatedListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& values)
+ : SVGAnimatedProperty(contextElement, attributeName)
+ , m_values(values)
+ {
+ if (!values.isEmpty())
+ m_wrappers.fill(0, values.size());
+ }
+
+ PropertyType& m_values;
+
+ // FIXME: The list wrapper cache is shared between baseVal/animVal. If we implement animVal,
+ // we need two seperated wrapper caches if the attribute gets animated.
+ ListWrapperCache m_wrappers;
+
+ RefPtr<SVGProperty> m_baseVal;
+ RefPtr<SVGProperty> m_animVal;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedListPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h
new file mode 100644
index 0000000..f515ab4
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h
@@ -0,0 +1,72 @@
+/*
+ * 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 SVGAnimatedPathSegListPropertyTearOff_h
+#define SVGAnimatedPathSegListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedListPropertyTearOff.h"
+#include "SVGPathSegList.h"
+#include "SVGPathSegListPropertyTearOff.h"
+
+namespace WebCore {
+
+class SVGPathSegListPropertyTearOff;
+
+class SVGAnimatedPathSegListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGPathSegList> {
+public:
+ SVGProperty* baseVal(SVGPathSegRole role)
+ {
+ if (!m_baseVal)
+ m_baseVal = SVGPathSegListPropertyTearOff::create(this, BaseValRole, role);
+ return m_baseVal.get();
+ }
+
+ SVGProperty* animVal(SVGPathSegRole role)
+ {
+ if (!m_animVal)
+ m_animVal = SVGPathSegListPropertyTearOff::create(this, AnimValRole, role);
+ return m_animVal.get();
+ }
+
+ int removeItemFromList(const RefPtr<SVGPathSeg>& segment, bool shouldSynchronizeWrappers)
+ {
+ // This should ever be called for our baseVal, as animVal can't modify the list.
+ return static_pointer_cast<SVGPathSegListPropertyTearOff>(m_baseVal)->removeItemFromList(segment, shouldSynchronizeWrappers);
+ }
+
+private:
+ friend class SVGAnimatedProperty;
+
+ static PassRefPtr<SVGAnimatedPathSegListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, SVGPathSegList& values)
+ {
+ ASSERT(contextElement);
+ return adoptRef(new SVGAnimatedPathSegListPropertyTearOff(contextElement, attributeName, values));
+ }
+
+ SVGAnimatedPathSegListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, SVGPathSegList& values)
+ : SVGAnimatedListPropertyTearOff<SVGPathSegList>(contextElement, attributeName, values)
+ {
+ }
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedPathSegListPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGAnimatedProperty.h b/Source/WebCore/svg/properties/SVGAnimatedProperty.h
new file mode 100644
index 0000000..1c25935
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedProperty.h
@@ -0,0 +1,105 @@
+/*
+ * 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 "SVGElement.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; }
+
+ void commitChange()
+ {
+ ASSERT(m_contextElement);
+ m_contextElement->invalidateSVGAttributes();
+ m_contextElement->svgAttributeChanged(m_attributeName);
+ }
+
+ virtual bool isAnimatedListTearOff() const { return false; }
+
+ // 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, const AtomicString& attributeIdentifier, PropertyType& property)
+ {
+ SVGAnimatedPropertyDescription key(element, attributeIdentifier);
+ 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 AtomicString& attributeIdentifier)
+ {
+ SVGAnimatedPropertyDescription key(element, attributeIdentifier);
+ return static_pointer_cast<TearOffType>(animatedPropertyCache()->get(key)).get();
+ }
+
+protected:
+ SVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName)
+ : m_contextElement(contextElement)
+ , m_attributeName(attributeName)
+ {
+ }
+
+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/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h b/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h
new file mode 100644
index 0000000..6fb5e66
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h
@@ -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 WTF::StringHasher::createBlobHash<sizeof(SVGAnimatedPropertyDescription)>(&key);
+ }
+
+ 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/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h b/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h
new file mode 100644
index 0000000..d5ba21a
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h
@@ -0,0 +1,151 @@
+/*
+ * 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 "SVGAnimatedPropertySynchronizer.h"
+#include "SVGPropertyTraits.h"
+
+namespace WebCore {
+
+// GetOwnerElementForType implementation
+template<typename OwnerType, bool isDerivedFromSVGElement>
+struct GetOwnerElementForType;
+
+template<typename OwnerType>
+struct GetOwnerElementForType<OwnerType, true> {
+ static SVGElement* ownerElement(OwnerType* type)
+ {
+ return type;
+ }
+};
+
+template<typename OwnerType>
+struct GetOwnerElementForType<OwnerType, false> {
+ static SVGElement* ownerElement(OwnerType* type)
+ {
+ SVGElement* context = type->contextElement();
+ ASSERT(context);
+ return context;
+ }
+};
+
+// IsDerivedFromSVGElement implementation
+template<typename OwnerType>
+struct IsDerivedFromSVGElement {
+ static const bool value = true;
+};
+
+class SVGViewSpec;
+template<>
+struct IsDerivedFromSVGElement<SVGViewSpec> {
+ static const bool value = false;
+};
+
+// SVGSynchronizableAnimatedProperty implementation
+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;
+};
+
+#define DEFINE_ANIMATED_PROPERTY(OwnerType, DOMAttribute, SVGDOMAttributeIdentifier, TearOffType, PropertyType, UpperProperty, LowerProperty) \
+void OwnerType::synchronize##UpperProperty() \
+{ \
+ if (!m_##LowerProperty.shouldSynchronize) \
+ return; \
+ AtomicString value(SVGPropertyTraits<PropertyType>::toString(LowerProperty##BaseValue())); \
+ SVGElement* contextElement = GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value>::ownerElement(this); \
+ SVGAnimatedPropertySynchronizer<IsDerivedFromSVGElement<OwnerType>::value>::synchronize(contextElement, DOMAttribute, value); \
+} \
+\
+PassRefPtr<TearOffType> OwnerType::LowerProperty##Animated() \
+{ \
+ m_##LowerProperty.shouldSynchronize = true; \
+ SVGElement* contextElement = GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value>::ownerElement(this); \
+ return SVGAnimatedProperty::lookupOrCreateWrapper<TearOffType, PropertyType>(contextElement, DOMAttribute, SVGDOMAttributeIdentifier, m_##LowerProperty.value); \
+}
+
+#define DECLARE_ANIMATED_PROPERTY(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; \
+} \
+\
+PassRefPtr<TearOffType> LowerProperty##Animated(); \
+\
+private: \
+ void synchronize##UpperProperty(); \
+\
+ mutable SVGSynchronizableAnimatedProperty<PropertyType> m_##LowerProperty;
+
+#define DECLARE_ANIMATED_LIST_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \
+DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \
+void detachAnimated##UpperProperty##ListWrappers(unsigned newListSize);
+
+#define DEFINE_ANIMATED_LIST_PROPERTY(OwnerType, DOMAttribute, SVGDOMAttributeIdentifier, TearOffType, PropertyType, UpperProperty, LowerProperty) \
+DEFINE_ANIMATED_PROPERTY(OwnerType, DOMAttribute, SVGDOMAttributeIdentifier, TearOffType, PropertyType, UpperProperty, LowerProperty) \
+void OwnerType::detachAnimated##UpperProperty##ListWrappers(unsigned newListSize) \
+{ \
+ SVGElement* contextElement = GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value>::ownerElement(this); \
+ SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<TearOffType>(contextElement, DOMAttribute.localName()); \
+ if (!wrapper) \
+ return; \
+ static_cast<TearOffType*>(wrapper)->detachListWrappers(newListSize); \
+}
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedPropertyMacros_h
diff --git a/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h b/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h
new file mode 100644
index 0000000..bb52442
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedPropertySynchronizer.h
@@ -0,0 +1,60 @@
+/*
+ * 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 SVGAnimatedPropertySynchronizer_h
+#define SVGAnimatedPropertySynchronizer_h
+
+#if ENABLE(SVG)
+#include "SVGElement.h"
+
+namespace WebCore {
+
+// Helper template used for synchronizing SVG <-> XML properties
+template<bool isDerivedFromSVGElement>
+struct SVGAnimatedPropertySynchronizer {
+ static void synchronize(SVGElement*, const QualifiedName&, const AtomicString&);
+};
+
+template<>
+struct SVGAnimatedPropertySynchronizer<true> {
+ static void synchronize(SVGElement* ownerElement, const QualifiedName& attrName, const AtomicString& value)
+ {
+ NamedNodeMap* namedAttrMap = ownerElement->attributes(false);
+ Attribute* old = namedAttrMap->getAttributeItem(attrName);
+ if (old && value.isNull())
+ namedAttrMap->removeAttribute(old->name());
+ else if (!old && !value.isNull())
+ namedAttrMap->addAttribute(ownerElement->createAttribute(attrName, value));
+ else if (old && !value.isNull())
+ old->setValue(value);
+ }
+};
+
+template<>
+struct SVGAnimatedPropertySynchronizer<false> {
+ static void synchronize(SVGElement*, const QualifiedName&, const AtomicString&)
+ {
+ // no-op, for types not inheriting from Element, thus nothing to synchronize
+ }
+};
+
+};
+
+#endif
+#endif
diff --git a/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h
new file mode 100644
index 0000000..252a4b4
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h
@@ -0,0 +1,71 @@
+/*
+ * 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 "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();
+ }
+
+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;
+
+ RefPtr<SVGProperty> m_baseVal;
+ RefPtr<SVGProperty> m_animVal;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h
new file mode 100644
index 0000000..930569e
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h
@@ -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 SVGAnimatedStaticPropertyTearOff_h
+#define SVGAnimatedStaticPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedProperty.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGAnimatedStaticPropertyTearOff : public SVGAnimatedProperty {
+public:
+ PropertyType& baseVal()
+ {
+ return m_property;
+ }
+
+ PropertyType& animVal()
+ {
+ // FIXME: No animVal support.
+ return m_property;
+ }
+
+ void setBaseVal(const PropertyType& property)
+ {
+ m_property = property;
+ commitChange();
+ }
+
+ // FIXME: No animVal support.
+ void setAnimVal(const PropertyType&) { }
+
+private:
+ friend class SVGAnimatedProperty;
+
+ static PassRefPtr<SVGAnimatedStaticPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& property)
+ {
+ ASSERT(contextElement);
+ return adoptRef(new SVGAnimatedStaticPropertyTearOff<PropertyType>(contextElement, attributeName, property));
+ }
+
+ SVGAnimatedStaticPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& property)
+ : SVGAnimatedProperty(contextElement, attributeName)
+ , m_property(property)
+ {
+ }
+
+private:
+ PropertyType& m_property;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedStaticPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h
new file mode 100644
index 0000000..2aa94c3
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h
@@ -0,0 +1,64 @@
+/*
+ * 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 SVGAnimatedTransformListPropertyTearOff_h
+#define SVGAnimatedTransformListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedListPropertyTearOff.h"
+#include "SVGTransformList.h"
+#include "SVGTransformListPropertyTearOff.h"
+
+namespace WebCore {
+
+class SVGAnimatedTransformListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGTransformList> {
+public:
+ SVGProperty* baseVal()
+ {
+ if (!m_baseVal)
+ m_baseVal = SVGTransformListPropertyTearOff::create(this, BaseValRole);
+ return m_baseVal.get();
+ }
+
+ SVGProperty* animVal()
+ {
+ if (!m_animVal)
+ m_animVal = SVGTransformListPropertyTearOff::create(this, AnimValRole);
+ return m_animVal.get();
+ }
+
+private:
+ friend class SVGAnimatedProperty;
+
+ static PassRefPtr<SVGAnimatedTransformListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, SVGTransformList& values)
+ {
+ ASSERT(contextElement);
+ return adoptRef(new SVGAnimatedTransformListPropertyTearOff(contextElement, attributeName, values));
+ }
+
+ SVGAnimatedTransformListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, SVGTransformList& values)
+ : SVGAnimatedListPropertyTearOff<SVGTransformList>(contextElement, attributeName, values)
+ {
+ }
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGAnimatedTransformListPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGListProperty.h b/Source/WebCore/svg/properties/SVGListProperty.h
new file mode 100644
index 0000000..0985ddb
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGListProperty.h
@@ -0,0 +1,428 @@
+/*
+ * 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 SVGListProperty_h
+#define SVGListProperty_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedProperty.h"
+#include "SVGException.h"
+#include "SVGPropertyTearOff.h"
+#include "SVGPropertyTraits.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGAnimatedListPropertyTearOff;
+
+template<typename PropertyType>
+class SVGListProperty : public SVGProperty {
+public:
+ typedef SVGListProperty<PropertyType> Self;
+
+ typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
+ typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
+ typedef PassRefPtr<ListItemTearOff> PassListItemTearOff;
+ typedef SVGAnimatedListPropertyTearOff<PropertyType> AnimatedListPropertyTearOff;
+ typedef typename SVGAnimatedListPropertyTearOff<PropertyType>::ListWrapperCache ListWrapperCache;
+
+ bool canAlterList(ExceptionCode& ec) const
+ {
+ if (m_role == AnimValRole) {
+ ec = NO_MODIFICATION_ALLOWED_ERR;
+ return false;
+ }
+
+ return true;
+ }
+
+ // SVGList::clear()
+ void clearValues(PropertyType& values, ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return;
+
+ values.clear();
+ commitChange();
+ }
+
+ void clearValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ if (!canAlterList(ec))
+ return;
+
+ animatedList->detachListWrappers(0);
+ animatedList->values().clear();
+ commitChange();
+ }
+
+ // SVGList::numberOfItems()
+ unsigned numberOfItemsValues(PropertyType& values) const
+ {
+ return values.size();
+ }
+
+ unsigned numberOfItemsValuesAndWrappers(AnimatedListPropertyTearOff* animatedList) const
+ {
+ ASSERT(animatedList);
+ return animatedList->values().size();
+ }
+
+ // SVGList::initialize()
+ ListItemType initializeValues(PropertyType& values, const ListItemType& newItem, ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return ListItemType();
+
+ // Spec: If the inserted item is already in a list, it is removed from its previous list before it is inserted into this list.
+ processIncomingListItemValue(newItem, 0);
+
+ // Spec: Clears all existing current items from the list and re-initializes the list to hold the single item specified by the parameter.
+ values.clear();
+ values.append(newItem);
+
+ commitChange();
+ return newItem;
+ }
+
+ PassListItemTearOff initializeValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ if (!canAlterList(ec))
+ return 0;
+
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ PropertyType& values = animatedList->values();
+ ListWrapperCache& wrappers = animatedList->wrappers();
+
+ RefPtr<ListItemTearOff> newItem = passNewItem;
+ ASSERT(values.size() == wrappers.size());
+
+ // Spec: If the inserted item is already in a list, it is removed from its previous list before it is inserted into this list.
+ processIncomingListItemWrapper(newItem, 0);
+
+ // Spec: Clears all existing current items from the list and re-initializes the list to hold the single item specified by the parameter.
+ animatedList->detachListWrappers(0);
+ values.clear();
+
+ values.append(newItem->propertyReference());
+ wrappers.append(newItem);
+
+ commitChange();
+ return newItem.release();
+ }
+
+ // SVGList::getItem()
+ bool canGetItem(PropertyType& values, unsigned index, ExceptionCode& ec)
+ {
+ if (index >= values.size()) {
+ ec = INDEX_SIZE_ERR;
+ return false;
+ }
+
+ return true;
+ }
+
+ ListItemType getItemValues(PropertyType& values, unsigned index, ExceptionCode& ec)
+ {
+ if (!canGetItem(values, index, ec))
+ return ListItemType();
+
+ // Spec: Returns the specified item from the list. The returned item is the item itself and not a copy.
+ return values.at(index);
+ }
+
+ PassListItemTearOff getItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, unsigned index, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ PropertyType& values = animatedList->values();
+ if (!canGetItem(values, index, ec))
+ return 0;
+
+ ListWrapperCache& wrappers = animatedList->wrappers();
+
+ // Spec: Returns the specified item from the list. The returned item is the item itself and not a copy.
+ // Any changes made to the item are immediately reflected in the list.
+ ASSERT(values.size() == wrappers.size());
+ RefPtr<ListItemTearOff> wrapper = wrappers.at(index);
+ if (!wrapper) {
+ // Create new wrapper, which is allowed to directly modify the item in the list, w/o copying and cache the wrapper in our map.
+ // It is also associated with our animated property, so it can notify the SVG Element which holds the SVGAnimated*List
+ // that it has been modified (and thus can call svgAttributeChanged(associatedAttributeName)).
+ wrapper = ListItemTearOff::create(animatedList, UndefinedRole, values.at(index));
+ wrappers.at(index) = wrapper;
+ }
+
+ return wrapper.release();
+ }
+
+ // SVGList::insertItemBefore()
+ ListItemType insertItemBeforeValues(PropertyType& values, const ListItemType& newItem, unsigned index, ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return ListItemType();
+
+ // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+ if (index > values.size())
+ index = values.size();
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ processIncomingListItemValue(newItem, &index);
+
+ // Spec: Inserts a new item into the list at the specified position. The index of the item before which the new item is to be
+ // inserted. The first item is number 0. If the index is equal to 0, then the new item is inserted at the front of the list.
+ values.insert(index, newItem);
+
+ commitChange();
+ return newItem;
+ }
+
+ PassListItemTearOff insertItemBeforeValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ if (!canAlterList(ec))
+ return 0;
+
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ PropertyType& values = animatedList->values();
+ ListWrapperCache& wrappers = animatedList->wrappers();
+
+ // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+ if (index > values.size())
+ index = values.size();
+
+ RefPtr<ListItemTearOff> newItem = passNewItem;
+ ASSERT(values.size() == wrappers.size());
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ processIncomingListItemWrapper(newItem, &index);
+
+ // Spec: Inserts a new item into the list at the specified position. The index of the item before which the new item is to be
+ // inserted. The first item is number 0. If the index is equal to 0, then the new item is inserted at the front of the list.
+ values.insert(index, newItem->propertyReference());
+
+ // Store new wrapper at position 'index', change its underlying value, so mutations of newItem, directly affect the item in the list.
+ wrappers.insert(index, newItem);
+
+ commitChange();
+ return newItem.release();
+ }
+
+ // SVGList::replaceItem()
+ bool canReplaceItem(PropertyType& values, unsigned index, ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return false;
+
+ if (index >= values.size()) {
+ ec = INDEX_SIZE_ERR;
+ return false;
+ }
+
+ return true;
+ }
+
+ ListItemType replaceItemValues(PropertyType& values, const ListItemType& newItem, unsigned index, ExceptionCode& ec)
+ {
+ if (!canReplaceItem(values, index, ec))
+ return ListItemType();
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ // Spec: If the item is already in this list, note that the index of the item to replace is before the removal of the item.
+ processIncomingListItemValue(newItem, &index);
+
+ if (values.isEmpty()) {
+ // 'newItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace.
+ ec = INDEX_SIZE_ERR;
+ return ListItemType();
+ }
+
+ // Update the value at the desired position 'index'.
+ values.at(index) = newItem;
+
+ commitChange();
+ return newItem;
+ }
+
+ PassListItemTearOff replaceItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ PropertyType& values = animatedList->values();
+ if (!canReplaceItem(values, index, ec))
+ return 0;
+
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ ListWrapperCache& wrappers = animatedList->wrappers();
+ ASSERT(values.size() == wrappers.size());
+ RefPtr<ListItemTearOff> newItem = passNewItem;
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ // Spec: If the item is already in this list, note that the index of the item to replace is before the removal of the item.
+ processIncomingListItemWrapper(newItem, &index);
+
+ if (values.isEmpty()) {
+ ASSERT(wrappers.isEmpty());
+ // 'passNewItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace.
+ ec = INDEX_SIZE_ERR;
+ return 0;
+ }
+
+ // Detach the existing wrapper.
+ RefPtr<ListItemTearOff> oldItem = wrappers.at(index);
+ if (oldItem)
+ oldItem->detachWrapper();
+
+ // Update the value and the wrapper at the desired position 'index'.
+ values.at(index) = newItem->propertyReference();
+ wrappers.at(index) = newItem;
+
+ commitChange();
+ return newItem.release();
+ }
+
+ // SVGList::removeItem()
+ bool canRemoveItem(PropertyType& values, unsigned index, ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return false;
+
+ if (index >= values.size()) {
+ ec = INDEX_SIZE_ERR;
+ return false;
+ }
+
+ return true;
+ }
+
+ ListItemType removeItemValues(PropertyType& values, unsigned index, ExceptionCode& ec)
+ {
+ if (!canRemoveItem(values, index, ec))
+ return ListItemType();
+
+ ListItemType oldItem = values.at(index);
+ values.remove(index);
+
+ commitChange();
+ return oldItem;
+ }
+
+ PassListItemTearOff removeItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, unsigned index, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ PropertyType& values = animatedList->values();
+ if (!canRemoveItem(values, index, ec))
+ return 0;
+
+ ListWrapperCache& wrappers = animatedList->wrappers();
+ ASSERT(values.size() == wrappers.size());
+
+ // Detach the existing wrapper.
+ RefPtr<ListItemTearOff> oldItem = wrappers.at(index);
+ if (!oldItem)
+ oldItem = ListItemTearOff::create(animatedList, UndefinedRole, values.at(index));
+
+ oldItem->detachWrapper();
+ wrappers.remove(index);
+ values.remove(index);
+
+ commitChange();
+ return oldItem.release();
+ }
+
+ // SVGList::appendItem()
+ ListItemType appendItemValues(PropertyType& values, const ListItemType& newItem, ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return ListItemType();
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ processIncomingListItemValue(newItem, 0);
+
+ // Append the value at the end of the list.
+ values.append(newItem);
+
+ commitChange();
+ return newItem;
+ }
+
+ PassListItemTearOff appendItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, PassListItemTearOff passNewItem, ExceptionCode& ec)
+ {
+ ASSERT(animatedList);
+ if (!canAlterList(ec))
+ return 0;
+
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ PropertyType& values = animatedList->values();
+ ListWrapperCache& wrappers = animatedList->wrappers();
+
+ RefPtr<ListItemTearOff> newItem = passNewItem;
+ ASSERT(values.size() == wrappers.size());
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ processIncomingListItemWrapper(newItem, 0);
+
+ // Append the value and wrapper at the end of the list.
+ values.append(newItem->propertyReference());
+ wrappers.append(newItem);
+
+ commitChange();
+ return newItem.release();
+ }
+
+ virtual SVGPropertyRole role() const { return m_role; }
+
+protected:
+ SVGListProperty(SVGPropertyRole role)
+ : m_role(role)
+ {
+ }
+
+ virtual void commitChange() = 0;
+ virtual void processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify) = 0;
+ virtual void processIncomingListItemWrapper(RefPtr<ListItemTearOff>& newItem, unsigned* indexToModify) = 0;
+
+private:
+ SVGPropertyRole m_role;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGListProperty_h
diff --git a/Source/WebCore/svg/properties/SVGListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGListPropertyTearOff.h
new file mode 100644
index 0000000..5a71735
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGListPropertyTearOff.h
@@ -0,0 +1,190 @@
+/*
+ * 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 "SVGListProperty.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGListPropertyTearOff : public SVGListProperty<PropertyType> {
+public:
+ typedef SVGListProperty<PropertyType> Base;
+
+ typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
+ typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
+ typedef PassRefPtr<ListItemTearOff> PassListItemTearOff;
+ typedef SVGAnimatedListPropertyTearOff<PropertyType> AnimatedListPropertyTearOff;
+ typedef typename SVGAnimatedListPropertyTearOff<PropertyType>::ListWrapperCache ListWrapperCache;
+
+ static PassRefPtr<SVGListPropertyTearOff<PropertyType> > create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
+ {
+ ASSERT(animatedProperty);
+ return adoptRef(new SVGListPropertyTearOff<PropertyType>(animatedProperty, role));
+ }
+
+ int removeItemFromList(ListItemTearOff* removeItem, bool shouldSynchronizeWrappers)
+ {
+ PropertyType& values = m_animatedProperty->values();
+ ListWrapperCache& wrappers = m_animatedProperty->wrappers();
+
+ // Lookup item in cache and remove its corresponding wrapper.
+ unsigned size = wrappers.size();
+ ASSERT(size == values.size());
+ for (unsigned i = 0; i < size; ++i) {
+ RefPtr<ListItemTearOff>& item = wrappers.at(i);
+ if (item != removeItem)
+ continue;
+
+ item->detachWrapper();
+ wrappers.remove(i);
+ values.remove(i);
+
+ if (shouldSynchronizeWrappers)
+ commitChange();
+
+ return i;
+ }
+
+ return -1;
+ }
+
+ // SVGList API
+ void clear(ExceptionCode& ec)
+ {
+ Base::clearValuesAndWrappers(m_animatedProperty.get(), ec);
+ }
+
+ unsigned numberOfItems() const
+ {
+ return Base::numberOfItemsValuesAndWrappers(m_animatedProperty.get());
+ }
+
+ PassListItemTearOff initialize(PassListItemTearOff passNewItem, ExceptionCode& ec)
+ {
+ return Base::initializeValuesAndWrappers(m_animatedProperty.get(), passNewItem, ec);
+ }
+
+ PassListItemTearOff getItem(unsigned index, ExceptionCode& ec)
+ {
+ return Base::getItemValuesAndWrappers(m_animatedProperty.get(), index, ec);
+ }
+
+ PassListItemTearOff insertItemBefore(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+ {
+ return Base::insertItemBeforeValuesAndWrappers(m_animatedProperty.get(), passNewItem, index, ec);
+ }
+
+ PassListItemTearOff replaceItem(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec)
+ {
+ return Base::replaceItemValuesAndWrappers(m_animatedProperty.get(), passNewItem, index, ec);
+ }
+
+ PassListItemTearOff removeItem(unsigned index, ExceptionCode& ec)
+ {
+ return Base::removeItemValuesAndWrappers(m_animatedProperty.get(), index, ec);
+ }
+
+ PassListItemTearOff appendItem(PassListItemTearOff passNewItem, ExceptionCode& ec)
+ {
+ return Base::appendItemValuesAndWrappers(m_animatedProperty.get(), passNewItem, ec);
+ }
+
+protected:
+ SVGListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
+ : SVGListProperty<PropertyType>(role)
+ , m_animatedProperty(animatedProperty)
+ {
+ }
+
+ virtual void commitChange()
+ {
+ PropertyType& values = m_animatedProperty->values();
+ ListWrapperCache& wrappers = m_animatedProperty->wrappers();
+
+ // Update existing wrappers, as the index in the values list has changed.
+ unsigned size = wrappers.size();
+ ASSERT(size == values.size());
+ for (unsigned i = 0; i < size; ++i) {
+ RefPtr<ListItemTearOff>& item = wrappers.at(i);
+ if (!item)
+ continue;
+ item->setAnimatedProperty(m_animatedProperty.get());
+ item->setValue(values.at(i));
+ }
+
+ m_animatedProperty->commitChange();
+ }
+
+ virtual void processIncomingListItemValue(const ListItemType&, unsigned*)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+ virtual void processIncomingListItemWrapper(RefPtr<ListItemTearOff>& newItem, unsigned* indexToModify)
+ {
+ SVGAnimatedProperty* animatedPropertyOfItem = newItem->animatedProperty();
+
+ // newItem has been created manually, it doesn't belong to any SVGElement.
+ // (for example: "textElement.x.baseVal.appendItem(svgsvgElement.createSVGLength())")
+ if (!animatedPropertyOfItem)
+ return;
+
+ // newItem belongs to a SVGElement, but its associated SVGAnimatedProperty is not an animated list tear off.
+ // (for example: "textElement.x.baseVal.appendItem(rectElement.width.baseVal)")
+ if (!animatedPropertyOfItem->isAnimatedListTearOff()) {
+ // We have to copy the incoming newItem, as we're not allowed to insert this tear off as is into our wrapper cache.
+ // Otherwhise we'll end up having two SVGAnimatedPropertys that operate on the same SVGPropertyTearOff. Consider the example above:
+ // SVGRectElements SVGAnimatedLength 'width' property baseVal points to the same tear off object
+ // that's inserted into SVGTextElements SVGAnimatedLengthList 'x'. textElement.x.baseVal.getItem(0).value += 150 would
+ // mutate the rectElement width _and_ the textElement x list. That's obviously wrong, take care of that.
+ newItem = ListItemTearOff::create(newItem->propertyReference());
+ return;
+ }
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ // '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 = static_cast<AnimatedListPropertyTearOff*>(animatedPropertyOfItem)->removeItemFromList(newItem.get(), 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;
+ }
+ }
+
+ // Back pointer to the animated property that created us
+ // For example (text.x.baseVal): m_animatedProperty points to the 'x' SVGAnimatedLengthList object
+ RefPtr<AnimatedListPropertyTearOff> m_animatedProperty;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGListPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp b/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp
new file mode 100644
index 0000000..a4eaf73
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGPathSegListPropertyTearOff.h"
+
+#include "SVGAnimatedPathSegListPropertyTearOff.h"
+#include "SVGNames.h"
+#include "SVGPathElement.h"
+#include "SVGPathSegWithContext.h"
+
+namespace WebCore {
+
+void SVGPathSegListPropertyTearOff::clear(ExceptionCode& ec)
+{
+ SVGPathSegList& values = m_animatedProperty->values();
+ if (values.isEmpty())
+ return;
+
+ unsigned size = values.size();
+ for (unsigned i = 0; i < size; ++i) {
+ ListItemType item = values.at(i);
+ static_cast<SVGPathSegWithContext*>(item.get())->setContextAndRole(0, PathSegUndefinedRole);
+ }
+
+ SVGPathSegListPropertyTearOff::Base::clearValues(values, ec);
+}
+
+SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::getItem(unsigned index, ExceptionCode& ec)
+{
+ SVGPathSegList& values = m_animatedProperty->values();
+ ListItemType returnedItem = Base::getItemValues(values, index, ec);
+ if (returnedItem) {
+ ASSERT(static_cast<SVGPathSegWithContext*>(returnedItem.get())->contextElement() == contextElement());
+ ASSERT(static_cast<SVGPathSegWithContext*>(returnedItem.get())->role() == m_pathSegRole);
+ }
+ return returnedItem.release();
+}
+
+SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::removeItem(unsigned index, ExceptionCode& ec)
+{
+ SVGPathSegList& values = m_animatedProperty->values();
+ SVGPathSegListPropertyTearOff::ListItemType removedItem = SVGPathSegListPropertyTearOff::Base::removeItemValues(values, index, ec);
+ if (removedItem)
+ static_cast<SVGPathSegWithContext*>(removedItem.get())->setContextAndRole(0, PathSegUndefinedRole);
+ return removedItem.release();
+}
+
+SVGPathElement* SVGPathSegListPropertyTearOff::contextElement() const
+{
+ SVGElement* contextElement = m_animatedProperty->contextElement();
+ ASSERT(contextElement);
+ ASSERT(contextElement->hasTagName(SVGNames::pathTag));
+ return static_cast<SVGPathElement*>(contextElement);
+}
+
+void SVGPathSegListPropertyTearOff::processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify)
+{
+ SVGPathSegWithContext* newItemWithContext = static_cast<SVGPathSegWithContext*>(newItem.get());
+ SVGAnimatedProperty* animatedPropertyOfItem = newItemWithContext->animatedProperty();
+
+ // Alter the role, after calling animatedProperty(), as that may influence the returned animated property.
+ newItemWithContext->setContextAndRole(contextElement(), m_pathSegRole);
+
+ if (!animatedPropertyOfItem)
+ return;
+
+ // newItem belongs to a SVGPathElement, but its associated SVGAnimatedProperty is not an animated list tear off.
+ // (for example: "pathElement.pathSegList.appendItem(pathElement.createSVGPathSegClosepath())")
+ if (!animatedPropertyOfItem->isAnimatedListTearOff())
+ return;
+
+ // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list.
+ // '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 = static_cast<SVGAnimatedPathSegListPropertyTearOff*>(animatedPropertyOfItem)->removeItemFromList(newItem.get(), 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;
+ }
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h
new file mode 100644
index 0000000..94acda1
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h
@@ -0,0 +1,160 @@
+/*
+ * 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 SVGPathSegListPropertyTearOff_h
+#define SVGPathSegListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGAnimatedListPropertyTearOff.h"
+#include "SVGPathSegList.h"
+
+namespace WebCore {
+
+class SVGPathElement;
+
+class SVGPathSegListPropertyTearOff : public SVGListProperty<SVGPathSegList> {
+public:
+ typedef SVGListProperty<SVGPathSegList> Base;
+ typedef SVGAnimatedListPropertyTearOff<SVGPathSegList> AnimatedListPropertyTearOff;
+ typedef SVGPropertyTraits<SVGPathSegList>::ListItemType ListItemType;
+ typedef PassRefPtr<SVGPathSeg> PassListItemType;
+
+ static PassRefPtr<SVGPathSegListPropertyTearOff> create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole)
+ {
+ ASSERT(animatedProperty);
+ return adoptRef(new SVGPathSegListPropertyTearOff(animatedProperty, role, pathSegRole));
+ }
+
+ int removeItemFromList(const ListItemType& removeItem, bool shouldSynchronizeWrappers)
+ {
+ SVGPathSegList& values = m_animatedProperty->values();
+
+ unsigned size = values.size();
+ for (unsigned i = 0; i < size; ++i) {
+ ListItemType& item = values.at(i);
+ if (item != removeItem)
+ continue;
+
+ values.remove(i);
+
+ if (shouldSynchronizeWrappers)
+ commitChange();
+
+ return i;
+ }
+
+ return -1;
+ }
+
+ // SVGList API
+ void clear(ExceptionCode&);
+
+ unsigned numberOfItems() const
+ {
+ SVGPathSegList& values = m_animatedProperty->values();
+ return Base::numberOfItemsValues(values);
+ }
+
+ PassListItemType initialize(PassListItemType passNewItem, ExceptionCode& ec)
+ {
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ ListItemType newItem = passNewItem;
+ SVGPathSegList& values = m_animatedProperty->values();
+ return Base::initializeValues(values, newItem, ec);
+ }
+
+ PassListItemType getItem(unsigned index, ExceptionCode&);
+
+ PassListItemType insertItemBefore(PassListItemType passNewItem, unsigned index, ExceptionCode& ec)
+ {
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ ListItemType newItem = passNewItem;
+ SVGPathSegList& values = m_animatedProperty->values();
+ return Base::insertItemBeforeValues(values, newItem, index, ec);
+ }
+
+ PassListItemType replaceItem(PassListItemType passNewItem, unsigned index, ExceptionCode& ec)
+ {
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ ListItemType newItem = passNewItem;
+ SVGPathSegList& values = m_animatedProperty->values();
+ return Base::replaceItemValues(values, newItem, index, ec);
+ }
+
+ PassListItemType removeItem(unsigned index, ExceptionCode&);
+
+ PassListItemType appendItem(PassListItemType passNewItem, ExceptionCode& ec)
+ {
+ // Not specified, but FF/Opera do it this way, and it's just sane.
+ if (!passNewItem) {
+ ec = SVGException::SVG_WRONG_TYPE_ERR;
+ return 0;
+ }
+
+ ListItemType newItem = passNewItem;
+ SVGPathSegList& values = m_animatedProperty->values();
+ return Base::appendItemValues(values, newItem, ec);
+ }
+
+private:
+ SVGPathSegListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole)
+ : SVGListProperty<SVGPathSegList>(role)
+ , m_animatedProperty(animatedProperty)
+ , m_pathSegRole(pathSegRole)
+ {
+ }
+
+ SVGPathElement* contextElement() const;
+
+ virtual void commitChange()
+ {
+ SVGPathSegList& values = m_animatedProperty->values();
+ values.commitChange(m_animatedProperty->contextElement());
+ }
+
+ virtual void processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify);
+ virtual void processIncomingListItemWrapper(RefPtr<ListItemTearOff>&, unsigned*)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+private:
+ RefPtr<AnimatedListPropertyTearOff> m_animatedProperty;
+ SVGPathSegRole m_pathSegRole;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGListPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGProperty.h b/Source/WebCore/svg/properties/SVGProperty.h
new file mode 100644
index 0000000..609e264
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGProperty.h
@@ -0,0 +1,45 @@
+/*
+ * 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() { }
+
+ virtual SVGPropertyRole role() const = 0;
+ virtual void commitChange() = 0;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGProperty_h
diff --git a/Source/WebCore/svg/properties/SVGPropertyTearOff.h b/Source/WebCore/svg/properties/SVGPropertyTearOff.h
new file mode 100644
index 0000000..d0eac3b
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGPropertyTearOff.h
@@ -0,0 +1,130 @@
+/*
+ * 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 "SVGAnimatedProperty.h"
+#include "SVGElement.h"
+#include "SVGProperty.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGPropertyTearOff : public SVGProperty {
+public:
+ typedef SVGPropertyTearOff<PropertyType> Self;
+
+ // Used for child types (baseVal/animVal) of a SVGAnimated* property (for example: SVGAnimatedLength::baseVal()).
+ // Also used for list tear offs (for example: text.x.baseVal.getItem(0)).
+ static PassRefPtr<Self> create(SVGAnimatedProperty* animatedProperty, SVGPropertyRole role, PropertyType& value)
+ {
+ ASSERT(animatedProperty);
+ return adoptRef(new Self(animatedProperty, role, value));
+ }
+
+ // Used for non-animated POD 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(); }
+
+ // 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; }
+
+ SVGElement* contextElement() const
+ {
+ if (!m_animatedProperty || m_valueIsCopy)
+ return 0;
+ return m_animatedProperty->contextElement();
+ }
+
+ void detachWrapper()
+ {
+ if (m_valueIsCopy)
+ return;
+
+ // 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.
+ m_value = new PropertyType(*m_value);
+ m_valueIsCopy = true;
+ m_animatedProperty = 0;
+ }
+
+ virtual void commitChange()
+ {
+ if (!m_animatedProperty || m_valueIsCopy)
+ return;
+ m_animatedProperty->commitChange();
+ }
+
+ virtual SVGPropertyRole role() const { return m_role; }
+
+protected:
+ SVGPropertyTearOff(SVGAnimatedProperty* animatedProperty, SVGPropertyRole role, PropertyType& value)
+ : m_animatedProperty(animatedProperty)
+ , m_role(role)
+ , 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_role(UndefinedRole)
+ , m_value(new PropertyType(initialValue))
+ , m_valueIsCopy(true)
+ {
+ }
+
+ virtual ~SVGPropertyTearOff()
+ {
+ if (m_valueIsCopy)
+ delete m_value;
+ }
+
+ RefPtr<SVGAnimatedProperty> m_animatedProperty;
+ SVGPropertyRole m_role;
+ PropertyType* m_value;
+ bool m_valueIsCopy : 1;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGPropertyTraits.h b/Source/WebCore/svg/properties/SVGPropertyTraits.h
new file mode 100644
index 0000000..0ed9339
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGPropertyTraits.h
@@ -0,0 +1,65 @@
+/*
+ * 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 <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+template<typename PropertyType>
+struct SVGPropertyTraits { };
+
+template<>
+struct SVGPropertyTraits<bool> {
+ static bool initialValue() { return false; }
+ static String toString(bool type) { return type ? "true" : "false"; }
+};
+
+template<>
+struct SVGPropertyTraits<int> {
+ static int initialValue() { return 0; }
+ static String toString(int type) { return String::number(type); }
+};
+
+template<>
+struct SVGPropertyTraits<long> {
+ static long initialValue() { return 0; }
+ static String toString(long type) { return String::number(type); }
+};
+
+template<>
+struct SVGPropertyTraits<float> {
+ static float initialValue() { return 0; }
+ static String toString(float type) { return String::number(type); }
+};
+
+template<>
+struct SVGPropertyTraits<String> {
+ static String initialValue() { return String(); }
+ static String toString(const String& type) { return type; }
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h
new file mode 100644
index 0000000..a6f0f28
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h
@@ -0,0 +1,114 @@
+/*
+ * 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 SVGStaticListPropertyTearOff_h
+#define SVGStaticListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGListProperty.h"
+
+namespace WebCore {
+
+template<typename PropertyType>
+class SVGStaticListPropertyTearOff : public SVGListProperty<PropertyType> {
+public:
+ typedef SVGListProperty<PropertyType> Base;
+
+ typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
+ typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
+
+ static PassRefPtr<SVGStaticListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, PropertyType& values)
+ {
+ ASSERT(contextElement);
+ return adoptRef(new SVGStaticListPropertyTearOff<PropertyType>(contextElement, values));
+ }
+
+ // SVGList API
+ void clear(ExceptionCode& ec)
+ {
+ Base::clearValues(m_values, ec);
+ }
+
+ unsigned numberOfItems() const
+ {
+ return Base::numberOfItemsValues(m_values);
+ }
+
+ ListItemType initialize(const ListItemType& newItem, ExceptionCode& ec)
+ {
+ return Base::initializeValues(m_values, newItem, ec);
+ }
+
+ ListItemType getItem(unsigned index, ExceptionCode& ec)
+ {
+ return Base::getItemValues(m_values, index, ec);
+ }
+
+ ListItemType insertItemBefore(const ListItemType& newItem, unsigned index, ExceptionCode& ec)
+ {
+ return Base::insertItemBeforeValues(m_values, newItem, index, ec);
+ }
+
+ ListItemType replaceItem(const ListItemType& newItem, unsigned index, ExceptionCode& ec)
+ {
+ return Base::replaceItemValues(m_values, newItem, index, ec);
+ }
+
+ ListItemType removeItem(unsigned index, ExceptionCode& ec)
+ {
+ return Base::removeItemValues(m_values, index, ec);
+ }
+
+ ListItemType appendItem(const ListItemType& newItem, ExceptionCode& ec)
+ {
+ return Base::appendItemValues(m_values, newItem, ec);
+ }
+
+private:
+ SVGStaticListPropertyTearOff(SVGElement* contextElement, PropertyType& values)
+ : SVGListProperty<PropertyType>(UndefinedRole)
+ , m_contextElement(contextElement)
+ , m_values(values)
+ {
+ }
+
+ virtual void commitChange()
+ {
+ m_values.commitChange(m_contextElement.get());
+ }
+
+ virtual void processIncomingListItemValue(const ListItemType&, unsigned*)
+ {
+ // no-op for static lists
+ }
+
+ virtual void processIncomingListItemWrapper(RefPtr<ListItemTearOff>&, unsigned*)
+ {
+ ASSERT_NOT_REACHED();
+ }
+
+private:
+ RefPtr<SVGElement> m_contextElement;
+ PropertyType& m_values;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGStaticListPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h b/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h
new file mode 100644
index 0000000..233880f
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h
@@ -0,0 +1,67 @@
+/*
+ * 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 SVGStaticPropertyTearOff_h
+#define SVGStaticPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGPropertyTearOff.h"
+
+namespace WebCore {
+
+#if COMPILER(MSVC)
+// UpdateMethod is 12 bytes. We have to pack to a size greater than or equal to that to avoid an
+// alignment warning (C4121). 16 is the next-largest size allowed for packing, so we use that.
+#pragma pack(push, 16)
+#endif
+template<typename ContextElement, typename PropertyType>
+class SVGStaticPropertyTearOff : public SVGPropertyTearOff<PropertyType> {
+public:
+ typedef SVGStaticPropertyTearOff<ContextElement, PropertyType> Self;
+ typedef void (ContextElement::*UpdateMethod)();
+
+ // Used for non-animated POD types that are not associated with a SVGAnimatedProperty object, nor with a XML DOM attribute
+ // (for example: SVGSVGElement::currentTranslate).
+ static PassRefPtr<Self> create(ContextElement* contextElement, PropertyType& value, UpdateMethod update)
+ {
+ ASSERT(contextElement);
+ return adoptRef(new Self(contextElement, value, update));
+ }
+
+ virtual void commitChange() { (m_contextElement.get()->*m_update)(); }
+
+private:
+ SVGStaticPropertyTearOff(ContextElement* contextElement, PropertyType& value, UpdateMethod update)
+ : SVGPropertyTearOff<PropertyType>(0, UndefinedRole, value)
+ , m_update(update)
+ , m_contextElement(contextElement)
+ {
+ }
+
+ UpdateMethod m_update;
+ RefPtr<ContextElement> m_contextElement;
+};
+#if COMPILER(MSVC)
+#pragma pack(pop)
+#endif
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGStaticPropertyTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGStaticPropertyWithParentTearOff.h b/Source/WebCore/svg/properties/SVGStaticPropertyWithParentTearOff.h
new file mode 100644
index 0000000..cf47960
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGStaticPropertyWithParentTearOff.h
@@ -0,0 +1,72 @@
+/*
+ * 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 SVGStaticPropertyWithParentTearOff_h
+#define SVGStaticPropertyWithParentTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGPropertyTearOff.h"
+
+namespace WebCore {
+
+#if COMPILER(MSVC)
+// UpdateMethod is 12 bytes. We have to pack to a size greater than or equal to that to avoid an
+// alignment warning (C4121). 16 is the next-largest size allowed for packing, so we use that.
+#pragma pack(push, 16)
+#endif
+template<typename ParentType, typename PropertyType>
+class SVGStaticPropertyWithParentTearOff : public SVGPropertyTearOff<PropertyType> {
+public:
+ typedef SVGStaticPropertyWithParentTearOff<ParentType, PropertyType> Self;
+ typedef void (ParentType::*UpdateMethod)();
+
+ // Used for non-animated POD types that are not associated with a SVGAnimatedProperty object, nor with a XML DOM attribute
+ // and that contain a parent type that's exposed to the bindings via a SVGStaticPropertyTearOff object
+ // (for example: SVGTransform::matrix).
+ static PassRefPtr<Self> create(SVGProperty* parent, PropertyType& value, UpdateMethod update)
+ {
+ ASSERT(parent);
+ return adoptRef(new Self(parent, value, update));
+ }
+
+ virtual void commitChange()
+ {
+ (static_cast<SVGPropertyTearOff<ParentType>*>(m_parent.get())->propertyReference().*m_update)();
+ m_parent->commitChange();
+ }
+
+private:
+ SVGStaticPropertyWithParentTearOff(SVGProperty* parent, PropertyType& value, UpdateMethod update)
+ : SVGPropertyTearOff<PropertyType>(0, UndefinedRole, value)
+ , m_update(update)
+ , m_parent(parent)
+ {
+ }
+
+ UpdateMethod m_update;
+ RefPtr<SVGProperty> m_parent;
+};
+#if COMPILER(MSVC)
+#pragma pack(pop)
+#endif
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGStaticPropertyWithParentTearOff_h
diff --git a/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h
new file mode 100644
index 0000000..e496c81
--- /dev/null
+++ b/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h
@@ -0,0 +1,83 @@
+/*
+ * 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 SVGTransformListPropertyTearOff_h
+#define SVGTransformListPropertyTearOff_h
+
+#if ENABLE(SVG)
+#include "SVGListPropertyTearOff.h"
+#include "SVGTransformList.h"
+
+namespace WebCore {
+
+// SVGTransformList contains two additional methods, that can be exposed to the bindings.
+class SVGTransformListPropertyTearOff : public SVGListPropertyTearOff<SVGTransformList> {
+public:
+ typedef SVGAnimatedListPropertyTearOff<SVGTransformList> AnimatedListPropertyTearOff;
+ typedef SVGAnimatedListPropertyTearOff<SVGTransformList>::ListWrapperCache ListWrapperCache;
+
+ static PassRefPtr<SVGListPropertyTearOff<SVGTransformList> > create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
+ {
+ ASSERT(animatedProperty);
+ return adoptRef(new SVGTransformListPropertyTearOff(animatedProperty, role));
+ }
+
+ PassRefPtr<SVGPropertyTearOff<SVGTransform> > createSVGTransformFromMatrix(SVGPropertyTearOff<SVGMatrix>* matrix, ExceptionCode& ec)
+ {
+ if (!matrix) {
+ ec = TYPE_MISMATCH_ERR;
+ return 0;
+ }
+ SVGTransformList& values = m_animatedProperty->values();
+ return SVGPropertyTearOff<SVGTransform>::create(values.createSVGTransformFromMatrix(matrix->propertyReference()));
+ }
+
+ PassRefPtr<SVGPropertyTearOff<SVGTransform> > consolidate(ExceptionCode& ec)
+ {
+ if (!canAlterList(ec))
+ return 0;
+
+ SVGTransformList& values = m_animatedProperty->values();
+ ListWrapperCache& wrappers = m_animatedProperty->wrappers();
+ ASSERT(values.size() == wrappers.size());
+
+ // Spec: If the list was empty, then a value of null is returned.
+ if (values.isEmpty())
+ return 0;
+
+ m_animatedProperty->detachListWrappers(0);
+ RefPtr<SVGPropertyTearOff<SVGTransform> > wrapper = SVGPropertyTearOff<SVGTransform>::create(values.consolidate());
+ wrappers.append(wrapper);
+
+ ASSERT(values.size() == wrappers.size());
+ return wrapper.release();
+ }
+
+private:
+ SVGTransformListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role)
+ : SVGListPropertyTearOff<SVGTransformList>(animatedProperty, role)
+ {
+ }
+
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGListPropertyTearOff_h