| Index: Source/core/animation/InvalidatableStyleInterpolation.cpp
|
| diff --git a/Source/core/animation/InvalidatableStyleInterpolation.cpp b/Source/core/animation/InvalidatableStyleInterpolation.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..eb62029591aac2ac6932c6709c8630a8497d9307
|
| --- /dev/null
|
| +++ b/Source/core/animation/InvalidatableStyleInterpolation.cpp
|
| @@ -0,0 +1,187 @@
|
| +// 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.
|
| +
|
| +#include "config.h"
|
| +#include "core/animation/InvalidatableStyleInterpolation.h"
|
| +
|
| +#include "core/animation/StringKeyframe.h"
|
| +
|
| +namespace blink {
|
| +
|
| +class PairwiseConversionCache : public InvalidatableStyleInterpolation::CachedConversion {
|
| +public:
|
| + static PassOwnPtrWillBeRawPtr<PairwiseConversionCache> create(
|
| + PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid,
|
| + const AnimationType& type,
|
| + PassOwnPtrWillBeRawPtr<InterpolableValue> startInterpolableValue,
|
| + PassOwnPtrWillBeRawPtr<InterpolableValue> endInterpolableValue,
|
| + PassRefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue)
|
| + {
|
| + return adoptPtrWillBeNoop(new PairwiseConversionCache(isInvalid, type, startInterpolableValue, endInterpolableValue, nonInterpolableValue));
|
| + }
|
| +
|
| + virtual void interpolate(double fraction, AnimationValue& result) const
|
| + {
|
| + ASSERT_UNUSED(m_type, result.type == &m_type);
|
| + ASSERT(result.nonInterpolableValue == m_nonInterpolableValue);
|
| + m_startInterpolableValue->interpolate(*m_endInterpolableValue, fraction, *result.interpolableValue);
|
| + }
|
| +
|
| + DEFINE_INLINE_VIRTUAL_TRACE()
|
| + {
|
| + CachedConversion::trace(visitor);
|
| + visitor->trace(m_startInterpolableValue);
|
| + visitor->trace(m_endInterpolableValue);
|
| + visitor->trace(m_nonInterpolableValue);
|
| + }
|
| +
|
| +private:
|
| + PairwiseConversionCache(
|
| + PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid,
|
| + const AnimationType& type,
|
| + PassOwnPtrWillBeRawPtr<InterpolableValue> startInterpolableValue,
|
| + PassOwnPtrWillBeRawPtr<InterpolableValue> endInterpolableValue,
|
| + PassRefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue)
|
| + : CachedConversion(isInvalid)
|
| + , m_type(type)
|
| + , m_startInterpolableValue(startInterpolableValue)
|
| + , m_endInterpolableValue(endInterpolableValue)
|
| + , m_nonInterpolableValue(nonInterpolableValue)
|
| + { }
|
| +
|
| + const AnimationType& m_type;
|
| + OwnPtrWillBeMember<InterpolableValue> m_startInterpolableValue;
|
| + OwnPtrWillBeMember<InterpolableValue> m_endInterpolableValue;
|
| + RefPtrWillBeMember<NonInterpolableValue> m_nonInterpolableValue;
|
| +};
|
| +
|
| +class DefaultConversionCache : public InvalidatableStyleInterpolation::CachedConversion {
|
| +public:
|
| + static PassOwnPtrWillBeRawPtr<DefaultConversionCache> create(
|
| + PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid,
|
| + AnimationValue& start,
|
| + AnimationValue& end)
|
| + {
|
| + return adoptPtrWillBeNoop(new DefaultConversionCache(isInvalid, start, end));
|
| + }
|
| +
|
| + static bool isBeforeFlip(double fraction) { return fraction < 0.5; }
|
| +
|
| + virtual void interpolate(double fraction, AnimationValue& result) const
|
| + {
|
| + if (!std::isnan(m_lastFraction) && isBeforeFlip(fraction) == isBeforeFlip(m_lastFraction))
|
| + return;
|
| + result.copy(isBeforeFlip(fraction) ? m_start : m_end);
|
| + m_lastFraction = fraction;
|
| + }
|
| +
|
| + DEFINE_INLINE_VIRTUAL_TRACE()
|
| + {
|
| + CachedConversion::trace(visitor);
|
| + visitor->trace(m_start);
|
| + visitor->trace(m_end);
|
| + }
|
| +
|
| +private:
|
| + DefaultConversionCache(
|
| + PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid,
|
| + AnimationValue& start,
|
| + AnimationValue& end)
|
| + : CachedConversion(isInvalid)
|
| + , m_lastFraction(std::numeric_limits<double>::quiet_NaN())
|
| + {
|
| + m_start.consume(start);
|
| + m_end.consume(end);
|
| + }
|
| +
|
| + AnimationValue m_start;
|
| + AnimationValue m_end;
|
| + mutable double m_lastFraction;
|
| +};
|
| +
|
| +
|
| +InvalidatableStyleInterpolation::InvalidatableStyleInterpolation(
|
| + const Vector<const AnimationType*>& applicableTypes,
|
| + PassRefPtrWillBeRawPtr<CSSPropertySpecificKeyframe> startKeyframe,
|
| + PassRefPtrWillBeRawPtr<CSSPropertySpecificKeyframe> endKeyframe)
|
| +: StyleInterpolation(nullptr, nullptr, applicableTypes.first()->property())
|
| +, m_applicableTypes(applicableTypes)
|
| +, m_startKeyframe(startKeyframe)
|
| +, m_endKeyframe(endKeyframe)
|
| +, m_cachedConversion(nullptr)
|
| +{
|
| + maybeCachePairwiseConversion(nullptr);
|
| + interpolate(0, 0);
|
| +}
|
| +
|
| +bool InvalidatableStyleInterpolation::maybeCachePairwiseConversion(const StyleResolverState* state) const
|
| +{
|
| + for (const auto& animationType : m_applicableTypes) {
|
| + RefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid;
|
| + OwnPtrWillBeRawPtr<InterpolableValue> startInterpolableValue;
|
| + OwnPtrWillBeRawPtr<InterpolableValue> endInterpolableValue;
|
| + RefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue;
|
| + if (animationType->maybeConvertPairwise(*m_startKeyframe, *m_endKeyframe, state, isInvalid, startInterpolableValue, endInterpolableValue, nonInterpolableValue)) {
|
| + m_cachedConversion = PairwiseConversionCache::create(
|
| + isInvalid.release(),
|
| + *animationType,
|
| + startInterpolableValue.release(),
|
| + endInterpolableValue.release(),
|
| + nonInterpolableValue.release());
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void InvalidatableStyleInterpolation::interpolate(int, double fraction)
|
| +{
|
| + m_currentFraction = fraction;
|
| + if (m_cachedConversion)
|
| + m_cachedConversion->interpolate(fraction, m_cachedValue);
|
| + else
|
| + m_cachedValue.clear();
|
| +}
|
| +
|
| +void InvalidatableStyleInterpolation::validateCache(const StyleResolverState& state) const
|
| +{
|
| + if (m_cachedConversion && !m_cachedConversion->isInvalid(state))
|
| + return;
|
| + m_cachedConversion = nullptr;
|
| + if (!maybeCachePairwiseConversion(&state))
|
| + cacheDefaultConversion(state);
|
| + m_cachedConversion->interpolate(m_currentFraction, m_cachedValue);
|
| +}
|
| +
|
| +void InvalidatableStyleInterpolation::cacheDefaultConversion(const StyleResolverState& state) const
|
| +{
|
| + RefPtrWillBeRawPtr<InterpolationIsInvalid> startIsInvalid;
|
| + AnimationValue startValue = convertSingleKeyframe(state, *m_startKeyframe, startIsInvalid);
|
| +
|
| + RefPtrWillBeRawPtr<InterpolationIsInvalid> endIsInvalid;
|
| + AnimationValue endValue = convertSingleKeyframe(state, *m_endKeyframe, endIsInvalid);
|
| +
|
| + InterpolationIsInvalid::chain(startIsInvalid, endIsInvalid.release());
|
| + m_cachedConversion = DefaultConversionCache::create(startIsInvalid.release(), startValue, endValue);
|
| +}
|
| +
|
| +AnimationValue InvalidatableStyleInterpolation::convertSingleKeyframe(const StyleResolverState& state, const CSSPropertySpecificKeyframe& keyframe, RefPtrWillBeRawPtr<InterpolationIsInvalid>& resultIsInvalid) const
|
| +{
|
| + for (const auto& animationType : m_applicableTypes) {
|
| + OwnPtrWillBeRawPtr<InterpolableValue> interpolableValue;
|
| + RefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue;
|
| + if (animationType->maybeConvertSingle(keyframe, &state, resultIsInvalid, interpolableValue, nonInterpolableValue))
|
| + return AnimationValue(animationType, interpolableValue.release(), nonInterpolableValue.release());
|
| + }
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +void InvalidatableStyleInterpolation::apply(StyleResolverState& state) const
|
| +{
|
| + validateCache(state);
|
| + if (m_cachedValue)
|
| + m_cachedValue.type->apply(*m_cachedValue.interpolableValue, m_cachedValue.nonInterpolableValue.get(), state);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|