diff options
Diffstat (limited to 'Source/WebCore/svg/properties')
25 files changed, 638 insertions, 1078 deletions
diff --git a/Source/WebCore/svg/properties/SVGAnimatedEnumerationPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedEnumerationPropertyTearOff.h index 1c8ea99bf..164cd648f 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedEnumerationPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedEnumerationPropertyTearOff.h @@ -17,10 +17,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedEnumerationPropertyTearOff_h -#define SVGAnimatedEnumerationPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGAnimatedStaticPropertyTearOff.h" #include "SVGException.h" #include "SVGPropertyTraits.h" @@ -28,22 +26,40 @@ namespace WebCore { template<typename EnumType> -class SVGAnimatedEnumerationPropertyTearOff : public SVGAnimatedStaticPropertyTearOff<unsigned> { +class SVGAnimatedEnumerationPropertyTearOff final : public SVGAnimatedStaticPropertyTearOff<unsigned> { public: - virtual void setBaseVal(const unsigned& property, ExceptionCode& ec) override + const unsigned& baseVal() final + { + const unsigned& baseVal = SVGAnimatedStaticPropertyTearOff::baseVal(); + + if (baseVal > SVGIDLEnumLimits<EnumType>::highestExposedEnumValue()) + return m_outOfRangeEnumValue; + + return baseVal; + } + + const unsigned& animVal() final + { + const unsigned& animVal = SVGAnimatedStaticPropertyTearOff::animVal(); + + if (animVal > SVGIDLEnumLimits<EnumType>::highestExposedEnumValue()) + return m_outOfRangeEnumValue; + + return animVal; + } + + ExceptionOr<void> setBaseVal(const unsigned& property) final { // All SVG enumeration values, that are allowed to be set via SVG DOM start with 1, 0 corresponds to unknown and is not settable through SVG DOM. - if (!property || property > SVGPropertyTraits<EnumType>::highestEnumValue()) { - ec = SVGException::SVG_INVALID_VALUE_ERR; - return; - } - SVGAnimatedStaticPropertyTearOff<unsigned>::setBaseVal(property, ec); + if (!property || property > SVGIDLEnumLimits<EnumType>::highestExposedEnumValue()) + return Exception { SVGException::SVG_INVALID_VALUE_ERR }; + return SVGAnimatedStaticPropertyTearOff<unsigned>::setBaseVal(property); } - static PassRefPtr<SVGAnimatedEnumerationPropertyTearOff<EnumType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, EnumType& property) + static Ref<SVGAnimatedEnumerationPropertyTearOff<EnumType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, EnumType& property) { ASSERT(contextElement); - return adoptRef(new SVGAnimatedEnumerationPropertyTearOff<EnumType>(contextElement, attributeName, animatedPropertyType, reinterpret_cast<unsigned&>(property))); + return adoptRef(*new SVGAnimatedEnumerationPropertyTearOff<EnumType>(contextElement, attributeName, animatedPropertyType, reinterpret_cast<unsigned&>(property))); } EnumType& currentAnimatedValue() @@ -58,9 +74,12 @@ private: : SVGAnimatedStaticPropertyTearOff<unsigned>(contextElement, attributeName, animatedPropertyType, property) { } + + static unsigned m_outOfRangeEnumValue; }; -} +// By convention, all enum values that represent UNKNOWN in SVG are equal to zero. +template<typename EnumType> +unsigned SVGAnimatedEnumerationPropertyTearOff<EnumType>::m_outOfRangeEnumValue = 0; -#endif // ENABLE(SVG) -#endif // SVGAnimatedEnumerationPropertyTearOff_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h index 9c6a277d3..0ce993793 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedListPropertyTearOff.h @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) 2016 Apple Inc. 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 @@ -17,10 +18,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedListPropertyTearOff_h -#define SVGAnimatedListPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGAnimatedProperty.h" #include "SVGListPropertyTearOff.h" #include "SVGStaticListPropertyTearOff.h" @@ -33,42 +32,59 @@ 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; - typedef SVGListProperty<PropertyType> ListProperty; - typedef SVGListPropertyTearOff<PropertyType> ListPropertyTearOff; - typedef PropertyType ContentType; - - virtual ListProperty* baseVal() + using ListItemType = typename SVGPropertyTraits<PropertyType>::ListItemType; + using ListItemTearOff = typename SVGPropertyTraits<PropertyType>::ListItemTearOff; + using ListWrapperCache = Vector<RefPtr<ListItemTearOff>>; + using ListProperty = SVGListProperty<PropertyType>; + using ListPropertyTearOff = typename SVGPropertyTraits<PropertyType>::ListPropertyTearOff; + using ContentType = PropertyType; + + static Ref<SVGAnimatedListPropertyTearOff<PropertyType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& values) { - if (!m_baseVal) - m_baseVal = ListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers); - return static_cast<ListProperty*>(m_baseVal.get()); + ASSERT(contextElement); + return adoptRef(*new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, values)); } - virtual ListProperty* animVal() + virtual Ref<ListPropertyTearOff> baseVal() { - if (!m_animVal) - m_animVal = ListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers); - return static_cast<ListProperty*>(m_animVal.get()); + if (m_baseVal) + return *m_baseVal; + + auto property = ListPropertyTearOff::create(*this, BaseValRole, m_values, m_wrappers); + m_baseVal = property.ptr(); + return property; } - virtual bool isAnimatedListTearOff() const override { return true; } + virtual Ref<ListPropertyTearOff> animVal() + { + if (m_animVal) + return *m_animVal; + + auto property = ListPropertyTearOff::create(*this, AnimValRole, m_values, m_wrappers); + m_animVal = property.ptr(); + return property; + } + + bool isAnimating() const override { return m_animatedProperty; } + bool isAnimatedListTearOff() const override { return true; } + void propertyWillBeDeleted(const SVGProperty& property) override + { + if (&property == m_baseVal) + m_baseVal = nullptr; + else if (&property == m_animVal) + m_animVal = nullptr; + } - int findItem(SVGProperty* property) const + int findItem(SVGProperty* property) { // This should ever be called for our baseVal, as animVal can't modify the list. - // It's safe to cast to ListPropertyTearOff here as all classes inheriting from us supply their own removeItemFromList() method. - typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff; - return static_cast<ListPropertyTearOff*>(m_baseVal.get())->findItem(static_cast<ListItemTearOff*>(property)); + return baseVal()->findItem(static_cast<ListItemTearOff*>(property)); } void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers) { // This should ever be called for our baseVal, as animVal can't modify the list. - // It's safe to cast to ListPropertyTearOff here as all classes inheriting from us supply their own removeItemFromList() method. - static_cast<ListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers); + baseVal()->removeItemFromList(itemIndex, shouldSynchronizeWrappers); } void detachListWrappers(unsigned newListSize) @@ -78,9 +94,8 @@ public: PropertyType& currentAnimatedValue() { - ASSERT(m_isAnimating); - ASSERT(m_animVal); - return static_cast<ListProperty*>(m_animVal.get())->values(); + ASSERT(isAnimating()); + return m_animatedProperty->values(); } const PropertyType& currentBaseValue() const @@ -90,7 +105,7 @@ public: void animationStarted(PropertyType* newAnimVal, bool shouldOwnValues = false) { - ASSERT(!m_isAnimating); + ASSERT(!isAnimating()); ASSERT(newAnimVal); ASSERT(m_values.size() == m_wrappers.size()); ASSERT(m_animatedWrappers.isEmpty()); @@ -99,67 +114,55 @@ public: if (!newAnimVal->isEmpty()) m_animatedWrappers.fill(0, newAnimVal->size()); - ListProperty* animVal = static_cast<ListProperty*>(this->animVal()); - animVal->setValuesAndWrappers(newAnimVal, &m_animatedWrappers, shouldOwnValues); - ASSERT(animVal->values().size() == animVal->wrappers().size()); - ASSERT(animVal->wrappers().size() == m_animatedWrappers.size()); - m_isAnimating = true; + m_animatedProperty = animVal(); + m_animatedProperty->setValuesAndWrappers(newAnimVal, &m_animatedWrappers, shouldOwnValues); + ASSERT(m_animatedProperty->values().size() == m_animatedProperty->wrappers().size()); + ASSERT(m_animatedProperty->wrappers().size() == m_animatedWrappers.size()); } void animationEnded() { - ASSERT(m_isAnimating); - ASSERT(m_animVal); + ASSERT(isAnimating()); ASSERT(m_values.size() == m_wrappers.size()); - ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get()); - ASSERT(animVal->values().size() == animVal->wrappers().size()); - ASSERT(animVal->wrappers().size() == m_animatedWrappers.size()); + ASSERT(m_animatedProperty->values().size() == m_animatedProperty->wrappers().size()); + ASSERT(m_animatedProperty->wrappers().size() == m_animatedWrappers.size()); - animVal->setValuesAndWrappers(&m_values, &m_wrappers, false); - ASSERT(animVal->values().size() == animVal->wrappers().size()); - ASSERT(animVal->wrappers().size() == m_wrappers.size()); + m_animatedProperty->setValuesAndWrappers(&m_values, &m_wrappers, false); + ASSERT(m_animatedProperty->values().size() == m_animatedProperty->wrappers().size()); + ASSERT(m_animatedProperty->wrappers().size() == m_wrappers.size()); m_animatedWrappers.clear(); - m_isAnimating = false; + m_animatedProperty = nullptr; } void synchronizeWrappersIfNeeded() { + ASSERT(isAnimating()); + // Eventually the wrapper list needs synchronization because any SVGAnimateLengthList::calculateAnimatedValue() call may // mutate the length of our values() list, and thus the wrapper() cache needs synchronization, to have the same size. - // Also existing wrappers which point directly at elements in the existing SVGLengthList have to be detached (so a copy + // Also existing wrappers which point directly at elements in the existing SVGLengthListValues have to be detached (so a copy // of them is created, so existing animVal variables in JS are kept-alive). If we'd detach them later the underlying - // SVGLengthList was already mutated, and our list item wrapper tear offs would point nowhere. Assertions would fire. - ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get()); - animVal->detachListWrappers(animVal->values().size()); + // SVGLengthListValues was already mutated, and our list item wrapper tear offs would point nowhere. Assertions would fire. + m_animatedProperty->detachListWrappers(m_animatedProperty->values().size()); - ASSERT(animVal->values().size() == animVal->wrappers().size()); - ASSERT(animVal->wrappers().size() == m_animatedWrappers.size()); + ASSERT(m_animatedProperty->values().size() == m_animatedProperty->wrappers().size()); + ASSERT(m_animatedProperty->wrappers().size() == m_animatedWrappers.size()); } void animValWillChange() { - ASSERT(m_isAnimating); - ASSERT(m_animVal); ASSERT(m_values.size() == m_wrappers.size()); synchronizeWrappersIfNeeded(); } void animValDidChange() { - ASSERT(m_isAnimating); - ASSERT(m_animVal); ASSERT(m_values.size() == m_wrappers.size()); synchronizeWrappersIfNeeded(); } - static PassRefPtr<SVGAnimatedListPropertyTearOff<PropertyType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& values) - { - ASSERT(contextElement); - return adoptRef(new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, values)); - } - protected: SVGAnimatedListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& values) : SVGAnimatedProperty(contextElement, attributeName, animatedPropertyType) @@ -174,11 +177,13 @@ protected: ListWrapperCache m_wrappers; ListWrapperCache m_animatedWrappers; - RefPtr<SVGProperty> m_baseVal; - RefPtr<SVGProperty> m_animVal; -}; + // Cache the raw pointer but return a RefPtr<>. This will break the cyclic reference + // between SVGListPropertyTearOff and SVGAnimatedListPropertyTearOff once the property + // pointer is not needed. + ListPropertyTearOff* m_baseVal { nullptr }; + ListPropertyTearOff* m_animVal { nullptr }; -} + RefPtr<ListProperty> m_animatedProperty; +}; -#endif // ENABLE(SVG) -#endif // SVGAnimatedListPropertyTearOff_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h index 83ef8d617..5ab1a43f0 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedPathSegListPropertyTearOff.h @@ -17,104 +17,109 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedPathSegListPropertyTearOff_h -#define SVGAnimatedPathSegListPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGAnimatedListPropertyTearOff.h" #include "SVGPathByteStream.h" #include "SVGPathElement.h" #include "SVGPathSegList.h" -#include "SVGPathSegListPropertyTearOff.h" #include "SVGPathUtilities.h" namespace WebCore { -class SVGAnimatedPathSegListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGPathSegList> { +class SVGAnimatedPathSegListPropertyTearOff final : public SVGAnimatedListPropertyTearOff<SVGPathSegListValues> { public: - virtual SVGListProperty<SVGPathSegList>* baseVal() override + using Base = SVGAnimatedListPropertyTearOff<SVGPathSegListValues>; + + static Ref<SVGAnimatedPathSegListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGPathSegListValues& values) { - if (!m_baseVal) - m_baseVal = SVGPathSegListPropertyTearOff::create(this, BaseValRole, PathSegUnalteredRole, m_values, m_wrappers); - return static_cast<SVGListProperty<SVGPathSegList>*>(m_baseVal.get()); + ASSERT(contextElement); + return adoptRef(*new SVGAnimatedPathSegListPropertyTearOff(contextElement, attributeName, animatedPropertyType, values)); } - virtual SVGListProperty<SVGPathSegList>* animVal() override + Ref<ListPropertyTearOff> baseVal() final { - if (!m_animVal) - m_animVal = SVGPathSegListPropertyTearOff::create(this, AnimValRole, PathSegUnalteredRole, m_values, m_wrappers); - return static_cast<SVGListProperty<SVGPathSegList>*>(m_animVal.get()); + if (m_baseVal) + return *m_baseVal; + + auto property = SVGPathSegList::create(*this, BaseValRole, PathSegUnalteredRole, m_values, m_wrappers); + m_baseVal = property.ptr(); + return property; } - int findItem(const RefPtr<SVGPathSeg>& segment) const + Ref<ListPropertyTearOff> animVal() final { - // This should ever be called for our baseVal, as animVal can't modify the list. - ASSERT(m_baseVal); - return static_cast<SVGPathSegListPropertyTearOff*>(m_baseVal.get())->findItem(segment); + if (m_animVal) + return *m_animVal; + + auto property = SVGPathSegList::create(*this, AnimValRole, PathSegUnalteredRole, m_values, m_wrappers); + m_animVal = property.ptr(); + return property; } - void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers) + int findItem(const RefPtr<SVGPathSeg>& segment) { - // This should ever be called for our baseVal, as animVal can't modify the list. - ASSERT(m_baseVal); - static_cast<SVGPathSegListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers); + return baseVal()->findItem(segment); } - static PassRefPtr<SVGAnimatedPathSegListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGPathSegList& values) + void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers) { - ASSERT(contextElement); - return adoptRef(new SVGAnimatedPathSegListPropertyTearOff(contextElement, attributeName, animatedPropertyType, values)); + baseVal()->removeItemFromList(itemIndex, shouldSynchronizeWrappers); } - using SVGAnimatedListPropertyTearOff<SVGPathSegList>::animationStarted; - void animationStarted(SVGPathByteStream* byteStream, const SVGPathSegList* baseValue) + using Base::animationStarted; + void animationStarted(SVGPathByteStream* byteStream, const SVGPathSegListValues* baseValue) { ASSERT(byteStream); ASSERT(baseValue); ASSERT(!m_animatedPathByteStream); m_animatedPathByteStream = byteStream; - // Pass shouldOwnValues=true, as the SVGPathSegList lifetime is solely managed by its tear off class. - SVGPathSegList* copy = new SVGPathSegList(*baseValue); - SVGAnimatedListPropertyTearOff<SVGPathSegList>::animationStarted(copy, true); + // Pass shouldOwnValues=true, as the SVGPathSegListValues lifetime is solely managed by its tear off class. + auto* copy = new SVGPathSegListValues(*baseValue); + Base::animationStarted(copy, true); } void animationEnded() { ASSERT(m_animatedPathByteStream); - m_animatedPathByteStream = 0; - SVGAnimatedListPropertyTearOff<SVGPathSegList>::animationEnded(); + m_animatedPathByteStream = nullptr; + Base::animationEnded(); } void animValDidChange() { ASSERT(m_animatedPathByteStream); - SVGPathElement* pathElement = toSVGPathElement(contextElement()); + SVGPathElement* pathElement = downcast<SVGPathElement>(contextElement()); // If the animVal is observed from JS, we have to update it on each animation step. // This is an expensive operation and only done, if someone actually observes the animatedPathSegList() while an animation is running. if (pathElement->isAnimValObserved()) { - SVGPathSegList& animatedList = currentAnimatedValue(); + auto& animatedList = currentAnimatedValue(); animatedList.clear(); - buildSVGPathSegListFromByteStream(m_animatedPathByteStream, pathElement, animatedList, UnalteredParsing); + buildSVGPathSegListValuesFromByteStream(*m_animatedPathByteStream, *pathElement, animatedList, UnalteredParsing); } - SVGAnimatedListPropertyTearOff<SVGPathSegList>::animValDidChange(); + Base::animValDidChange(); } SVGPathByteStream* animatedPathByteStream() const { return m_animatedPathByteStream; } private: - SVGAnimatedPathSegListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGPathSegList& values) - : SVGAnimatedListPropertyTearOff<SVGPathSegList>(contextElement, attributeName, animatedPropertyType, values) - , m_animatedPathByteStream(0) + SVGAnimatedPathSegListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGPathSegListValues& values) + : Base(contextElement, attributeName, animatedPropertyType, values) + , m_animatedPathByteStream(nullptr) + { + ASSERT(contextElement); + ASSERT(is<SVGPathElement>(contextElement)); + } + + virtual ~SVGAnimatedPathSegListPropertyTearOff() { + downcast<SVGPathElement>(contextElement())->animatedPropertyWillBeDeleted(); } SVGPathByteStream* m_animatedPathByteStream; }; -} - -#endif // ENABLE(SVG) -#endif // SVGAnimatedPathSegListPropertyTearOff_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAnimatedProperty.cpp b/Source/WebCore/svg/properties/SVGAnimatedProperty.cpp index 60fae5bbf..f24a8d871 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedProperty.cpp +++ b/Source/WebCore/svg/properties/SVGAnimatedProperty.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) Research In Motion Limited 2010. All rights reserved. * Copyright (C) 2013 Samsung Electronics. All rights reserved. + * Copyright (C) 2016 Apple Inc. 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 @@ -19,8 +20,6 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "SVGAnimatedProperty.h" #include "SVGElement.h" @@ -31,7 +30,6 @@ SVGAnimatedProperty::SVGAnimatedProperty(SVGElement* contextElement, const Quali : m_contextElement(contextElement) , m_attributeName(attributeName) , m_animatedPropertyType(animatedPropertyType) - , m_isAnimating(false) , m_isReadOnly(false) { } @@ -39,16 +37,15 @@ SVGAnimatedProperty::SVGAnimatedProperty(SVGElement* contextElement, const Quali SVGAnimatedProperty::~SVGAnimatedProperty() { // Remove wrapper from cache. - Cache& cache = *animatedPropertyCache(); - for (auto it = cache.begin(), end = cache.end(); it != end; ++it) { - if (it->value == this) { - cache.remove(it); + for (auto& cache : *animatedPropertyCache()) { + if (cache.value == this) { + animatedPropertyCache()->remove(cache.key); break; } } // Assure that animationEnded() was called, if animationStarted() was called before. - ASSERT(!m_isAnimating); + ASSERT(!isAnimating()); } void SVGAnimatedProperty::commitChange() @@ -57,6 +54,8 @@ void SVGAnimatedProperty::commitChange() ASSERT(!m_contextElement->m_deletionHasBegun); m_contextElement->invalidateSVGAttributes(); m_contextElement->svgAttributeChanged(m_attributeName); + // Needed to synchronize with CSSOM for presentation attributes with SVG DOM. + m_contextElement->synchronizeAnimatedSVGAttribute(m_attributeName); } SVGAnimatedProperty::Cache* SVGAnimatedProperty::animatedPropertyCache() @@ -66,5 +65,3 @@ SVGAnimatedProperty::Cache* SVGAnimatedProperty::animatedPropertyCache() } } // namespace WebCore - -#endif // ENABLE(SVG) diff --git a/Source/WebCore/svg/properties/SVGAnimatedProperty.h b/Source/WebCore/svg/properties/SVGAnimatedProperty.h index 93f076b2b..b39772b41 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedProperty.h +++ b/Source/WebCore/svg/properties/SVGAnimatedProperty.h @@ -1,6 +1,7 @@ /* * Copyright (C) Research In Motion Limited 2010. All rights reserved. * Copyright (C) 2013 Samsung Electronics. All rights reserved. + * Copyright (C) 2016 Apple Inc. 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 @@ -18,10 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedProperty_h -#define SVGAnimatedProperty_h +#pragma once -#if ENABLE(SVG) #include "SVGAnimatedPropertyDescription.h" #include "SVGPropertyInfo.h" #include <wtf/RefCounted.h> @@ -29,19 +28,21 @@ 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; } AnimatedPropertyType animatedPropertyType() const { return m_animatedPropertyType; } - bool isAnimating() const { return m_isAnimating; } bool isReadOnly() const { return m_isReadOnly; } void setIsReadOnly() { m_isReadOnly = true; } void commitChange(); + virtual bool isAnimating() const { return false; } virtual bool isAnimatedListTearOff() const { return false; } + virtual void propertyWillBeDeleted(const SVGProperty&) { } // Caching facilities. typedef HashMap<SVGAnimatedPropertyDescription, SVGAnimatedProperty*, SVGAnimatedPropertyDescriptionHash, SVGAnimatedPropertyDescriptionHashTraits> Cache; @@ -49,22 +50,27 @@ public: virtual ~SVGAnimatedProperty(); template<typename OwnerType, typename TearOffType, typename PropertyType> - static PassRefPtr<TearOffType> lookupOrCreateWrapper(OwnerType* element, const SVGPropertyInfo* info, PropertyType& property) + static Ref<TearOffType> lookupOrCreateWrapper(OwnerType* element, const SVGPropertyInfo* info, PropertyType& property) { ASSERT(info); SVGAnimatedPropertyDescription key(element, info->propertyIdentifier); - RefPtr<SVGAnimatedProperty> wrapper = animatedPropertyCache()->get(key); - if (!wrapper) { - wrapper = TearOffType::create(element, info->attributeName, info->animatedPropertyType, property); - if (info->animatedPropertyState == PropertyIsReadOnly) - wrapper->setIsReadOnly(); - animatedPropertyCache()->set(key, wrapper.get()); - } - return static_pointer_cast<TearOffType>(wrapper); + + auto result = animatedPropertyCache()->add(key, nullptr); + if (!result.isNewEntry) + return static_cast<TearOffType&>(*result.iterator->value); + + Ref<SVGAnimatedProperty> wrapper = TearOffType::create(element, info->attributeName, info->animatedPropertyType, property); + if (info->animatedPropertyState == PropertyIsReadOnly) + wrapper->setIsReadOnly(); + + // Cache the raw pointer but return a Ref<>. This will break the cyclic reference + // between SVGAnimatedProperty and SVGElement once the property pointer is not needed. + result.iterator->value = wrapper.ptr(); + return static_reference_cast<TearOffType>(wrapper); } template<typename OwnerType, typename TearOffType> - static TearOffType* lookupWrapper(OwnerType* element, const SVGPropertyInfo* info) + static RefPtr<TearOffType> lookupWrapper(OwnerType* element, const SVGPropertyInfo* info) { ASSERT(info); SVGAnimatedPropertyDescription key(element, info->propertyIdentifier); @@ -72,7 +78,7 @@ public: } template<typename OwnerType, typename TearOffType> - static TearOffType* lookupWrapper(const OwnerType* element, const SVGPropertyInfo* info) + static RefPtr<TearOffType> lookupWrapper(const OwnerType* element, const SVGPropertyInfo* info) { return lookupWrapper<OwnerType, TearOffType>(const_cast<OwnerType*>(element), info); } @@ -88,11 +94,7 @@ private: AnimatedPropertyType m_animatedPropertyType; protected: - bool m_isAnimating; bool m_isReadOnly; }; -} - -#endif // ENABLE(SVG) -#endif // SVGAnimatedProperty_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h b/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h index 610fb148d..f1d9a04b0 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h +++ b/Source/WebCore/svg/properties/SVGAnimatedPropertyDescription.h @@ -19,10 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedPropertyDescription_h -#define SVGAnimatedPropertyDescription_h +#pragma once -#if ENABLE(SVG) #include <wtf/HashMap.h> #include <wtf/text/AtomicString.h> @@ -33,8 +31,8 @@ class SVGElement; struct SVGAnimatedPropertyDescription { // Empty value SVGAnimatedPropertyDescription() - : m_element(0) - , m_attributeName(0) + : m_element(nullptr) + , m_attributeName(nullptr) { } @@ -82,7 +80,4 @@ struct SVGAnimatedPropertyDescriptionHash { struct SVGAnimatedPropertyDescriptionHashTraits : WTF::SimpleClassHashTraits<SVGAnimatedPropertyDescription> { }; -} - -#endif // ENABLE(SVG) -#endif // SVGAnimatedPropertyDescription_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h b/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h index 1ddbc5c6c..30f855679 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h +++ b/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h @@ -19,14 +19,13 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedPropertyMacros_h -#define SVGAnimatedPropertyMacros_h +#pragma once -#if ENABLE(SVG) #include "Element.h" #include "SVGAnimatedProperty.h" #include "SVGAttributeToPropertyMap.h" #include "SVGPropertyTraits.h" +#include <wtf/NeverDestroyed.h> #include <wtf/StdLibExtras.h> namespace WebCore { @@ -71,40 +70,36 @@ struct SVGSynchronizableAnimatedProperty { #define BEGIN_REGISTER_ANIMATED_PROPERTIES(OwnerType) \ SVGAttributeToPropertyMap& OwnerType::attributeToPropertyMap() \ { \ - DEFINE_STATIC_LOCAL(SVGAttributeToPropertyMap, s_attributeToPropertyMap, ()); \ - return s_attributeToPropertyMap; \ + static NeverDestroyed<SVGAttributeToPropertyMap> map; \ + return map; \ } \ \ static void registerAnimatedPropertiesFor##OwnerType() \ { \ - SVGAttributeToPropertyMap& map = OwnerType::attributeToPropertyMap(); \ + auto& map = OwnerType::attributeToPropertyMap(); \ if (!map.isEmpty()) \ return; \ typedef OwnerType UseOwnerType; -#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) \ - map.addProperty(UseOwnerType::LowerProperty##PropertyInfo()); - -#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) \ - map.addProperties(ClassName::attributeToPropertyMap()); \ - +#define REGISTER_LOCAL_ANIMATED_PROPERTY(LowerProperty) map.addProperty(*UseOwnerType::LowerProperty##PropertyInfo()); +#define REGISTER_PARENT_ANIMATED_PROPERTIES(ClassName) map.addProperties(ClassName::attributeToPropertyMap()); #define END_REGISTER_ANIMATED_PROPERTIES } // Property definition helpers (used in SVG*.cpp files) #define DEFINE_ANIMATED_PROPERTY(AnimatedPropertyTypeEnum, OwnerType, DOMAttribute, SVGDOMAttributeIdentifier, UpperProperty, LowerProperty) \ const SVGPropertyInfo* OwnerType::LowerProperty##PropertyInfo() { \ - DEFINE_STATIC_LOCAL(const SVGPropertyInfo, s_propertyInfo, \ + static NeverDestroyed<const SVGPropertyInfo> s_propertyInfo = SVGPropertyInfo \ (AnimatedPropertyTypeEnum, \ PropertyIsReadWrite, \ DOMAttribute, \ SVGDOMAttributeIdentifier, \ &OwnerType::synchronize##UpperProperty, \ - &OwnerType::lookupOrCreate##UpperProperty##Wrapper)); \ - return &s_propertyInfo; \ + &OwnerType::lookupOrCreate##UpperProperty##Wrapper); \ + return &s_propertyInfo.get(); \ } // Property declaration helpers (used in SVG*.h files) -#define BEGIN_DECLARE_ANIMATED_PROPERTIES(OwnerType) \ +#define BEGIN_DECLARE_ANIMATED_PROPERTIES_BASE(OwnerType) \ public: \ static SVGAttributeToPropertyMap& attributeToPropertyMap(); \ virtual SVGAttributeToPropertyMap& localAttributeToPropertyMap() \ @@ -113,33 +108,42 @@ public: \ } \ typedef OwnerType UseOwnerType; -#define DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \ +#define BEGIN_DECLARE_ANIMATED_PROPERTIES(OwnerType) \ +public: \ + static SVGAttributeToPropertyMap& attributeToPropertyMap(); \ + SVGAttributeToPropertyMap& localAttributeToPropertyMap() override \ + { \ + return attributeToPropertyMap(); \ + } \ + typedef OwnerType UseOwnerType; + +#define DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty, OverrideSpecifier) \ public: \ static const SVGPropertyInfo* LowerProperty##PropertyInfo(); \ PropertyType& LowerProperty() const \ { \ - if (TearOffType* wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) { \ + if (auto wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) { \ if (wrapper->isAnimating()) \ return wrapper->currentAnimatedValue(); \ } \ return m_##LowerProperty.value; \ } \ \ - PropertyType& LowerProperty##BaseValue() const \ + PropertyType& LowerProperty##BaseValue() const OverrideSpecifier \ { \ return m_##LowerProperty.value; \ } \ \ - void set##UpperProperty##BaseValue(const PropertyType& type, const bool validValue = true) \ + void set##UpperProperty##BaseValue(const PropertyType& type, const bool validValue = true) OverrideSpecifier \ { \ m_##LowerProperty.value = type; \ m_##LowerProperty.isValid = validValue; \ } \ \ - PassRefPtr<TearOffType> LowerProperty##Animated() \ + Ref<TearOffType> LowerProperty##Animated() \ { \ m_##LowerProperty.shouldSynchronize = true; \ - return static_pointer_cast<TearOffType>(lookupOrCreate##UpperProperty##Wrapper(this)); \ + return static_reference_cast<TearOffType>(lookupOrCreate##UpperProperty##Wrapper(this)); \ } \ \ bool LowerProperty##IsValid() const \ @@ -156,7 +160,7 @@ private: \ m_##LowerProperty.synchronize(this, LowerProperty##PropertyInfo()->attributeName, value); \ } \ \ - static PassRefPtr<SVGAnimatedProperty> lookupOrCreate##UpperProperty##Wrapper(SVGElement* maskedOwnerType) \ + static Ref<SVGAnimatedProperty> lookupOrCreate##UpperProperty##Wrapper(SVGElement* maskedOwnerType) \ { \ ASSERT(maskedOwnerType); \ UseOwnerType* ownerType = static_cast<UseOwnerType*>(maskedOwnerType); \ @@ -176,14 +180,11 @@ private: \ // List specific definition/declaration helpers #define DECLARE_ANIMATED_LIST_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \ -DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty) \ +DECLARE_ANIMATED_PROPERTY(TearOffType, PropertyType, UpperProperty, LowerProperty, ) \ void detachAnimated##UpperProperty##ListWrappers(unsigned newListSize) \ { \ - if (TearOffType* wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) \ + if (auto wrapper = SVGAnimatedProperty::lookupWrapper<UseOwnerType, TearOffType>(this, LowerProperty##PropertyInfo())) \ wrapper->detachListWrappers(newListSize); \ } -} - -#endif // ENABLE(SVG) -#endif // SVGAnimatedPropertyMacros_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h index d406ff5d0..fc62c9da4 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedPropertyTearOff.h @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) 2016 Apple Inc. 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 @@ -17,58 +18,60 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedPropertyTearOff_h -#define SVGAnimatedPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGAnimatedProperty.h" #include "SVGPropertyTearOff.h" namespace WebCore { -template<typename PropertyType> -class SVGAnimatedPropertyTearOff : public SVGAnimatedProperty { +template<typename T> +class SVGAnimatedPropertyTearOff final : public SVGAnimatedProperty { public: - typedef SVGPropertyTearOff<PropertyType> PropertyTearOff; - typedef PropertyType ContentType; + using PropertyTearOff = T; + using PropertyType = typename PropertyTearOff::PropertyType; + using ContentType = PropertyType; - virtual ~SVGAnimatedPropertyTearOff() + static Ref<SVGAnimatedPropertyTearOff<PropertyTearOff>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property) { - if (m_baseVal) { - ASSERT(m_baseVal->animatedProperty() == this); - m_baseVal->setAnimatedProperty(0); - } - if (m_animVal) { - ASSERT(m_animVal->animatedProperty() == this); - m_animVal->setAnimatedProperty(0); - } + ASSERT(contextElement); + return adoptRef(*new SVGAnimatedPropertyTearOff<PropertyTearOff>(contextElement, attributeName, animatedPropertyType, property)); } - PropertyTearOff* baseVal() + Ref<PropertyTearOff> baseVal() { - if (!m_baseVal) - m_baseVal = PropertyTearOff::create(this, BaseValRole, m_property); - return m_baseVal.get(); + if (m_baseVal) + return *m_baseVal; + + auto property = PropertyTearOff::create(*this, BaseValRole, m_property); + m_baseVal = property.ptr(); + return property; } - PropertyTearOff* animVal() + Ref<PropertyTearOff> animVal() { - if (!m_animVal) - m_animVal = PropertyTearOff::create(this, AnimValRole, m_property); - return m_animVal.get(); + if (m_animVal) + return *m_animVal; + + auto property = PropertyTearOff::create(*this, AnimValRole, m_property); + m_animVal = property.ptr(); + return property; } - static PassRefPtr<SVGAnimatedPropertyTearOff<PropertyType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property) + bool isAnimating() const final { return m_animatedProperty; } + + void propertyWillBeDeleted(const SVGProperty& property) final { - ASSERT(contextElement); - return adoptRef(new SVGAnimatedPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, property)); + if (&property == m_baseVal) + m_baseVal = nullptr; + else if (&property == m_animVal) + m_animVal = nullptr; } PropertyType& currentAnimatedValue() { - ASSERT(m_isAnimating); - ASSERT(m_animVal); - return m_animVal->propertyReference(); + ASSERT(isAnimating()); + return m_animatedProperty->propertyReference(); } const PropertyType& currentBaseValue() const @@ -78,32 +81,29 @@ public: void animationStarted(PropertyType* newAnimVal) { - ASSERT(!m_isAnimating); + ASSERT(!isAnimating()); ASSERT(newAnimVal); - animVal()->setValue(*newAnimVal); - m_isAnimating = true; + m_animatedProperty = animVal(); + m_animatedProperty->setValue(*newAnimVal); } void animationEnded() { - ASSERT(m_isAnimating); - ASSERT(m_animVal); - m_animVal->setValue(m_property); - m_isAnimating = false; + ASSERT(isAnimating()); + m_animatedProperty->setValue(m_property); + m_animatedProperty = nullptr; } void animValWillChange() { // no-op for non list types. - ASSERT(m_isAnimating); - ASSERT(m_animVal); + ASSERT(isAnimating()); } void animValDidChange() { // no-op for non list types. - ASSERT(m_isAnimating); - ASSERT(m_animVal); + ASSERT(isAnimating()); } private: @@ -114,11 +114,10 @@ private: } PropertyType& m_property; - RefPtr<PropertyTearOff> m_baseVal; - RefPtr<PropertyTearOff> m_animVal; + PropertyTearOff* m_baseVal { nullptr }; + PropertyTearOff* m_animVal { nullptr }; + + RefPtr<PropertyTearOff> m_animatedProperty; }; } - -#endif // ENABLE(SVG) -#endif // SVGAnimatedPropertyTearOff_h diff --git a/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h index b035bd91d..c5b2fd906 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedStaticPropertyTearOff.h @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. + * Copyright (C) 2016 Apple Inc. 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 @@ -17,11 +18,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedStaticPropertyTearOff_h -#define SVGAnimatedStaticPropertyTearOff_h +#pragma once -#if ENABLE(SVG) -#include "ExceptionCode.h" +#include "ExceptionOr.h" #include "SVGAnimatedProperty.h" namespace WebCore { @@ -31,34 +30,36 @@ class SVGAnimatedStaticPropertyTearOff : public SVGAnimatedProperty { public: typedef PropertyType ContentType; - PropertyType& baseVal() + virtual const PropertyType& baseVal() { return m_property; } - PropertyType& animVal() + virtual const PropertyType& animVal() { if (m_animatedProperty) return *m_animatedProperty; return m_property; } - virtual void setBaseVal(const PropertyType& property, ExceptionCode&) + virtual ExceptionOr<void> setBaseVal(const PropertyType& property) { m_property = property; commitChange(); + return { }; } - static PassRefPtr<SVGAnimatedStaticPropertyTearOff<PropertyType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property) + bool isAnimating() const override { return m_animatedProperty; } + + static Ref<SVGAnimatedStaticPropertyTearOff<PropertyType>> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property) { ASSERT(contextElement); - return adoptRef(new SVGAnimatedStaticPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, property)); + return adoptRef(*new SVGAnimatedStaticPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, property)); } PropertyType& currentAnimatedValue() { - ASSERT(m_isAnimating); - ASSERT(m_animatedProperty); + ASSERT(isAnimating()); return *m_animatedProperty; } @@ -69,40 +70,34 @@ public: void animationStarted(PropertyType* newAnimVal) { - ASSERT(!m_isAnimating); - ASSERT(!m_animatedProperty); + ASSERT(!isAnimating()); ASSERT(newAnimVal); m_animatedProperty = newAnimVal; - m_isAnimating = true; } void animationEnded() { - ASSERT(m_isAnimating); - ASSERT(m_animatedProperty); - m_animatedProperty = 0; - m_isAnimating = false; + ASSERT(isAnimating()); + m_animatedProperty = nullptr; } void animValWillChange() { // no-op for non list types. - ASSERT(m_isAnimating); - ASSERT(m_animatedProperty); + ASSERT(isAnimating()); } void animValDidChange() { // no-op for non list types. - ASSERT(m_isAnimating); - ASSERT(m_animatedProperty); + ASSERT(isAnimating()); } protected: SVGAnimatedStaticPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, PropertyType& property) : SVGAnimatedProperty(contextElement, attributeName, animatedPropertyType) , m_property(property) - , m_animatedProperty(0) + , m_animatedProperty(nullptr) { } @@ -112,6 +107,3 @@ private: }; } - -#endif // ENABLE(SVG) -#endif // SVGAnimatedStaticPropertyTearOff_h diff --git a/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h index ba133d4e4..435b3ac58 100644 --- a/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGAnimatedTransformListPropertyTearOff.h @@ -17,46 +17,46 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAnimatedTransformListPropertyTearOff_h -#define SVGAnimatedTransformListPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGAnimatedListPropertyTearOff.h" #include "SVGTransformList.h" -#include "SVGTransformListPropertyTearOff.h" namespace WebCore { -class SVGAnimatedTransformListPropertyTearOff : public SVGAnimatedListPropertyTearOff<SVGTransformList> { +class SVGAnimatedTransformListPropertyTearOff final : public SVGAnimatedListPropertyTearOff<SVGTransformListValues> { public: - virtual SVGListPropertyTearOff<SVGTransformList>* baseVal() override + static Ref<SVGAnimatedTransformListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGTransformListValues& values) { - if (!m_baseVal) - m_baseVal = SVGTransformListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers); - return static_cast<SVGListPropertyTearOff<SVGTransformList>*>(m_baseVal.get()); + ASSERT(contextElement); + return adoptRef(*new SVGAnimatedTransformListPropertyTearOff(contextElement, attributeName, animatedPropertyType, values)); } - virtual SVGListPropertyTearOff<SVGTransformList>* animVal() override + Ref<ListPropertyTearOff> baseVal() final { - if (!m_animVal) - m_animVal = SVGTransformListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers); - return static_cast<SVGListPropertyTearOff<SVGTransformList>*>(m_animVal.get()); + if (m_baseVal) + return *m_baseVal; + + auto property = SVGTransformList::create(*this, BaseValRole, m_values, m_wrappers); + m_baseVal = property.ptr(); + return property; } - static PassRefPtr<SVGAnimatedTransformListPropertyTearOff> create(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGTransformList& values) + Ref<ListPropertyTearOff> animVal() final { - ASSERT(contextElement); - return adoptRef(new SVGAnimatedTransformListPropertyTearOff(contextElement, attributeName, animatedPropertyType, values)); + if (m_animVal) + return *m_animVal; + + auto property = SVGTransformList::create(*this, AnimValRole, m_values, m_wrappers); + m_animVal = property.ptr(); + return property; } private: - SVGAnimatedTransformListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGTransformList& values) - : SVGAnimatedListPropertyTearOff<SVGTransformList>(contextElement, attributeName, animatedPropertyType, values) + SVGAnimatedTransformListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType, SVGTransformListValues& values) + : SVGAnimatedListPropertyTearOff<SVGTransformListValues>(contextElement, attributeName, animatedPropertyType, values) { } }; -} - -#endif // ENABLE(SVG) -#endif // SVGAnimatedTransformListPropertyTearOff_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp b/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp index 2c3949bed..9629e58ca 100644 --- a/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp +++ b/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2011. All rights reserved. + * Copyright (C) 2015 Apple Inc. 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 @@ -18,113 +19,68 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "SVGAttributeToPropertyMap.h" #include "SVGAnimatedProperty.h" -#include "SVGPropertyInfo.h" namespace WebCore { void SVGAttributeToPropertyMap::addProperties(const SVGAttributeToPropertyMap& map) { - AttributeToPropertiesMap::const_iterator end = map.m_map.end(); - for (AttributeToPropertiesMap::const_iterator it = map.m_map.begin(); it != end; ++it) { - const PropertiesVector* vector = it->value.get(); - ASSERT(vector); - - // FIXME: This looks up the attribute name in the hash table for each property, even though all the - // properties in a single vector are guaranteed to have the same attribute name. - // FIXME: This grows the vector one item at a time, even though we know up front exactly how many - // elements we are adding to the vector. - PropertiesVector::const_iterator vectorEnd = vector->end(); - for (PropertiesVector::const_iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt) - addProperty(*vectorIt); + for (auto& vector : map.m_map.values()) { + ASSERT(!vector.isEmpty()); + auto& properties = m_map.add(vector[0]->attributeName, PropertyInfoVector()).iterator->value; + properties.reserveCapacity(properties.size() + vector.size()); + for (auto* property : vector) + properties.uncheckedAppend(property); } } -void SVGAttributeToPropertyMap::addProperty(const SVGPropertyInfo* info) +void SVGAttributeToPropertyMap::addProperty(const SVGPropertyInfo& info) { - ASSERT(info); - ASSERT(info->attributeName != anyQName()); - if (PropertiesVector* vector = m_map.get(info->attributeName)) { - vector->append(info); - return; - } - // FIXME: This does a second hash table lookup, but with HashMap::add we could instead do only one. - auto vector = std::make_unique<PropertiesVector>(); - vector->append(info); - m_map.set(info->attributeName, std::move(vector)); + m_map.add(info.attributeName, PropertyInfoVector()).iterator->value.append(&info); } -void SVGAttributeToPropertyMap::animatedPropertiesForAttribute(SVGElement* ownerType, const QualifiedName& attributeName, Vector<RefPtr<SVGAnimatedProperty>>& properties) +Vector<RefPtr<SVGAnimatedProperty>> SVGAttributeToPropertyMap::properties(SVGElement& contextElement, const QualifiedName& attributeName) const { - ASSERT(ownerType); - PropertiesVector* vector = m_map.get(attributeName); - if (!vector) - return; - - PropertiesVector::iterator vectorEnd = vector->end(); - for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt) - properties.append(animatedProperty(ownerType, attributeName, *vectorIt)); + Vector<RefPtr<SVGAnimatedProperty>> properties; + auto it = m_map.find(attributeName); + if (it == m_map.end()) + return properties; + properties.reserveInitialCapacity(it->value.size()); + for (auto* property : it->value) + properties.uncheckedAppend(property->lookupOrCreateWrapperForAnimatedProperty(&contextElement)); + return properties; } -void SVGAttributeToPropertyMap::animatedPropertyTypeForAttribute(const QualifiedName& attributeName, Vector<AnimatedPropertyType>& propertyTypes) +Vector<AnimatedPropertyType> SVGAttributeToPropertyMap::types(const QualifiedName& attributeName) const { - PropertiesVector* vector = m_map.get(attributeName); - if (!vector) - return; - - PropertiesVector::iterator vectorEnd = vector->end(); - for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt) - propertyTypes.append((*vectorIt)->animatedPropertyType); + Vector<AnimatedPropertyType> types; + auto it = m_map.find(attributeName); + if (it == m_map.end()) + return types; + types.reserveInitialCapacity(it->value.size()); + for (auto* property : it->value) + types.uncheckedAppend(property->animatedPropertyType); + return types; } -void SVGAttributeToPropertyMap::synchronizeProperties(SVGElement* contextElement) +void SVGAttributeToPropertyMap::synchronizeProperties(SVGElement& contextElement) const { - ASSERT(contextElement); - AttributeToPropertiesMap::iterator end = m_map.end(); - for (AttributeToPropertiesMap::iterator it = m_map.begin(); it != end; ++it) { - PropertiesVector* vector = it->value.get(); - ASSERT(vector); - - PropertiesVector::iterator vectorEnd = vector->end(); - for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt) - synchronizeProperty(contextElement, it->key, *vectorIt); + for (auto& vector : m_map.values()) { + for (auto* property : vector) + property->synchronizeProperty(&contextElement); } } -bool SVGAttributeToPropertyMap::synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName) +bool SVGAttributeToPropertyMap::synchronizeProperty(SVGElement& contextElement, const QualifiedName& attributeName) const { - ASSERT(contextElement); - PropertiesVector* vector = m_map.get(attributeName); - if (!vector) + auto it = m_map.find(attributeName); + if (it == m_map.end()) return false; - - PropertiesVector::iterator vectorEnd = vector->end(); - for (PropertiesVector::iterator vectorIt = vector->begin(); vectorIt != vectorEnd; ++vectorIt) - synchronizeProperty(contextElement, attributeName, *vectorIt); - + for (auto* property : it->value) + property->synchronizeProperty(&contextElement); return true; } -void SVGAttributeToPropertyMap::synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo* info) -{ - ASSERT(info); - ASSERT_UNUSED(attributeName, attributeName == info->attributeName); - ASSERT(info->synchronizeProperty); - (*info->synchronizeProperty)(contextElement); -} - -PassRefPtr<SVGAnimatedProperty> SVGAttributeToPropertyMap::animatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo* info) -{ - ASSERT(info); - ASSERT_UNUSED(attributeName, attributeName == info->attributeName); - ASSERT(info->lookupOrCreateWrapperForAnimatedProperty); - return (*info->lookupOrCreateWrapperForAnimatedProperty)(contextElement); } - -} - -#endif diff --git a/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h b/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h index 0ba24254e..94768056a 100644 --- a/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h +++ b/Source/WebCore/svg/properties/SVGAttributeToPropertyMap.h @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2011. All rights reserved. + * Copyright (C) 2015 Apple Inc. 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 @@ -17,10 +18,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGAttributeToPropertyMap_h -#define SVGAttributeToPropertyMap_h +#pragma once -#if ENABLE(SVG) #include "SVGPropertyInfo.h" #include <wtf/HashMap.h> @@ -33,27 +32,18 @@ class SVGAttributeToPropertyMap { public: bool isEmpty() const { return m_map.isEmpty(); } + void addProperty(const SVGPropertyInfo&); void addProperties(const SVGAttributeToPropertyMap&); - void addProperty(const SVGPropertyInfo*); - // FIXME: To match WebKit coding style either these functions should have return values instead of out parameters, - // or the word "get" should be added as a prefix to their names. - void animatedPropertiesForAttribute(SVGElement* contextElement, const QualifiedName& attributeName, Vector<RefPtr<SVGAnimatedProperty>>&); - void animatedPropertyTypeForAttribute(const QualifiedName& attributeName, Vector<AnimatedPropertyType>&); + Vector<RefPtr<SVGAnimatedProperty>> properties(SVGElement&, const QualifiedName& attributeName) const; + Vector<AnimatedPropertyType> types(const QualifiedName& attributeName) const; - void synchronizeProperties(SVGElement* contextElement); - bool synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName); + void synchronizeProperties(SVGElement&) const; + bool synchronizeProperty(SVGElement&, const QualifiedName& attributeName) const; private: - void synchronizeProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo*); - PassRefPtr<SVGAnimatedProperty> animatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, const SVGPropertyInfo*); - - typedef Vector<const SVGPropertyInfo*> PropertiesVector; - typedef HashMap<QualifiedName, std::unique_ptr<PropertiesVector>> AttributeToPropertiesMap; - AttributeToPropertiesMap m_map; + typedef Vector<const SVGPropertyInfo*> PropertyInfoVector; + HashMap<QualifiedName, PropertyInfoVector> m_map; }; -} - -#endif -#endif +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGListProperty.h b/Source/WebCore/svg/properties/SVGListProperty.h index 80c4b62d8..9b0d42032 100644 --- a/Source/WebCore/svg/properties/SVGListProperty.h +++ b/Source/WebCore/svg/properties/SVGListProperty.h @@ -17,13 +17,13 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGListProperty_h -#define SVGListProperty_h +#pragma once -#if ENABLE(SVG) +#include "ExceptionCode.h" #include "SVGException.h" #include "SVGPropertyTearOff.h" #include "SVGPropertyTraits.h" +#include <wtf/Ref.h> namespace WebCore { @@ -43,18 +43,15 @@ 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; + using ListItemType = typename SVGPropertyTraits<PropertyType>::ListItemType; + using ListItemTearOff = typename SVGPropertyTraits<PropertyType>::ListItemTearOff; + using AnimatedListPropertyTearOff = SVGAnimatedListPropertyTearOff<PropertyType>; + using ListWrapperCache = typename AnimatedListPropertyTearOff::ListWrapperCache; - bool canAlterList(ExceptionCode& ec) const + ExceptionOr<bool> canAlterList() const { - if (m_role == AnimValRole) { - ec = NO_MODIFICATION_ALLOWED_ERR; - return false; - } + if (m_role == AnimValRole) + return Exception { NO_MODIFICATION_ALLOWED_ERR }; return true; } @@ -63,9 +60,8 @@ public: { // See SVGPropertyTearOff::detachWrapper() for an explanation about what's happening here. ASSERT(wrappers); - unsigned size = wrappers->size(); - for (unsigned i = 0; i < size; ++i) { - if (ListItemTearOff* item = wrappers->at(i).get()) + for (auto& item : *wrappers) { + if (item) item->detachWrapper(); } @@ -97,23 +93,29 @@ public: } // SVGList::clear() - void clearValues(ExceptionCode& ec) + ExceptionOr<void> clearValues() { - if (!canAlterList(ec)) - return; + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); m_values->clear(); commitChange(); + return { }; } - void clearValuesAndWrappers(ExceptionCode& ec) + ExceptionOr<void> clearValuesAndWrappers() { - if (!canAlterList(ec)) - return; + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); detachListWrappers(0); m_values->clear(); commitChange(); + return { }; } // SVGList::numberOfItems() @@ -123,10 +125,12 @@ public: } // SVGList::initialize() - ListItemType initializeValues(const ListItemType& newItem, ExceptionCode& ec) + ExceptionOr<ListItemType> initializeValues(const ListItemType& newItem) { - if (!canAlterList(ec)) - return ListItemType(); + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // 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); @@ -136,24 +140,22 @@ public: m_values->append(newItem); commitChange(); - return newItem; + return ListItemType { newItem }; } - PassListItemTearOff initializeValuesAndWrappers(PassListItemTearOff passNewItem, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> initializeValuesAndWrappers(ListItemTearOff& item) { ASSERT(m_wrappers); - 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; - } + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); - RefPtr<ListItemTearOff> newItem = passNewItem; ASSERT(m_values->size() == m_wrappers->size()); + Ref<ListItemTearOff> newItem(item); + // 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); @@ -162,37 +164,40 @@ public: m_values->clear(); m_values->append(newItem->propertyReference()); - m_wrappers->append(newItem); + m_wrappers->append(newItem.ptr()); commitChange(); - return newItem.release(); + return WTFMove(newItem); } // SVGList::getItem() - bool canGetItem(unsigned index, ExceptionCode& ec) + ExceptionOr<bool> canGetItem(unsigned index) { - if (index >= m_values->size()) { - ec = INDEX_SIZE_ERR; - return false; - } + if (index >= m_values->size()) + return Exception { INDEX_SIZE_ERR }; return true; } - ListItemType getItemValues(unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> getItemValues(unsigned index) { - if (!canGetItem(index, ec)) - return ListItemType(); + auto result = canGetItem(index); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // Spec: Returns the specified item from the list. The returned item is the item itself and not a copy. - return m_values->at(index); + return ListItemType { m_values->at(index) }; } - PassListItemTearOff getItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> getItemValuesAndWrappers(AnimatedListPropertyTearOff& animatedList, unsigned index) { ASSERT(m_wrappers); - if (!canGetItem(index, ec)) - return 0; + + auto result = canGetItem(index); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // 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. @@ -206,14 +211,16 @@ public: m_wrappers->at(index) = wrapper; } - return wrapper.release(); + return wrapper.releaseNonNull(); } // SVGList::insertItemBefore() - ListItemType insertItemBeforeValues(const ListItemType& newItem, unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> insertItemBeforeValues(const ListItemType& newItem, unsigned index) { - if (!canAlterList(ec)) - return ListItemType(); + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. if (index > m_values->size()) @@ -222,7 +229,7 @@ public: // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list. if (!processIncomingListItemValue(newItem, &index)) { // Inserting the item before itself is a no-op. - return newItem; + return ListItemType { newItem }; } // 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 @@ -230,107 +237,103 @@ public: m_values->insert(index, newItem); commitChange(); - return newItem; + return ListItemType { newItem }; } - PassListItemTearOff insertItemBeforeValuesAndWrappers(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> insertItemBeforeValuesAndWrappers(ListItemTearOff& item, unsigned index) { ASSERT(m_wrappers); - 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; - } + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list. if (index > m_values->size()) - index = m_values->size(); + index = m_values->size(); - RefPtr<ListItemTearOff> newItem = passNewItem; ASSERT(m_values->size() == m_wrappers->size()); + Ref<ListItemTearOff> newItem(item); + // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list. if (!processIncomingListItemWrapper(newItem, &index)) - return newItem.release(); + return WTFMove(newItem); // Spec: Inserts a new item into the list at the specified position. The index of the item before which the new item is to be // inserted. The first item is number 0. If the index is equal to 0, then the new item is inserted at the front of the list. m_values->insert(index, newItem->propertyReference()); // Store new wrapper at position 'index', change its underlying value, so mutations of newItem, directly affect the item in the list. - m_wrappers->insert(index, newItem); + m_wrappers->insert(index, newItem.ptr()); commitChange(); - return newItem.release(); + return WTFMove(newItem); } // SVGList::replaceItem() - bool canReplaceItem(unsigned index, ExceptionCode& ec) + ExceptionOr<bool> canReplaceItem(unsigned index) { - if (!canAlterList(ec)) - return false; + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); - if (index >= m_values->size()) { - ec = INDEX_SIZE_ERR; - return false; - } + if (index >= m_values->size()) + return Exception { INDEX_SIZE_ERR }; return true; } - ListItemType replaceItemValues(const ListItemType& newItem, unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> replaceItemValues(const ListItemType& newItem, unsigned index) { - if (!canReplaceItem(index, ec)) - return ListItemType(); + auto result = canReplaceItem(index); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // 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. if (!processIncomingListItemValue(newItem, &index)) { // Replacing the item with itself is a no-op. - return newItem; + return ListItemType { newItem }; } if (m_values->isEmpty()) { // 'newItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace. - ec = INDEX_SIZE_ERR; - return ListItemType(); + return Exception { INDEX_SIZE_ERR }; } // Update the value at the desired position 'index'. m_values->at(index) = newItem; commitChange(); - return newItem; + return ListItemType { newItem }; } - PassListItemTearOff replaceItemValuesAndWrappers(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> replaceItemValuesAndWrappers(ListItemTearOff& item, unsigned index) { ASSERT(m_wrappers); - if (!canReplaceItem(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; - } + auto result = canReplaceItem(index); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); ASSERT(m_values->size() == m_wrappers->size()); - RefPtr<ListItemTearOff> newItem = passNewItem; + + Ref<ListItemTearOff> newItem(item); // 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. if (!processIncomingListItemWrapper(newItem, &index)) - return newItem.release(); + return WTFMove(newItem); if (m_values->isEmpty()) { ASSERT(m_wrappers->isEmpty()); - // 'passNewItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace. - ec = INDEX_SIZE_ERR; - return 0; + // 'newItem' already lived in our list, we removed it, and now we're empty, which means there's nothing to replace. + return Exception { INDEX_SIZE_ERR }; } // Detach the existing wrapper. @@ -340,43 +343,48 @@ public: // Update the value and the wrapper at the desired position 'index'. m_values->at(index) = newItem->propertyReference(); - m_wrappers->at(index) = newItem; + m_wrappers->at(index) = newItem.ptr(); commitChange(); - return newItem.release(); + return WTFMove(newItem); } // SVGList::removeItem() - bool canRemoveItem(unsigned index, ExceptionCode& ec) + ExceptionOr<bool> canRemoveItem(unsigned index) { - if (!canAlterList(ec)) - return false; + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); - if (index >= m_values->size()) { - ec = INDEX_SIZE_ERR; - return false; - } + if (index >= m_values->size()) + return Exception { INDEX_SIZE_ERR }; return true; } - ListItemType removeItemValues(unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> removeItemValues(unsigned index) { - if (!canRemoveItem(index, ec)) - return ListItemType(); + auto result = canRemoveItem(index); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); ListItemType oldItem = m_values->at(index); m_values->remove(index); commitChange(); - return oldItem; + return WTFMove(oldItem); } - PassListItemTearOff removeItemValuesAndWrappers(AnimatedListPropertyTearOff* animatedList, unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> removeItemValuesAndWrappers(AnimatedListPropertyTearOff& animatedList, unsigned index) { ASSERT(m_wrappers); - if (!canRemoveItem(index, ec)) - return 0; + + auto result = canRemoveItem(index); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); ASSERT(m_values->size() == m_wrappers->size()); @@ -390,14 +398,16 @@ public: m_values->remove(index); commitChange(); - return oldItem.release(); + return oldItem.releaseNonNull(); } // SVGList::appendItem() - ListItemType appendItemValues(const ListItemType& newItem, ExceptionCode& ec) + ExceptionOr<ListItemType> appendItemValues(const ListItemType& newItem) { - if (!canAlterList(ec)) - return ListItemType(); + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); // 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); @@ -406,33 +416,31 @@ public: m_values->append(newItem); commitChange(ListModificationAppend); - return newItem; + return ListItemType { newItem }; } - PassListItemTearOff appendItemValuesAndWrappers(PassListItemTearOff passNewItem, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> appendItemValuesAndWrappers(ListItemTearOff& item) { ASSERT(m_wrappers); - 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; - } + auto result = canAlterList(); + if (result.hasException()) + return result.releaseException(); + ASSERT(result.releaseReturnValue()); - RefPtr<ListItemTearOff> newItem = passNewItem; ASSERT(m_values->size() == m_wrappers->size()); + Ref<ListItemTearOff> newItem(item); + // 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. m_values->append(newItem->propertyReference()); - m_wrappers->append(newItem); + m_wrappers->append(newItem.ptr()); commitChange(ListModificationAppend); - return newItem.release(); + return WTFMove(newItem); } PropertyType& values() @@ -462,14 +470,14 @@ protected: delete m_values; } - virtual void commitChange() = 0; + void commitChange() override = 0; virtual void commitChange(ListModification) { commitChange(); } virtual bool processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify) = 0; - virtual bool processIncomingListItemWrapper(RefPtr<ListItemTearOff>& newItem, unsigned* indexToModify) = 0; + virtual bool processIncomingListItemWrapper(Ref<ListItemTearOff>& newItem, unsigned* indexToModify) = 0; SVGPropertyRole m_role; bool m_ownsValues; @@ -478,6 +486,3 @@ protected: }; } - -#endif // ENABLE(SVG) -#endif // SVGListProperty_h diff --git a/Source/WebCore/svg/properties/SVGListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGListPropertyTearOff.h index 674d93d75..86f70b53d 100644 --- a/Source/WebCore/svg/properties/SVGListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGListPropertyTearOff.h @@ -17,10 +17,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGListPropertyTearOff_h -#define SVGListPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGListProperty.h" namespace WebCore { @@ -28,23 +26,22 @@ namespace WebCore { template<typename PropertyType> class SVGListPropertyTearOff : public SVGListProperty<PropertyType> { public: - typedef SVGListProperty<PropertyType> Base; - typedef SVGListPropertyTearOff<PropertyType> Self; + using Base = SVGListProperty<PropertyType>; + using Self = SVGListPropertyTearOff<PropertyType>; - typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType; - typedef SVGPropertyTearOff<ListItemType> ListItemTearOff; - typedef PassRefPtr<ListItemTearOff> PassListItemTearOff; - typedef SVGAnimatedListPropertyTearOff<PropertyType> AnimatedListPropertyTearOff; - typedef typename SVGAnimatedListPropertyTearOff<PropertyType>::ListWrapperCache ListWrapperCache; + using ListItemType = typename SVGPropertyTraits<PropertyType>::ListItemType; + using ListItemTearOff = typename SVGPropertyTraits<PropertyType>::ListItemTearOff; + using PtrListItemTearOff = RefPtr<ListItemTearOff>; + using AnimatedListPropertyTearOff = SVGAnimatedListPropertyTearOff<PropertyType>; + using ListWrapperCache = typename SVGAnimatedListPropertyTearOff<PropertyType>::ListWrapperCache; using Base::m_role; using Base::m_values; using Base::m_wrappers; - static PassRefPtr<Self> create(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, PropertyType& values, ListWrapperCache& wrappers) + static Ref<Self> create(AnimatedListPropertyTearOff& animatedProperty, SVGPropertyRole role, PropertyType& values, ListWrapperCache& wrappers) { - ASSERT(animatedProperty); - return adoptRef(new Self(animatedProperty, role, values, wrappers)); + return adoptRef(*new Self(animatedProperty, role, values, wrappers)); } int findItem(ListItemTearOff* item) const @@ -79,58 +76,63 @@ public: } // SVGList API - void clear(ExceptionCode& ec) + ExceptionOr<void> clear() { - Base::clearValuesAndWrappers(ec); + return Base::clearValuesAndWrappers(); } - PassListItemTearOff initialize(PassListItemTearOff passNewItem, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> initialize(ListItemTearOff& newItem) { - return Base::initializeValuesAndWrappers(passNewItem, ec); + return Base::initializeValuesAndWrappers(newItem); } - PassListItemTearOff getItem(unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> getItem(unsigned index) { - return Base::getItemValuesAndWrappers(m_animatedProperty.get(), index, ec); + return Base::getItemValuesAndWrappers(m_animatedProperty.get(), index); } - PassListItemTearOff insertItemBefore(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> insertItemBefore(ListItemTearOff& newItem, unsigned index) { - return Base::insertItemBeforeValuesAndWrappers(passNewItem, index, ec); + return Base::insertItemBeforeValuesAndWrappers(newItem, index); } - PassListItemTearOff replaceItem(PassListItemTearOff passNewItem, unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> replaceItem(ListItemTearOff& newItem, unsigned index) { - return Base::replaceItemValuesAndWrappers(passNewItem, index, ec); + return Base::replaceItemValuesAndWrappers(newItem, index); } - PassListItemTearOff removeItem(unsigned index, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> removeItem(unsigned index) { - return Base::removeItemValuesAndWrappers(m_animatedProperty.get(), index, ec); + return Base::removeItemValuesAndWrappers(m_animatedProperty.get(), index); } - PassListItemTearOff appendItem(PassListItemTearOff passNewItem, ExceptionCode& ec) + ExceptionOr<Ref<ListItemTearOff>> appendItem(ListItemTearOff& newItem) { - return Base::appendItemValuesAndWrappers(passNewItem, ec); + return Base::appendItemValuesAndWrappers(newItem); } protected: - SVGListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, PropertyType& values, ListWrapperCache& wrappers) + SVGListPropertyTearOff(AnimatedListPropertyTearOff& animatedProperty, SVGPropertyRole role, PropertyType& values, ListWrapperCache& wrappers) : SVGListProperty<PropertyType>(role, values, &wrappers) , m_animatedProperty(animatedProperty) { } - virtual bool isReadOnly() const override + virtual ~SVGListPropertyTearOff() + { + m_animatedProperty->propertyWillBeDeleted(*this); + } + + bool isReadOnly() const override { if (m_role == AnimValRole) return true; - if (m_animatedProperty && m_animatedProperty->isReadOnly()) + if (m_animatedProperty->isReadOnly()) return true; return false; } - virtual void commitChange() override + void commitChange() override { ASSERT(m_values); ASSERT(m_wrappers); @@ -142,20 +144,20 @@ protected: ListItemTearOff* item = m_wrappers->at(i).get(); if (!item) continue; - item->setAnimatedProperty(m_animatedProperty.get()); + item->setAnimatedProperty(m_animatedProperty.ptr()); item->setValue(m_values->at(i)); } m_animatedProperty->commitChange(); } - virtual bool processIncomingListItemValue(const ListItemType&, unsigned*) override + bool processIncomingListItemValue(const ListItemType&, unsigned*) override { ASSERT_NOT_REACHED(); return true; } - virtual bool processIncomingListItemWrapper(RefPtr<ListItemTearOff>& newItem, unsigned* indexToModify) override + bool processIncomingListItemWrapper(Ref<ListItemTearOff>& newItem, unsigned* indexToModify) override { SVGAnimatedProperty* animatedPropertyOfItem = newItem->animatedProperty(); @@ -178,9 +180,9 @@ protected: // 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; + bool livesInOtherList = animatedPropertyOfItem != m_animatedProperty.ptr(); AnimatedListPropertyTearOff* propertyTearOff = static_cast<AnimatedListPropertyTearOff*>(animatedPropertyOfItem); - int indexToRemove = propertyTearOff->findItem(newItem.get()); + int indexToRemove = propertyTearOff->findItem(newItem.ptr()); ASSERT(indexToRemove != -1); // Do not remove newItem if already in this list at the target index. @@ -205,10 +207,7 @@ protected: // 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; + Ref<AnimatedListPropertyTearOff> m_animatedProperty; }; } - -#endif // ENABLE(SVG) -#endif // SVGListPropertyTearOff_h diff --git a/Source/WebCore/svg/properties/SVGMatrixTearOff.h b/Source/WebCore/svg/properties/SVGMatrixTearOff.h index a7ae98855..0188031ce 100644 --- a/Source/WebCore/svg/properties/SVGMatrixTearOff.h +++ b/Source/WebCore/svg/properties/SVGMatrixTearOff.h @@ -17,46 +17,43 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGMatrixTearOff_h -#define SVGMatrixTearOff_h +#pragma once -#if ENABLE(SVG) -#include "SVGPropertyTearOff.h" +#include "SVGMatrix.h" #include "SVGTransform.h" namespace WebCore { -class SVGMatrixTearOff : public SVGPropertyTearOff<SVGMatrix> { +class SVGMatrixTearOff final : public SVGMatrix { public: - // 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<SVGMatrixTearOff> create(SVGPropertyTearOff<SVGTransform>& parent, SVGMatrix& value) + static Ref<SVGMatrixTearOff> create(SVGTransform& parent, SVGMatrixValue& value) { - RefPtr<SVGMatrixTearOff> result = adoptRef(new SVGMatrixTearOff(&parent, value)); + ASSERT_UNUSED(value, &parent.propertyReference().svgMatrix() == &value); + Ref<SVGMatrixTearOff> result = adoptRef(*new SVGMatrixTearOff(parent)); parent.addChild(result->m_weakFactory.createWeakPtr()); - return result.release(); + return result; } - virtual void commitChange() + SVGMatrixValue& propertyReference() final { return m_parent->propertyReference().svgMatrix(); } + + void setValue(SVGMatrixValue& value) final { m_parent->propertyReference().setMatrix(value); } + + void commitChange() final { m_parent->propertyReference().updateSVGMatrix(); m_parent->commitChange(); } private: - SVGMatrixTearOff(SVGPropertyTearOff<SVGTransform>* parent, SVGMatrix& value) - : SVGPropertyTearOff<SVGMatrix>(0, UndefinedRole, value) - , m_parent(parent) + SVGMatrixTearOff(SVGTransform& parent) + : SVGMatrix(nullptr) + , m_parent(&parent) , m_weakFactory(this) { } - RefPtr<SVGPropertyTearOff<SVGTransform>> m_parent; + RefPtr<SVGTransform> m_parent; WeakPtrFactory<SVGPropertyTearOffBase> m_weakFactory; }; -} - -#endif // ENABLE(SVG) -#endif // SVGMatrixTearOff_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp b/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp deleted file mode 100644 index 573d453a4..000000000 --- a/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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::clearContextAndRoles() -{ - ASSERT(m_values); - unsigned size = m_values->size(); - for (unsigned i = 0; i < size; ++i) { - ListItemType item = m_values->at(i); - static_cast<SVGPathSegWithContext*>(item.get())->setContextAndRole(0, PathSegUndefinedRole); - } -} - -void SVGPathSegListPropertyTearOff::clear(ExceptionCode& ec) -{ - ASSERT(m_values); - if (m_values->isEmpty()) - return; - - clearContextAndRoles(); - SVGPathSegListPropertyTearOff::Base::clearValues(ec); -} - -SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::getItem(unsigned index, ExceptionCode& ec) -{ - ListItemType returnedItem = Base::getItemValues(index, ec); - if (returnedItem) { - ASSERT(static_cast<SVGPathSegWithContext*>(returnedItem.get())->contextElement() == contextElement()); - ASSERT(static_cast<SVGPathSegWithContext*>(returnedItem.get())->role() == m_pathSegRole); - } - return returnedItem.release(); -} - -SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::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; - } - - if (index < m_values->size()) { - ListItemType replacedItem = m_values->at(index); - ASSERT(replacedItem); - static_cast<SVGPathSegWithContext*>(replacedItem.get())->setContextAndRole(0, PathSegUndefinedRole); - } - - ListItemType newItem = passNewItem; - return Base::replaceItemValues(newItem, index, ec); -} - -SVGPathSegListPropertyTearOff::PassListItemType SVGPathSegListPropertyTearOff::removeItem(unsigned index, ExceptionCode& ec) -{ - SVGPathSegListPropertyTearOff::ListItemType removedItem = SVGPathSegListPropertyTearOff::Base::removeItemValues(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); - return toSVGPathElement(contextElement); -} - -bool 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 true; - - // 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 true; - - // 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; - SVGAnimatedPathSegListPropertyTearOff* propertyTearOff = static_cast<SVGAnimatedPathSegListPropertyTearOff*>(animatedPropertyOfItem); - int indexToRemove = propertyTearOff->findItem(newItem.get()); - ASSERT(indexToRemove != -1); - - // Do not remove newItem if already in this list at the target index. - if (!livesInOtherList && indexToModify && static_cast<unsigned>(indexToRemove) == *indexToModify) - return false; - - propertyTearOff->removeItemFromList(indexToRemove, livesInOtherList); - - if (!indexToModify) - return true; - - // 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>(indexToRemove) < index) - --index; - } - - return true; -} - -} - -#endif // ENABLE(SVG) diff --git a/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h deleted file mode 100644 index aaed821bf..000000000 --- a/Source/WebCore/svg/properties/SVGPathSegListPropertyTearOff.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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, SVGPathSegList& values, ListWrapperCache& wrappers) - { - ASSERT(animatedProperty); - return adoptRef(new SVGPathSegListPropertyTearOff(animatedProperty, role, pathSegRole, values, wrappers)); - } - - int findItem(const ListItemType& item) const - { - ASSERT(m_values); - - unsigned size = m_values->size(); - for (size_t i = 0; i < size; ++i) { - if (item == m_values->at(i)) - return i; - } - - return -1; - } - - void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers) - { - ASSERT(m_values); - ASSERT_WITH_SECURITY_IMPLICATION(itemIndex < m_values->size()); - - m_values->remove(itemIndex); - - if (shouldSynchronizeWrappers) - commitChange(); - } - - // SVGList API - void clear(ExceptionCode&); - - 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; - } - - clearContextAndRoles(); - ListItemType newItem = passNewItem; - return Base::initializeValues(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; - return Base::insertItemBeforeValues(newItem, index, ec); - } - - PassListItemType replaceItem(PassListItemType, unsigned index, ExceptionCode&); - - 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; - return Base::appendItemValues(newItem, ec); - } - -private: - SVGPathSegListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGPathSegRole pathSegRole, SVGPathSegList& values, ListWrapperCache& wrappers) - : SVGListProperty<SVGPathSegList>(role, values, &wrappers) - , m_animatedProperty(animatedProperty) - , m_pathSegRole(pathSegRole) - { - } - - SVGPathElement* contextElement() const; - - void clearContextAndRoles(); - - using Base::m_role; - - virtual bool isReadOnly() const override - { - if (m_role == AnimValRole) - return true; - if (m_animatedProperty && m_animatedProperty->isReadOnly()) - return true; - return false; - } - - virtual void commitChange() override - { - ASSERT(m_values); - m_values->commitChange(m_animatedProperty->contextElement(), ListModificationUnknown); - } - - virtual void commitChange(ListModification listModification) override - { - ASSERT(m_values); - m_values->commitChange(m_animatedProperty->contextElement(), listModification); - } - - virtual bool processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify) override; - virtual bool processIncomingListItemWrapper(RefPtr<ListItemTearOff>&, unsigned*) override - { - ASSERT_NOT_REACHED(); - return true; - } - -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 index 69394e3f5..b236cee04 100644 --- a/Source/WebCore/svg/properties/SVGProperty.h +++ b/Source/WebCore/svg/properties/SVGProperty.h @@ -17,10 +17,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGProperty_h -#define SVGProperty_h +#pragma once -#if ENABLE(SVG) #include <wtf/RefCounted.h> namespace WebCore { @@ -39,7 +37,4 @@ public: virtual void commitChange() = 0; }; -} - -#endif // ENABLE(SVG) -#endif // SVGProperty_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGPropertyInfo.cpp b/Source/WebCore/svg/properties/SVGPropertyInfo.cpp index 43063246c..45c862cd5 100644 --- a/Source/WebCore/svg/properties/SVGPropertyInfo.cpp +++ b/Source/WebCore/svg/properties/SVGPropertyInfo.cpp @@ -20,8 +20,6 @@ #include "config.h" #include "SVGPropertyInfo.h" -#if ENABLE(SVG) - namespace WebCore { SVGPropertyInfo::SVGPropertyInfo(AnimatedPropertyType newType, AnimatedPropertyState newState, const QualifiedName& newAttributeName, const AtomicString& newPropertyIdentifier, SynchronizeProperty newSynchronizeProperty, LookupOrCreateWrapperForAnimatedProperty newLookupOrCreateWrapperForAnimatedProperty) @@ -35,5 +33,3 @@ SVGPropertyInfo::SVGPropertyInfo(AnimatedPropertyType newType, AnimatedPropertyS } } // namespace - -#endif // ENABLE(SVG) diff --git a/Source/WebCore/svg/properties/SVGPropertyInfo.h b/Source/WebCore/svg/properties/SVGPropertyInfo.h index 54778ee9e..165f9b5b7 100644 --- a/Source/WebCore/svg/properties/SVGPropertyInfo.h +++ b/Source/WebCore/svg/properties/SVGPropertyInfo.h @@ -17,12 +17,9 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGPropertyInfo_h -#define SVGPropertyInfo_h +#pragma once -#if ENABLE(SVG) #include "QualifiedName.h" -#include <wtf/PassRefPtr.h> namespace WebCore { @@ -59,7 +56,7 @@ struct SVGPropertyInfo { WTF_MAKE_FAST_ALLOCATED; public: typedef void (*SynchronizeProperty)(SVGElement*); - typedef PassRefPtr<SVGAnimatedProperty> (*LookupOrCreateWrapperForAnimatedProperty)(SVGElement*); + typedef Ref<SVGAnimatedProperty> (*LookupOrCreateWrapperForAnimatedProperty)(SVGElement*); SVGPropertyInfo(AnimatedPropertyType newType, AnimatedPropertyState newState, const QualifiedName& newAttributeName, const AtomicString& newPropertyIdentifier, SynchronizeProperty newSynchronizeProperty, @@ -73,7 +70,4 @@ public: LookupOrCreateWrapperForAnimatedProperty lookupOrCreateWrapperForAnimatedProperty; }; -} - -#endif // ENABLE(SVG) -#endif // SVGPropertyInfo_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGPropertyTearOff.h b/Source/WebCore/svg/properties/SVGPropertyTearOff.h index e0f09b3a7..46f693568 100644 --- a/Source/WebCore/svg/properties/SVGPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGPropertyTearOff.h @@ -1,5 +1,6 @@ /* * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) 2016 Apple Inc. 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 @@ -17,45 +18,57 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGPropertyTearOff_h -#define SVGPropertyTearOff_h +#pragma once -#if ENABLE(SVG) +#include "ExceptionOr.h" #include "SVGAnimatedProperty.h" -#include "SVGElement.h" #include "SVGProperty.h" #include <wtf/WeakPtr.h> namespace WebCore { +class SVGElement; + class SVGPropertyTearOffBase : public SVGProperty { public: virtual void detachWrapper() = 0; }; -template<typename PropertyType> +template<typename T> class SVGPropertyTearOff : public SVGPropertyTearOffBase { public: - typedef SVGPropertyTearOff<PropertyType> Self; + using PropertyType = T; + using Self = SVGPropertyTearOff<PropertyType>; // 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) + static Ref<Self> create(SVGAnimatedProperty& animatedProperty, SVGPropertyRole role, PropertyType& value) { - ASSERT(animatedProperty); - return adoptRef(new Self(animatedProperty, role, value)); + return adoptRef(*new Self(animatedProperty, role, value)); } // Used for non-animated POD types (for example: SVGSVGElement::createSVGLength()). - static PassRefPtr<Self> create(const PropertyType& initialValue) + static Ref<Self> create(const PropertyType& initialValue) { - return adoptRef(new Self(initialValue)); + return adoptRef(*new Self(initialValue)); } - PropertyType& propertyReference() { return *m_value; } - SVGAnimatedProperty* animatedProperty() const { return m_animatedProperty; } + static Ref<Self> create(const PropertyType* initialValue) + { + return adoptRef(*new Self(initialValue)); + } - void setValue(PropertyType& value) + template<typename U> static ExceptionOr<Ref<Self>> create(ExceptionOr<U>&& initialValue) + { + if (initialValue.hasException()) + return initialValue.releaseException(); + return create(initialValue.releaseReturnValue()); + } + + virtual PropertyType& propertyReference() { return *m_value; } + SVGAnimatedProperty* animatedProperty() const { return m_animatedProperty.get(); } + + virtual void setValue(PropertyType& value) { if (m_valueIsCopy) { detachChildren(); @@ -68,16 +81,13 @@ public: void setAnimatedProperty(SVGAnimatedProperty* animatedProperty) { m_animatedProperty = animatedProperty; - - if (m_animatedProperty) - m_contextElement = m_animatedProperty->contextElement(); } SVGElement* contextElement() const { if (!m_animatedProperty || m_valueIsCopy) - return 0; - return m_contextElement.get(); + return nullptr; + return m_animatedProperty->contextElement(); } void addChild(WeakPtr<SVGPropertyTearOffBase> child) @@ -85,7 +95,7 @@ public: m_childTearOffs.append(child); } - virtual void detachWrapper() override + void detachWrapper() override { if (m_valueIsCopy) return; @@ -101,17 +111,17 @@ public: // 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; + m_animatedProperty = nullptr; } - virtual void commitChange() override + void commitChange() override { if (!m_animatedProperty || m_valueIsCopy) return; m_animatedProperty->commitChange(); } - virtual bool isReadOnly() const override + bool isReadOnly() const override { if (m_role == AnimValRole) return true; @@ -127,17 +137,17 @@ protected: , m_value(&value) , m_valueIsCopy(false) { - // Using operator & is completely fine, as SVGAnimatedProperty owns this reference, - // and we're guaranteed to live as long as SVGAnimatedProperty does. - - if (m_animatedProperty) - m_contextElement = m_animatedProperty->contextElement(); } SVGPropertyTearOff(const PropertyType& initialValue) - : m_animatedProperty(0) + : SVGPropertyTearOff(&initialValue) + { + } + + SVGPropertyTearOff(const PropertyType* initialValue) + : m_animatedProperty(nullptr) , m_role(UndefinedRole) - , m_value(new PropertyType(initialValue)) + , m_value(initialValue ? new PropertyType(*initialValue) : nullptr) , m_valueIsCopy(true) { } @@ -148,6 +158,9 @@ protected: detachChildren(); delete m_value; } + + if (m_animatedProperty) + m_animatedProperty->propertyWillBeDeleted(*this); } void detachChildren() @@ -159,8 +172,7 @@ protected: m_childTearOffs.clear(); } - RefPtr<SVGElement> m_contextElement; - SVGAnimatedProperty* m_animatedProperty; + RefPtr<SVGAnimatedProperty> m_animatedProperty; SVGPropertyRole m_role; PropertyType* m_value; Vector<WeakPtr<SVGPropertyTearOffBase>> m_childTearOffs; @@ -168,6 +180,3 @@ protected: }; } - -#endif // ENABLE(SVG) -#endif // SVGPropertyTearOff_h diff --git a/Source/WebCore/svg/properties/SVGPropertyTraits.h b/Source/WebCore/svg/properties/SVGPropertyTraits.h index 3abb5a8a1..afdad958a 100644 --- a/Source/WebCore/svg/properties/SVGPropertyTraits.h +++ b/Source/WebCore/svg/properties/SVGPropertyTraits.h @@ -18,10 +18,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGPropertyTraits_h -#define SVGPropertyTraits_h +#pragma once -#if ENABLE(SVG) #include <wtf/text/WTFString.h> namespace WebCore { @@ -59,7 +57,10 @@ struct SVGPropertyTraits<String> { static String toString(const String& type) { return type; } }; -} +template<typename EnumType> +struct SVGIDLEnumLimits { + // Specialize this function for a particular enumeration to limit the values that are exposed through the DOM. + static unsigned highestExposedEnumValue() { return SVGPropertyTraits<EnumType>::highestEnumValue(); } +}; -#endif -#endif +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h index b0a85ddc5..786874dca 100644 --- a/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGStaticListPropertyTearOff.h @@ -17,101 +17,95 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGStaticListPropertyTearOff_h -#define SVGStaticListPropertyTearOff_h +#pragma once -#if ENABLE(SVG) #include "SVGListProperty.h" namespace WebCore { -template<typename PropertyType> +template<typename PropertyType> class SVGStaticListPropertyTearOff : public SVGListProperty<PropertyType> { public: - typedef SVGListProperty<PropertyType> Base; + using Self = SVGStaticListPropertyTearOff<PropertyType>; + using Base = SVGListProperty<PropertyType>; - typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType; - typedef SVGPropertyTearOff<ListItemType> ListItemTearOff; + using ListItemType = typename SVGPropertyTraits<PropertyType>::ListItemType; + using ListItemTearOff = typename SVGPropertyTraits<PropertyType>::ListItemTearOff; using Base::m_role; using Base::m_values; - static PassRefPtr<SVGStaticListPropertyTearOff<PropertyType>> create(SVGElement& contextElement, PropertyType& values) + static Ref<Self> create(SVGElement& contextElement, PropertyType& values) { - return adoptRef(new SVGStaticListPropertyTearOff<PropertyType>(&contextElement, values)); + return adoptRef(*new Self(contextElement, values)); } - // SVGList API - void clear(ExceptionCode& ec) + ExceptionOr<void> clear() { - Base::clearValues(ec); + return Base::clearValues(); } - ListItemType initialize(const ListItemType& newItem, ExceptionCode& ec) + ExceptionOr<ListItemType> initialize(const ListItemType& newItem) { - return Base::initializeValues(newItem, ec); + return Base::initializeValues(newItem); } - ListItemType getItem(unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> getItem(unsigned index) { - return Base::getItemValues(index, ec); + return Base::getItemValues(index); } - ListItemType insertItemBefore(const ListItemType& newItem, unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> insertItemBefore(const ListItemType& newItem, unsigned index) { - return Base::insertItemBeforeValues(newItem, index, ec); + return Base::insertItemBeforeValues(newItem, index); } - ListItemType replaceItem(const ListItemType& newItem, unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> replaceItem(const ListItemType& newItem, unsigned index) { - return Base::replaceItemValues(newItem, index, ec); + return Base::replaceItemValues(newItem, index); } - ListItemType removeItem(unsigned index, ExceptionCode& ec) + ExceptionOr<ListItemType> removeItem(unsigned index) { - return Base::removeItemValues(index, ec); + return Base::removeItemValues(index); } - ListItemType appendItem(const ListItemType& newItem, ExceptionCode& ec) + ExceptionOr<ListItemType> appendItem(const ListItemType& newItem) { - return Base::appendItemValues(newItem, ec); + return Base::appendItemValues(newItem); } -private: +protected: SVGStaticListPropertyTearOff(SVGElement* contextElement, PropertyType& values) - : SVGListProperty<PropertyType>(UndefinedRole, values, 0) - , m_contextElement(contextElement) + : Base(UndefinedRole, values, nullptr) + , m_contextElement(*contextElement) { } - virtual bool isReadOnly() const + bool isReadOnly() const override { return m_role == AnimValRole; } - virtual void commitChange() + void commitChange() override { ASSERT(m_values); - m_values->commitChange(m_contextElement.get()); + m_values->commitChange(m_contextElement); } - virtual bool processIncomingListItemValue(const ListItemType&, unsigned*) + bool processIncomingListItemValue(const ListItemType&, unsigned*) override { // no-op for static lists return true; } - virtual bool processIncomingListItemWrapper(RefPtr<ListItemTearOff>&, unsigned*) + bool processIncomingListItemWrapper(Ref<ListItemTearOff>&, unsigned*) override { ASSERT_NOT_REACHED(); return true; } -private: - RefPtr<SVGElement> m_contextElement; + Ref<SVGElement> m_contextElement; }; } - -#endif // ENABLE(SVG) -#endif // SVGStaticListPropertyTearOff_h diff --git a/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h b/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h index 962c1679d..5e2ca09a0 100644 --- a/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h +++ b/Source/WebCore/svg/properties/SVGStaticPropertyTearOff.h @@ -17,11 +17,7 @@ * Boston, MA 02110-1301, USA. */ -#ifndef SVGStaticPropertyTearOff_h -#define SVGStaticPropertyTearOff_h - -#if ENABLE(SVG) -#include "SVGPropertyTearOff.h" +#pragma once namespace WebCore { @@ -30,26 +26,28 @@ namespace WebCore { // 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> { +template<typename ContextElement, typename PropertyTearOff> +class SVGStaticPropertyTearOff final : public PropertyTearOff { public: - typedef SVGStaticPropertyTearOff<ContextElement, PropertyType> Self; + using Self = SVGStaticPropertyTearOff<ContextElement, PropertyTearOff>; + using PropertyType = typename PropertyTearOff::PropertyType; + 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) + static Ref<Self> create(ContextElement& contextElement, PropertyType& value, UpdateMethod update) { - return adoptRef(new Self(&contextElement, value, update)); + return adoptRef(*new Self(contextElement, value, update)); } - virtual void commitChange() { (m_contextElement.get()->*m_update)(); } + void commitChange() final { (m_contextElement.get()->*m_update)(); } private: - SVGStaticPropertyTearOff(ContextElement* contextElement, PropertyType& value, UpdateMethod update) - : SVGPropertyTearOff<PropertyType>(0, UndefinedRole, value) + SVGStaticPropertyTearOff(ContextElement& contextElement, PropertyType& value, UpdateMethod update) + : PropertyTearOff(UndefinedRole, value) , m_update(update) - , m_contextElement(contextElement) + , m_contextElement(&contextElement) { } @@ -60,7 +58,4 @@ private: #pragma pack(pop) #endif -} - -#endif // ENABLE(SVG) -#endif // SVGStaticPropertyTearOff_h +} // namespace WebCore diff --git a/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h b/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h deleted file mode 100644 index 7fc183b59..000000000 --- a/Source/WebCore/svg/properties/SVGTransformListPropertyTearOff.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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, SVGTransformList& values, ListWrapperCache& wrappers) - { - ASSERT(animatedProperty); - return adoptRef(new SVGTransformListPropertyTearOff(animatedProperty, role, values, wrappers)); - } - - PassRefPtr<SVGPropertyTearOff<SVGTransform>> createSVGTransformFromMatrix(SVGPropertyTearOff<SVGMatrix>* matrix, ExceptionCode& ec) - { - ASSERT(m_values); - if (!matrix) { - ec = TYPE_MISMATCH_ERR; - return 0; - } - return SVGPropertyTearOff<SVGTransform>::create(m_values->createSVGTransformFromMatrix(matrix->propertyReference())); - } - - PassRefPtr<SVGPropertyTearOff<SVGTransform>> consolidate(ExceptionCode& ec) - { - ASSERT(m_values); - ASSERT(m_wrappers); - if (!canAlterList(ec)) - return 0; - - ASSERT(m_values->size() == m_wrappers->size()); - - // Spec: If the list was empty, then a value of null is returned. - if (m_values->isEmpty()) - return 0; - - detachListWrappers(0); - RefPtr<SVGPropertyTearOff<SVGTransform>> wrapper = SVGPropertyTearOff<SVGTransform>::create(m_values->consolidate()); - m_wrappers->append(wrapper); - - ASSERT(m_values->size() == m_wrappers->size()); - return wrapper.release(); - } - -private: - SVGTransformListPropertyTearOff(AnimatedListPropertyTearOff* animatedProperty, SVGPropertyRole role, SVGTransformList& values, ListWrapperCache& wrappers) - : SVGListPropertyTearOff<SVGTransformList>(animatedProperty, role, values, wrappers) - { - } -}; - -} - -#endif // ENABLE(SVG) -#endif // SVGListPropertyTearOff_h |