diff options
| author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 | 
|---|---|---|
| committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 | 
| commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
| tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/svg/properties | |
| parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
| download | external_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')
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 | 
