blob: 8b11d40d2ec2a5fb7ac09d884ef6c821066087aa [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/TypedInterpolationValue.h"
#include "platform/animation/AnimationUtilities.h"
#include "platform/heap/Handle.h"
#include "wtf/PtrUtil.h"
#include "wtf/Vector.h"
#include <cmath>
#include <memory>
namespace blink {
class StyleResolverState;
// Represents an animation's effect between an adjacent pair of
// PropertySpecificKeyframes after converting the keyframes to an internal
// format with respect to the animation environment and underlying values.
class PrimitiveInterpolation {
USING_FAST_MALLOC(PrimitiveInterpolation);
WTF_MAKE_NONCOPYABLE(PrimitiveInterpolation);
public:
virtual ~PrimitiveInterpolation() {}
virtual void interpolateValue(
double fraction,
std::unique_ptr<TypedInterpolationValue>& 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 std::unique_ptr<PairwisePrimitiveInterpolation> create(
const InterpolationType& type,
std::unique_ptr<InterpolableValue> start,
std::unique_ptr<InterpolableValue> end,
PassRefPtr<NonInterpolableValue> nonInterpolableValue) {
return wrapUnique(new PairwisePrimitiveInterpolation(
type, std::move(start), std::move(end),
std::move(nonInterpolableValue)));
}
const InterpolationType& type() const { return m_type; }
std::unique_ptr<TypedInterpolationValue> initialValue() const {
return TypedInterpolationValue::create(m_type, m_start->clone(),
m_nonInterpolableValue);
}
private:
PairwisePrimitiveInterpolation(
const InterpolationType& type,
std::unique_ptr<InterpolableValue> start,
std::unique_ptr<InterpolableValue> end,
PassRefPtr<NonInterpolableValue> nonInterpolableValue)
: m_type(type),
m_start(std::move(start)),
m_end(std::move(end)),
m_nonInterpolableValue(nonInterpolableValue) {
DCHECK(m_start);
DCHECK(m_end);
}
void interpolateValue(
double fraction,
std::unique_ptr<TypedInterpolationValue>& result) const final {
DCHECK(result);
DCHECK_EQ(&result->type(), &m_type);
DCHECK_EQ(result->getNonInterpolableValue(), m_nonInterpolableValue.get());
m_start->interpolate(*m_end, fraction,
*result->mutableValue().interpolableValue);
}
double interpolateUnderlyingFraction(double start,
double end,
double fraction) const final {
return blend(start, end, fraction);
}
const InterpolationType& m_type;
std::unique_ptr<InterpolableValue> m_start;
std::unique_ptr<InterpolableValue> m_end;
RefPtr<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 std::unique_ptr<FlipPrimitiveInterpolation> create(
std::unique_ptr<TypedInterpolationValue> start,
std::unique_ptr<TypedInterpolationValue> end) {
return wrapUnique(
new FlipPrimitiveInterpolation(std::move(start), std::move(end)));
}
private:
FlipPrimitiveInterpolation(std::unique_ptr<TypedInterpolationValue> start,
std::unique_ptr<TypedInterpolationValue> end)
: m_start(std::move(start)),
m_end(std::move(end)),
m_lastFraction(std::numeric_limits<double>::quiet_NaN()) {}
void interpolateValue(
double fraction,
std::unique_ptr<TypedInterpolationValue>& result) const final {
if (!std::isnan(m_lastFraction) &&
(fraction < 0.5) == (m_lastFraction < 0.5))
return;
const TypedInterpolationValue* 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; }
std::unique_ptr<TypedInterpolationValue> m_start;
std::unique_ptr<TypedInterpolationValue> m_end;
mutable double m_lastFraction;
};
} // namespace blink
#endif // PrimitiveInterpolation_h