blob: f5f65bfd9066adf8ac1dcddb0e7a5adad8b1e6dd [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 InterpolationType_h
#define InterpolationType_h
#include "core/animation/InterpolationValue.h"
#include "core/animation/Keyframe.h"
#include "core/animation/PairwiseInterpolationValue.h"
#include "core/animation/PrimitiveInterpolation.h"
#include "core/animation/PropertyHandle.h"
#include "core/animation/UnderlyingValueOwner.h"
#include "platform/heap/Handle.h"
#include "wtf/Allocator.h"
#include <memory>
namespace blink {
class InterpolationEnvironment;
// Subclasses of InterpolationType implement the logic for a specific value type of a specific PropertyHandle to:
// - Convert PropertySpecificKeyframe values to (Pairwise)?InterpolationValues: maybeConvertPairwise() and maybeConvertSingle()
// - Convert the target Element's property value to an InterpolationValue: maybeConvertUnderlyingValue()
// - Apply an InterpolationValue to a target Element's property: apply().
class InterpolationType {
USING_FAST_MALLOC(InterpolationType);
WTF_MAKE_NONCOPYABLE(InterpolationType);
public:
virtual ~InterpolationType() { NOTREACHED(); }
PropertyHandle getProperty() const { return m_property; }
// ConversionCheckers are returned from calls to maybeConvertPairwise() and maybeConvertSingle() to enable the caller to check
// whether the result is still valid given changes in the InterpolationEnvironment and underlying InterpolationValue.
class ConversionChecker {
USING_FAST_MALLOC(ConversionChecker);
WTF_MAKE_NONCOPYABLE(ConversionChecker);
public:
virtual ~ConversionChecker() { }
void setType(const InterpolationType& type) { m_type = &type; }
const InterpolationType& type() const { return *m_type; }
virtual bool isValid(const InterpolationEnvironment&, const InterpolationValue& underlying) const = 0;
protected:
ConversionChecker()
: m_type(nullptr)
{ }
const InterpolationType* m_type;
};
using ConversionCheckers = Vector<std::unique_ptr<ConversionChecker>>;
virtual PairwiseInterpolationValue maybeConvertPairwise(const PropertySpecificKeyframe& startKeyframe, const PropertySpecificKeyframe& endKeyframe, const InterpolationEnvironment& environment, const InterpolationValue& underlying, ConversionCheckers& conversionCheckers) const
{
InterpolationValue start = maybeConvertSingle(startKeyframe, environment, underlying, conversionCheckers);
if (!start)
return nullptr;
InterpolationValue end = maybeConvertSingle(endKeyframe, environment, underlying, conversionCheckers);
if (!end)
return nullptr;
return maybeMergeSingles(std::move(start), std::move(end));
}
virtual InterpolationValue maybeConvertSingle(const PropertySpecificKeyframe&, const InterpolationEnvironment&, const InterpolationValue& underlying, ConversionCheckers&) const = 0;
virtual InterpolationValue maybeConvertUnderlyingValue(const InterpolationEnvironment&) const = 0;
virtual void composite(UnderlyingValueOwner& underlyingValueOwner, double underlyingFraction, const InterpolationValue& value, double interpolationFraction) const
{
ASSERT(!underlyingValueOwner.value().nonInterpolableValue);
ASSERT(!value.nonInterpolableValue);
underlyingValueOwner.mutableValue().interpolableValue->scaleAndAdd(underlyingFraction, *value.interpolableValue);
}
virtual void apply(const InterpolableValue&, const NonInterpolableValue*, InterpolationEnvironment&) const = 0;
// Implement reference equality checking via pointer equality checking as these are singletons.
bool operator==(const InterpolationType& other) const { return this == &other; }
bool operator!=(const InterpolationType& other) const { return this != &other; }
protected:
InterpolationType(PropertyHandle property)
: m_property(property)
{ }
virtual PairwiseInterpolationValue maybeMergeSingles(InterpolationValue&& start, InterpolationValue&& end) const
{
ASSERT(!start.nonInterpolableValue);
ASSERT(!end.nonInterpolableValue);
return PairwiseInterpolationValue(
std::move(start.interpolableValue),
std::move(end.interpolableValue),
nullptr);
}
const PropertyHandle m_property;
};
} // namespace blink
#endif // InterpolationType_h