SVGAnimatedListPropertyTearOff.h [plain text]
#ifndef SVGAnimatedListPropertyTearOff_h
#define SVGAnimatedListPropertyTearOff_h
#include "SVGAnimatedProperty.h"
#include "SVGListPropertyTearOff.h"
#include "SVGStaticListPropertyTearOff.h"
namespace WebCore {
template<typename PropertyType>
class SVGPropertyTearOff;
template<typename PropertyType>
class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty {
public:
typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
typedef Vector<RefPtr<ListItemTearOff>> ListWrapperCache;
typedef SVGListProperty<PropertyType> ListProperty;
typedef SVGListPropertyTearOff<PropertyType> ListPropertyTearOff;
typedef PropertyType ContentType;
virtual ListProperty* baseVal()
{
if (!m_baseVal)
m_baseVal = ListPropertyTearOff::create(this, BaseValRole, m_values, m_wrappers);
return static_cast<ListProperty*>(m_baseVal.get());
}
virtual ListProperty* animVal()
{
if (!m_animVal)
m_animVal = ListPropertyTearOff::create(this, AnimValRole, m_values, m_wrappers);
return static_cast<ListProperty*>(m_animVal.get());
}
virtual bool isAnimatedListTearOff() const override { return true; }
int findItem(SVGProperty* property) const
{
typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff;
return static_cast<ListPropertyTearOff*>(m_baseVal.get())->findItem(static_cast<ListItemTearOff*>(property));
}
void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers)
{
static_cast<ListPropertyTearOff*>(m_baseVal.get())->removeItemFromList(itemIndex, shouldSynchronizeWrappers);
}
void detachListWrappers(unsigned newListSize)
{
ListProperty::detachListWrappersAndResize(&m_wrappers, newListSize);
}
PropertyType& currentAnimatedValue()
{
ASSERT(m_isAnimating);
ASSERT(m_animVal);
return static_cast<ListProperty*>(m_animVal.get())->values();
}
const PropertyType& currentBaseValue() const
{
return m_values;
}
void animationStarted(PropertyType* newAnimVal, bool shouldOwnValues = false)
{
ASSERT(!m_isAnimating);
ASSERT(newAnimVal);
ASSERT(m_values.size() == m_wrappers.size());
ASSERT(m_animatedWrappers.isEmpty());
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;
}
void animationEnded()
{
ASSERT(m_isAnimating);
ASSERT(m_animVal);
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());
animVal->setValuesAndWrappers(&m_values, &m_wrappers, false);
ASSERT(animVal->values().size() == animVal->wrappers().size());
ASSERT(animVal->wrappers().size() == m_wrappers.size());
m_animatedWrappers.clear();
m_isAnimating = false;
}
void synchronizeWrappersIfNeeded()
{
ListProperty* animVal = static_cast<ListProperty*>(m_animVal.get());
animVal->detachListWrappers(animVal->values().size());
ASSERT(animVal->values().size() == animVal->wrappers().size());
ASSERT(animVal->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)
, m_values(values)
{
if (!values.isEmpty())
m_wrappers.fill(0, values.size());
}
PropertyType& m_values;
ListWrapperCache m_wrappers;
ListWrapperCache m_animatedWrappers;
RefPtr<SVGProperty> m_baseVal;
RefPtr<SVGProperty> m_animVal;
};
}
#endif // SVGAnimatedListPropertyTearOff_h