SVGAnimatedListPropertyTearOff.h [plain text]
#pragma once
#include "SVGAnimatedProperty.h"
#include "SVGListPropertyTearOff.h"
#include "SVGStaticListPropertyTearOff.h"
namespace WebCore {
template<typename PropertyType>
class SVGPropertyTearOff;
template<typename PropertyType>
class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty {
public:
using ListItemType = typename SVGPropertyTraits<PropertyType>::ListItemType;
using ListItemTearOff = typename SVGPropertyTraits<PropertyType>::ListItemTearOff;
using ListWrapperCache = Vector<WeakPtr<SVGPropertyTearOff<ListItemType>>>;
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)
{
ASSERT(contextElement);
return adoptRef(*new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, animatedPropertyType, values));
}
virtual Ref<ListPropertyTearOff> baseVal()
{
if (m_baseVal)
return *static_cast<ListPropertyTearOff*>(m_baseVal.get());
auto property = ListPropertyTearOff::create(*this, BaseValRole, m_values, m_wrappers);
m_baseVal = makeWeakPtr(property.get());
return property;
}
virtual Ref<ListPropertyTearOff> animVal()
{
if (m_animVal)
return *static_cast<ListPropertyTearOff*>(m_animVal.get());
auto property = ListPropertyTearOff::create(*this, AnimValRole, m_values, m_wrappers);
m_animVal = makeWeakPtr(property.get());
return property;
}
bool isAnimating() const override { return m_animatedProperty; }
bool isAnimatedListTearOff() const override { return true; }
int findItem(SVGProperty* property)
{
return baseVal()->findItem(static_cast<ListItemTearOff*>(property));
}
void removeItemFromList(size_t itemIndex, bool shouldSynchronizeWrappers)
{
baseVal()->removeItemFromList(itemIndex, shouldSynchronizeWrappers);
}
void detachListWrappers(unsigned newListSize)
{
ListProperty::detachListWrappersAndResize(&m_wrappers, newListSize);
}
PropertyType& currentAnimatedValue()
{
ASSERT(isAnimating());
return m_animatedProperty->values();
}
const PropertyType& currentBaseValue() const
{
return m_values;
}
void animationStarted(PropertyType* newAnimVal, bool shouldOwnValues = false)
{
ASSERT(!isAnimating());
ASSERT(newAnimVal);
ASSERT(m_values.size() == m_wrappers.size());
ASSERT(m_animatedWrappers.isEmpty());
if (!newAnimVal->isEmpty())
m_animatedWrappers.fill(0, newAnimVal->size());
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(isAnimating());
ASSERT(m_values.size() == m_wrappers.size());
ASSERT(m_animatedProperty->values().size() == m_animatedProperty->wrappers().size());
ASSERT(m_animatedProperty->wrappers().size() == m_animatedWrappers.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_animatedProperty = nullptr;
}
void synchronizeWrappersIfNeeded()
{
if (!isAnimating()) {
ASSERT_NOT_REACHED();
return;
}
m_animatedProperty->detachListWrappers(m_animatedProperty->values().size());
ASSERT(m_animatedProperty->values().size() == m_animatedProperty->wrappers().size());
ASSERT(m_animatedProperty->wrappers().size() == m_animatedWrappers.size());
}
void animValWillChange()
{
ASSERT(m_values.size() == m_wrappers.size());
synchronizeWrappersIfNeeded();
}
void animValDidChange()
{
ASSERT(m_values.size() == m_wrappers.size());
synchronizeWrappersIfNeeded();
}
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;
WeakPtr<SVGListProperty<PropertyType>> m_baseVal;
WeakPtr<SVGListProperty<PropertyType>> m_animVal;
RefPtr<ListProperty> m_animatedProperty;
};
}