Index: Source/core/svg/properties/NewSVGAnimatedProperty.h |
diff --git a/Source/core/svg/properties/NewSVGAnimatedProperty.h b/Source/core/svg/properties/NewSVGAnimatedProperty.h |
index 40d6c5730e811377855a55ce8486f3caaf3df747..f0ef356552d02d2068e04acfe9e7ab3c9fa48d2f 100644 |
--- a/Source/core/svg/properties/NewSVGAnimatedProperty.h |
+++ b/Source/core/svg/properties/NewSVGAnimatedProperty.h |
@@ -33,6 +33,7 @@ G* * Redistributions in binary form must reproduce the above |
#include "bindings/v8/ExceptionStatePlaceholder.h" |
#include "bindings/v8/ScriptWrappable.h" |
+#include "core/dom/ExceptionCode.h" |
#include "core/svg/SVGParsingError.h" |
#include "core/svg/properties/NewSVGPropertyTearOff.h" |
#include "core/svg/properties/SVGPropertyInfo.h" |
@@ -51,15 +52,15 @@ public: |
virtual NewSVGPropertyBase* baseValueBase() = 0; |
virtual NewSVGPropertyBase* currentValueBase() = 0; |
- virtual void animationStarted() = 0; |
+ virtual void animationStarted(); |
virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() = 0; |
virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase>) = 0; |
- virtual void animationEnded() = 0; |
- virtual void animValWillChange() = 0; |
- virtual void animValDidChange() = 0; |
+ virtual void animationEnded(); |
+ virtual void animValWillChange(); |
+ virtual void animValDidChange(); |
virtual bool needsSynchronizeAttribute() = 0; |
- void synchronizeAttribute(); |
+ virtual void synchronizeAttribute(); |
AnimatedPropertyType type() const |
{ |
@@ -76,11 +77,29 @@ public: |
return m_attributeName; |
} |
+ bool isAnimating() const |
+ { |
+ return m_isAnimating; |
+ } |
+ |
+ bool isReadOnly() const |
+ { |
+ return m_isReadOnly; |
+ } |
+ |
+ void setReadOnly() |
+ { |
+ m_isReadOnly = true; |
+ } |
+ |
protected: |
NewSVGAnimatedPropertyBase(AnimatedPropertyType, SVGElement*, const QualifiedName& attributeName); |
+ void commitChange(); |
private: |
const AnimatedPropertyType m_type; |
+ bool m_isReadOnly; |
+ bool m_isAnimating; |
// This reference is kept alive from V8 wrapper |
SVGElement* m_contextElement; |
@@ -91,36 +110,14 @@ private: |
}; |
template <typename Property> |
-class NewSVGAnimatedProperty : public NewSVGAnimatedPropertyBase { |
+class NewSVGAnimatedPropertyCommon : public NewSVGAnimatedPropertyBase { |
public: |
- typedef typename Property::TearOffType TearOffType; |
- |
- static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue) |
- { |
- return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue)); |
- } |
- |
- ~NewSVGAnimatedProperty() |
- { |
- ASSERT(!isAnimating()); |
- } |
- |
- bool isReadOnly() const |
- { |
- return m_isReadOnly; |
- } |
- |
- void setReadOnly() |
- { |
- m_isReadOnly = true; |
- } |
- |
Property* baseValue() |
{ |
return m_baseValue.get(); |
} |
- virtual NewSVGPropertyBase* baseValueBase() |
+ virtual NewSVGPropertyBase* baseValueBase() OVERRIDE |
{ |
return baseValue(); |
} |
@@ -130,7 +127,7 @@ public: |
return m_currentValue ? m_currentValue.get() : m_baseValue.get(); |
} |
- virtual NewSVGPropertyBase* currentValueBase() |
+ virtual NewSVGPropertyBase* currentValueBase() OVERRIDE |
{ |
return currentValue(); |
} |
@@ -140,65 +137,74 @@ public: |
TrackExceptionState es; |
m_baseValue->setValueAsString(value, es); |
+ commitChange(); |
if (es.hadException()) |
parseError = ParsingAttributeFailedError; |
} |
- bool isAnimating() const |
- { |
- return m_isAnimating; |
- } |
- |
- virtual void animationStarted() |
- { |
- ASSERT(!isAnimating()); |
- m_isAnimating = true; |
- } |
- |
- virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() |
+ virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() OVERRIDE |
{ |
return m_baseValue->clone(); |
} |
- virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> value) |
+ virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> passValue) OVERRIDE |
{ |
ASSERT(isAnimating()); |
- // FIXME: add type check |
- m_currentValue = static_pointer_cast<Property>(value); |
- |
- if (m_animValTearOff) |
- m_animValTearOff->setTarget(m_currentValue); |
+ RefPtr<NewSVGPropertyBase> value = passValue; |
+ ASSERT(value->type() == Property::classType()); |
+ m_currentValue = static_pointer_cast<Property>(value.release()); |
} |
- virtual void animationEnded() |
+ virtual void animationEnded() OVERRIDE |
{ |
- ASSERT(isAnimating()); |
- m_isAnimating = false; |
+ NewSVGAnimatedPropertyBase::animationEnded(); |
ASSERT(m_currentValue); |
m_currentValue.clear(); |
+ } |
- if (m_animValTearOff) |
- m_animValTearOff->setTarget(m_baseValue); |
+protected: |
+ NewSVGAnimatedPropertyCommon(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue) |
+ : NewSVGAnimatedPropertyBase(Property::classType(), contextElement, attributeName) |
+ , m_baseValue(initialValue) |
+ { |
} |
- virtual void animValWillChange() |
+private: |
+ RefPtr<Property> m_baseValue; |
+ RefPtr<Property> m_currentValue; |
+}; |
+ |
+// Implementation of SVGAnimatedProperty which has tear-off value types. |
+// This is for classes which return special type for its "animVal". |
+// Examples are SVGAnimatedLength, SVGAnimatedRect, SVGAnimated*List, etc. |
+template <typename Property, typename TearOffType = typename Property::TearOffType> |
+class NewSVGAnimatedProperty : public NewSVGAnimatedPropertyCommon<Property> { |
+public: |
+ static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue) |
{ |
- ASSERT(isAnimating()); |
+ return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue)); |
} |
- virtual void animValDidChange() |
+ virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> value) OVERRIDE |
{ |
- ASSERT(isAnimating()); |
+ NewSVGAnimatedPropertyCommon<Property>::setAnimatedValue(value); |
+ updateAnimValTearOffIfNeeded(); |
+ } |
+ |
+ virtual void animationEnded() OVERRIDE |
+ { |
+ NewSVGAnimatedPropertyCommon<Property>::animationEnded(); |
+ updateAnimValTearOffIfNeeded(); |
} |
- virtual bool needsSynchronizeAttribute() |
+ virtual bool needsSynchronizeAttribute() OVERRIDE |
{ |
// DOM attribute synchronization is only needed if tear-off is being touched from javascript or the property is being animated. |
// This prevents unnecessary attribute creation on target element. |
- return m_baseValTearOff || isAnimating(); |
+ return m_baseValTearOff || this->isAnimating(); |
} |
// SVGAnimated* DOM Spec implementations: |
@@ -208,7 +214,7 @@ public: |
virtual TearOffType* baseVal() |
{ |
if (!m_baseValTearOff) |
- m_baseValTearOff = TearOffType::create(m_baseValue, contextElement(), PropertyIsNotAnimVal, attributeName()); |
+ m_baseValTearOff = TearOffType::create(this->baseValue(), this->contextElement(), PropertyIsNotAnimVal, this->attributeName()); |
return m_baseValTearOff.get(); |
} |
@@ -216,35 +222,100 @@ public: |
TearOffType* animVal() |
{ |
if (!m_animValTearOff) |
- m_animValTearOff = TearOffType::create(currentValue(), contextElement(), PropertyIsAnimVal, attributeName()); |
+ m_animValTearOff = TearOffType::create(this->currentValue(), this->contextElement(), PropertyIsAnimVal, this->attributeName()); |
return m_animValTearOff.get(); |
} |
protected: |
NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue) |
- : NewSVGAnimatedPropertyBase(Property::classType(), contextElement, attributeName) |
- , m_isReadOnly(false) |
- , m_isAnimating(false) |
- , m_baseValue(initialValue) |
+ : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName, initialValue) |
{ |
} |
private: |
- bool m_isReadOnly; |
- bool m_isAnimating; |
+ void updateAnimValTearOffIfNeeded() |
+ { |
+ if (m_animValTearOff) |
+ m_animValTearOff->setTarget(this->currentValue()); |
+ } |
// When still (not animated): |
// Both m_animValTearOff and m_baseValTearOff target m_baseValue. |
// When animated: |
// m_animValTearOff targets m_currentValue. |
// m_baseValTearOff targets m_baseValue. |
- RefPtr<Property> m_baseValue; |
- RefPtr<Property> m_currentValue; |
RefPtr<TearOffType> m_baseValTearOff; |
RefPtr<TearOffType> m_animValTearOff; |
}; |
+// Implementation of SVGAnimatedProperty which uses primitive types. |
+// This is for classes which return primitive type for its "animVal". |
+// Examples are SVGAnimatedBoolean, SVGAnimatedNumber, etc. |
+// This is implemented as template specialization used when TearOffType is set to void. |
+template <typename Property> |
+class NewSVGAnimatedProperty<Property, void> : public NewSVGAnimatedPropertyCommon<Property> { |
+public: |
+ typedef typename Property::PrimitiveType PrimitiveType; |
+ |
+ static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue) |
+ { |
+ return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue)); |
+ } |
+ |
+ virtual bool needsSynchronizeAttribute() OVERRIDE |
+ { |
+ // DOM attribute synchronization is only needed if tear-off is being touched from javascript or the property is being animated. |
+ // This prevents unnecessary attribute creation on target element. |
+ return m_baseValueUpdated || this->isAnimating(); |
+ } |
+ |
+ virtual void synchronizeAttribute() OVERRIDE |
+ { |
+ NewSVGAnimatedPropertyBase::synchronizeAttribute(); |
+ m_baseValueUpdated = false; |
+ } |
+ |
+ // SVGAnimated* DOM Spec implementations: |
+ |
+ // baseVal()/setBaseVal()/animVal() are only to be used from SVG DOM implementation. |
+ // Use currentValue() from C++ code. |
+ PrimitiveType baseVal() |
+ { |
+ return this->baseValue()->value(); |
+ } |
+ |
+ void setBaseVal(PrimitiveType value, WebCore::ExceptionState& exceptionState) |
+ { |
+ if (this->isReadOnly()) { |
+ exceptionState.throwDOMException(NoModificationAllowedError, "The attribute is read-only."); |
+ return; |
+ } |
+ |
+ this->baseValue()->setValue(value); |
+ |
+ ASSERT(this->attributeName() != nullQName()); |
+ this->contextElement()->invalidateSVGAttributes(); |
+ this->contextElement()->svgAttributeChanged(this->attributeName()); |
+ |
+ m_baseValueUpdated = true; |
+ } |
+ |
+ PrimitiveType animVal() |
+ { |
+ return this->currentValue()->value(); |
+ } |
+ |
+protected: |
+ NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue) |
+ : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName, initialValue) |
+ , m_baseValueUpdated(false) |
+ { |
+ } |
+ |
+ bool m_baseValueUpdated; |
+}; |
+ |
} |
#endif // NewSVGAnimatedProperty_h |