blob: 40b4c9083d2a1f42d7639ccff84af23961a0d528 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ListSVGInterpolation_h
#define ListSVGInterpolation_h
#include "core/animation/SVGInterpolation.h"
#include "core/svg/properties/SVGAnimatedProperty.h"
#include "core/svg/properties/SVGProperty.h"
namespace blink {
template<typename InterpolationType, typename NonInterpolableType>
class ListSVGInterpolationImpl : public SVGInterpolation {
public:
typedef typename InterpolationType::ListType ListType;
typedef typename InterpolationType::ListType::ItemPropertyType ItemPropertyType;
static PassRefPtr<ListSVGInterpolationImpl<InterpolationType, NonInterpolableType>> maybeCreate(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute)
{
ASSERT(start->type() == ListType::classType());
ASSERT(end->type() == ListType::classType());
ListType* startList = static_cast<ListType*>(start);
ListType* endList = static_cast<ListType*>(end);
if (startList->length() != endList->length())
return nullptr;
size_t length = startList->length();
for (size_t i = 0; i < length; i++) {
if (!InterpolationType::canCreateFrom(startList->at(i), endList->at(i))) {
return nullptr;
}
}
Vector<NonInterpolableType> nonInterpolableData(length);
OwnPtr<InterpolableList> startValue = InterpolableList::create(length);
OwnPtr<InterpolableList> endValue = InterpolableList::create(length);
for (size_t i = 0; i < length; i++) {
startValue->set(i, InterpolationType::toInterpolableValue(startList->at(i), attribute.get(), &nonInterpolableData.at(i)));
endValue->set(i, InterpolationType::toInterpolableValue(endList->at(i), attribute.get(), nullptr));
}
return adoptRef(new ListSVGInterpolationImpl<InterpolationType, NonInterpolableType>(startValue.release(), endValue.release(), attribute, nonInterpolableData));
}
private:
ListSVGInterpolationImpl(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute, Vector<NonInterpolableType> nonInterpolableData)
: SVGInterpolation(start, end, attribute)
{
m_nonInterpolableData.swap(nonInterpolableData);
}
static PassRefPtrWillBeRawPtr<ListType> fromInterpolableValue(const InterpolableValue& value, const Vector<NonInterpolableType>& m_nonInterpolableData, const SVGElement* element, const SVGAnimatedPropertyBase* attribute)
{
const InterpolableList& listValue = toInterpolableList(value);
RefPtrWillBeRawPtr<ListType> result = InterpolationType::createList(*attribute);
for (size_t i = 0; i < listValue.length(); i++)
result->append(InterpolationType::fromInterpolableValue(*listValue.get(i), m_nonInterpolableData.at(i), element));
return result.release();
}
virtual PassRefPtrWillBeRawPtr<SVGPropertyBase> interpolatedValue(SVGElement& element) const
{
return fromInterpolableValue(*m_cachedValue, m_nonInterpolableData, &element, attribute());
}
Vector<NonInterpolableType> m_nonInterpolableData;
};
template<typename InterpolationType>
class ListSVGInterpolationImpl<InterpolationType, void> : public SVGInterpolation {
public:
typedef typename InterpolationType::ListType ListType;
static PassRefPtr<ListSVGInterpolationImpl<InterpolationType, void>> maybeCreate(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute)
{
ASSERT(start->type() == ListType::classType());
ASSERT(end->type() == ListType::classType());
ListType* startList = static_cast<ListType*>(start);
ListType* endList = static_cast<ListType*>(end);
if (startList->length() != endList->length())
return nullptr;
return adoptRef(new ListSVGInterpolationImpl<InterpolationType, void>(toInterpolableValue(startList), toInterpolableValue(endList), attribute));
}
private:
ListSVGInterpolationImpl(PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute)
: SVGInterpolation(start, end, attribute)
{
}
static PassOwnPtr<InterpolableValue> toInterpolableValue(ListType* listValue)
{
size_t length = listValue->length();
OwnPtr<InterpolableList> result = InterpolableList::create(length);
for (size_t i = 0; i < length; i++)
result->set(i, InterpolationType::toInterpolableValue(listValue->at(i)));
return result.release();
}
static PassRefPtrWillBeRawPtr<ListType> fromInterpolableValue(const InterpolableValue& value)
{
const InterpolableList& listValue = toInterpolableList(value);
RefPtrWillBeRawPtr<ListType> result = ListType::create();
for (size_t i = 0; i < listValue.length(); i++) {
result->append(InterpolationType::fromInterpolableValue(*listValue.get(i)));
}
return result.release();
}
virtual PassRefPtrWillBeRawPtr<SVGPropertyBase> interpolatedValue(SVGElement& element) const
{
return fromInterpolableValue(*m_cachedValue);
}
};
template<typename InterpolationType>
class ListSVGInterpolation {
public:
static PassRefPtr<ListSVGInterpolationImpl<InterpolationType, typename InterpolationType::NonInterpolableType>> maybeCreate(SVGPropertyBase* start, SVGPropertyBase* end, PassRefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute)
{
return ListSVGInterpolationImpl<InterpolationType, typename InterpolationType::NonInterpolableType>::maybeCreate(start, end, attribute);
}
};
} // namespace blink
#endif // ListSVGInterpolation_h