blob: a9cad544ca70d206ea540949b59336a21762ae6a [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 PrimitiveInterpolation_h
#define PrimitiveInterpolation_h
#include "core/animation/InterpolationValue.h"
#include "platform/animation/AnimationUtilities.h"
#include "platform/heap/Handle.h"
#include "wtf/Vector.h"
#include <cmath>
namespace blink {
class StyleResolverState;
// Represents a conversion from a pair of keyframes to something compatible with interpolation.
// This is agnostic to whether the keyframes are compatible with each other or not.
class PrimitiveInterpolation {
WTF_MAKE_FAST_ALLOCATED(PrimitiveInterpolation);
WTF_MAKE_NONCOPYABLE(PrimitiveInterpolation);
public:
virtual ~PrimitiveInterpolation() { }
virtual void interpolateValue(double fraction, OwnPtr<InterpolationValue>& result) const = 0;
virtual double interpolateUnderlyingFraction(double start, double end, double fraction) const = 0;
virtual bool isFlip() const { return false; }
protected:
PrimitiveInterpolation() { }
};
// Represents a pair of keyframes that are compatible for "smooth" interpolation eg. "0px" and "100px".
class PairwisePrimitiveInterpolation : public PrimitiveInterpolation {
public:
~PairwisePrimitiveInterpolation() override { }
static PassOwnPtr<PairwisePrimitiveInterpolation> create(const InterpolationType& type, PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue)
{
return adoptPtr(new PairwisePrimitiveInterpolation(type, start, end, nonInterpolableValue));
}
PassOwnPtr<InterpolationValue> initialValue() const
{
return InterpolationValue::create(m_type, m_start->clone(), m_nonInterpolableValue);
}
private:
PairwisePrimitiveInterpolation(const InterpolationType& type, PassOwnPtr<InterpolableValue> start, PassOwnPtr<InterpolableValue> end, PassRefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue)
: m_type(type)
, m_start(start)
, m_end(end)
, m_nonInterpolableValue(nonInterpolableValue)
{ }
void interpolateValue(double fraction, OwnPtr<InterpolationValue>& result) const final
{
ASSERT(result);
ASSERT(&result->type() == &m_type);
ASSERT(result->nonInterpolableValue() == m_nonInterpolableValue.get());
m_start->interpolate(*m_end, fraction, *result->mutableComponent().interpolableValue);
}
double interpolateUnderlyingFraction(double start, double end, double fraction) const final { return blend(start, end, fraction); }
const InterpolationType& m_type;
OwnPtr<InterpolableValue> m_start;
OwnPtr<InterpolableValue> m_end;
RefPtrWillBePersistent<NonInterpolableValue> m_nonInterpolableValue;
};
// Represents a pair of incompatible keyframes that fall back to 50% flip behaviour eg. "auto" and "0px".
class FlipPrimitiveInterpolation : public PrimitiveInterpolation {
public:
~FlipPrimitiveInterpolation() override { }
static PassOwnPtr<FlipPrimitiveInterpolation> create(PassOwnPtr<InterpolationValue> start, PassOwnPtr<InterpolationValue> end)
{
return adoptPtr(new FlipPrimitiveInterpolation(start, end));
}
private:
FlipPrimitiveInterpolation(PassOwnPtr<InterpolationValue> start, PassOwnPtr<InterpolationValue> end)
: m_start(start)
, m_end(end)
, m_lastFraction(std::numeric_limits<double>::quiet_NaN())
{ }
void interpolateValue(double fraction, OwnPtr<InterpolationValue>& result) const final
{
// TODO(alancutter): Remove this optimisation once Oilpan is default.
if (!std::isnan(m_lastFraction) && (fraction < 0.5) == (m_lastFraction < 0.5))
return;
const InterpolationValue* side = ((fraction < 0.5) ? m_start : m_end).get();
result = side ? side->clone() : nullptr;
m_lastFraction = fraction;
}
double interpolateUnderlyingFraction(double start, double end, double fraction) const final { return fraction < 0.5 ? start : end; }
bool isFlip() const final { return true; }
OwnPtr<InterpolationValue> m_start;
OwnPtr<InterpolationValue> m_end;
mutable double m_lastFraction;
};
} // namespace blink
#endif // PrimitiveInterpolation_h