blob: fdb7d29a398a7d183a1bc040d5601c55c1baef40 [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 <cmath>
#include <memory>
#include "base/macros.h"
#include "core/animation/TypedInterpolationValue.h"
#include "platform/animation/AnimationUtilities.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/PtrUtil.h"
namespace blink {
// 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);
public:
virtual ~PrimitiveInterpolation() = default;
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() = default;
DISALLOW_COPY_AND_ASSIGN(PrimitiveInterpolation);
};
// Represents a pair of keyframes that are compatible for "smooth" interpolation
// eg. "0px" and "100px".
class PairwisePrimitiveInterpolation : public PrimitiveInterpolation {
public:
~PairwisePrimitiveInterpolation() override = default;
static std::unique_ptr<PairwisePrimitiveInterpolation> Create(
const InterpolationType& type,
std::unique_ptr<InterpolableValue> start,
std::unique_ptr<InterpolableValue> end,
scoped_refptr<NonInterpolableValue> non_interpolable_value) {
return WTF::WrapUnique(new PairwisePrimitiveInterpolation(
type, std::move(start), std::move(end),
std::move(non_interpolable_value)));
}
const InterpolationType& GetType() const { return type_; }
std::unique_ptr<TypedInterpolationValue> InitialValue() const {
return TypedInterpolationValue::Create(type_, start_->Clone(),
non_interpolable_value_);
}
private:
PairwisePrimitiveInterpolation(
const InterpolationType& type,
std::unique_ptr<InterpolableValue> start,
std::unique_ptr<InterpolableValue> end,
scoped_refptr<NonInterpolableValue> non_interpolable_value)
: type_(type),
start_(std::move(start)),
end_(std::move(end)),
non_interpolable_value_(std::move(non_interpolable_value)) {
DCHECK(start_);
DCHECK(end_);
}
void InterpolateValue(
double fraction,
std::unique_ptr<TypedInterpolationValue>& result) const final {
DCHECK(result);
DCHECK_EQ(&result->GetType(), &type_);
DCHECK_EQ(result->GetNonInterpolableValue(), non_interpolable_value_.get());
start_->Interpolate(*end_, fraction,
*result->MutableValue().interpolable_value);
}
double InterpolateUnderlyingFraction(double start,
double end,
double fraction) const final {
return Blend(start, end, fraction);
}
const InterpolationType& type_;
std::unique_ptr<InterpolableValue> start_;
std::unique_ptr<InterpolableValue> end_;
scoped_refptr<NonInterpolableValue> non_interpolable_value_;
};
// Represents a pair of incompatible keyframes that fall back to 50% flip
// behaviour eg. "auto" and "0px".
class FlipPrimitiveInterpolation : public PrimitiveInterpolation {
public:
~FlipPrimitiveInterpolation() override = default;
static std::unique_ptr<FlipPrimitiveInterpolation> Create(
std::unique_ptr<TypedInterpolationValue> start,
std::unique_ptr<TypedInterpolationValue> end) {
return WTF::WrapUnique(
new FlipPrimitiveInterpolation(std::move(start), std::move(end)));
}
private:
FlipPrimitiveInterpolation(std::unique_ptr<TypedInterpolationValue> start,
std::unique_ptr<TypedInterpolationValue> end)
: start_(std::move(start)),
end_(std::move(end)),
last_fraction_(std::numeric_limits<double>::quiet_NaN()) {}
void InterpolateValue(
double fraction,
std::unique_ptr<TypedInterpolationValue>& result) const final {
if (!std::isnan(last_fraction_) &&
(fraction < 0.5) == (last_fraction_ < 0.5))
return;
const TypedInterpolationValue* side =
((fraction < 0.5) ? start_ : end_).get();
result = side ? side->Clone() : nullptr;
last_fraction_ = 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> start_;
std::unique_ptr<TypedInterpolationValue> end_;
mutable double last_fraction_;
};
} // namespace blink
#endif // PrimitiveInterpolation_h