SVGAnimatedDecoratedProperty.h [plain text]
#pragma once
#include "SVGAnimatedProperty.h"
#include "SVGDecoratedProperty.h"
namespace WebCore {
template<template <typename, typename> class DecoratedProperty, typename DecorationType>
class SVGAnimatedDecoratedProperty : public SVGAnimatedProperty {
public:
template<typename PropertyType, typename AnimatedProperty = SVGAnimatedDecoratedProperty>
static Ref<AnimatedProperty> create(SVGElement* contextElement)
{
return adoptRef(*new AnimatedProperty(contextElement, adoptRef(*new DecoratedProperty<DecorationType, PropertyType>())));
}
template<typename PropertyType, typename AnimatedProperty = SVGAnimatedDecoratedProperty>
static Ref<AnimatedProperty> create(SVGElement* contextElement, const PropertyType& value)
{
return adoptRef(*new AnimatedProperty(contextElement, DecoratedProperty<DecorationType, PropertyType>::create(value)));
}
SVGAnimatedDecoratedProperty(SVGElement* contextElement, Ref<SVGDecoratedProperty<DecorationType>>&& baseVal)
: SVGAnimatedProperty(contextElement)
, m_baseVal(WTFMove(baseVal))
{
}
ExceptionOr<void> setBaseVal(const DecorationType& baseVal)
{
if (!m_baseVal->setValue(baseVal))
return Exception { TypeError };
commitPropertyChange(nullptr);
return { };
}
template<typename PropertyType>
void setBaseValInternal(const PropertyType& baseVal)
{
m_baseVal->setValueInternal(static_cast<DecorationType>(baseVal));
if (m_animVal)
m_animVal->setValueInternal(static_cast<DecorationType>(baseVal));
}
DecorationType baseVal() const { return m_baseVal->value(); }
template<typename PropertyType>
void setAnimVal(const PropertyType& animVal)
{
ASSERT(isAnimating() && m_animVal);
m_animVal->setValueInternal(static_cast<DecorationType>(animVal));
}
template<typename PropertyType = DecorationType>
PropertyType animVal() const
{
ASSERT_IMPLIES(isAnimating(), m_animVal);
return static_cast<PropertyType>((isAnimating() ? *m_animVal : m_baseVal.get()).value());
}
String baseValAsString() const override { return m_baseVal->valueAsString(); }
String animValAsString() const override
{
ASSERT(isAnimating() && !!m_animVal);
return m_animVal->valueAsString();
}
void setDirty() override { m_state = SVGPropertyState::Dirty; }
bool isDirty() const override { return m_state == SVGPropertyState::Dirty; }
Optional<String> synchronize() override
{
if (m_state == SVGPropertyState::Clean)
return WTF::nullopt;
m_state = SVGPropertyState::Clean;
return baseValAsString();
}
template<typename PropertyType>
PropertyType currentValue() const
{
ASSERT_IMPLIES(isAnimating(), m_animVal);
return static_cast<PropertyType>((isAnimating() ? *m_animVal : m_baseVal.get()).valueInternal());
}
void startAnimation(SVGAttributeAnimator& animator) override
{
if (m_animVal)
m_animVal->setValue(m_baseVal->value());
else
m_animVal = m_baseVal->clone();
SVGAnimatedProperty::startAnimation(animator);
}
void stopAnimation(SVGAttributeAnimator& animator) override
{
SVGAnimatedProperty::stopAnimation(animator);
if (!isAnimating())
m_animVal = nullptr;
else if (m_animVal)
m_animVal->setValue(m_baseVal->value());
}
void instanceStartAnimation(SVGAttributeAnimator& animator, SVGAnimatedProperty& animated) override
{
if (isAnimating())
return;
m_animVal = static_cast<decltype(*this)>(animated).m_animVal;
SVGAnimatedProperty::instanceStartAnimation(animator, animated);
}
void instanceStopAnimation(SVGAttributeAnimator& animator) override
{
if (!isAnimating())
return;
m_animVal = nullptr;
SVGAnimatedProperty::instanceStopAnimation(animator);
}
protected:
Ref<SVGDecoratedProperty<DecorationType>> m_baseVal;
RefPtr<SVGDecoratedProperty<DecorationType>> m_animVal;
SVGPropertyState m_state { SVGPropertyState::Clean };
};
}