Chromium Code Reviews| Index: Source/core/animation/InvalidatableStyleInterpolation.cpp |
| diff --git a/Source/core/animation/InvalidatableStyleInterpolation.cpp b/Source/core/animation/InvalidatableStyleInterpolation.cpp |
| index 0631d399b199108fc9df609a5e288a8fa8ce2f54..c2ab166dda6ea5c25d0d09d7f2c797111c7e7c57 100644 |
| --- a/Source/core/animation/InvalidatableStyleInterpolation.cpp |
| +++ b/Source/core/animation/InvalidatableStyleInterpolation.cpp |
| @@ -6,6 +6,7 @@ |
| #include "core/animation/InvalidatableStyleInterpolation.h" |
| #include "core/animation/StringKeyframe.h" |
| +#include "core/css/resolver/StyleResolverState.h" |
| namespace blink { |
| @@ -18,13 +19,15 @@ InvalidatableStyleInterpolation::InvalidatableStyleInterpolation( |
| , m_startKeyframe(startKeyframe) |
| , m_endKeyframe(endKeyframe) |
| { |
| - maybeCachePairwiseConversion(nullptr); |
| + maybeCachePairwiseConversion(nullptr, nullptr); |
| interpolate(0, 0); |
| } |
| -bool InvalidatableStyleInterpolation::maybeCachePairwiseConversion(const StyleResolverState* state) const |
| +bool InvalidatableStyleInterpolation::maybeCachePairwiseConversion(const StyleResolverState* state, const InterpolationValue* underlyingValue) const |
| { |
| for (const auto& interpolationType : m_interpolationTypes) { |
| + if ((m_startKeyframe.isNeutral() || m_endKeyframe.isNeutral()) && (!underlyingValue || underlyingValue->type() != *interpolationType)) |
| + continue; |
| OwnPtrWillBeRawPtr<PairwisePrimitiveInterpolation> pairwiseConversion = interpolationType->maybeConvertPairwise(m_startKeyframe, m_endKeyframe, state, m_conversionCheckers); |
| if (pairwiseConversion) { |
| m_cachedValue = pairwiseConversion->initialValue(); |
| @@ -39,23 +42,54 @@ void InvalidatableStyleInterpolation::interpolate(int, double fraction) |
| { |
| m_currentFraction = fraction; |
| if (m_cachedConversion) |
| - m_cachedConversion->interpolate(fraction, m_cachedValue); |
| + m_cachedConversion->interpolateValue(fraction, m_cachedValue); |
| // We defer the interpolation to ensureValidInterpolation() if m_cachedConversion is null. |
| } |
| -PassOwnPtrWillBeRawPtr<InterpolationValue> InvalidatableStyleInterpolation::convertSingleKeyframe(const CSSPropertySpecificKeyframe& keyframe, const StyleResolverState& state) const |
| +PassOwnPtrWillBeRawPtr<InterpolationValue> InvalidatableStyleInterpolation::convertSingleKeyframe(const CSSPropertySpecificKeyframe& keyframe, const StyleResolverState& state, const InterpolationValue* underlyingValue) const |
| { |
| + if (keyframe.isNeutral() && !underlyingValue) |
| + return nullptr; |
| for (const auto& interpolationType : m_interpolationTypes) { |
| + if (keyframe.isNeutral() && underlyingValue->type() != *interpolationType) |
| + continue; |
| OwnPtrWillBeRawPtr<InterpolationValue> result = interpolationType->maybeConvertSingle(keyframe, &state, m_conversionCheckers); |
| if (result) |
| return result.release(); |
| } |
| - ASSERT_NOT_REACHED(); |
| + ASSERT(keyframe.isNeutral()); |
| return nullptr; |
| } |
| -bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& state) const |
| +PassOwnPtrWillBeRawPtr<InterpolationValue> InvalidatableStyleInterpolation::maybeConvertUnderlyingValue(const StyleResolverState& state) const |
| { |
| + for (const auto& interpolationType : m_interpolationTypes) { |
| + OwnPtrWillBeRawPtr<InterpolationValue> result = interpolationType->maybeConvertUnderlyingValue(state); |
| + if (result) |
| + return result.release(); |
| + } |
| + return nullptr; |
| +} |
| + |
| +bool InvalidatableStyleInterpolation::dependsOnUnderlyingValue() const |
| +{ |
| + return (m_startKeyframe.underlyingFraction() != 0 && m_currentFraction != 1) || (m_endKeyframe.underlyingFraction() != 0 && m_currentFraction != 0); |
| +} |
| + |
| +bool InvalidatableStyleInterpolation::isNeutralKeyframeActive() const |
| +{ |
| + return (m_startKeyframe.isNeutral() && m_currentFraction != 1) || (m_endKeyframe.isNeutral() && m_currentFraction != 0); |
| +} |
| + |
| +bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& state, const InterpolationValue* underlyingValue) const |
| +{ |
| + if (isNeutralKeyframeActive()) { |
| + if (m_cachedConversion->isFlip()) |
| + return false; |
| + // Pairwise interpolation can never happen between different InterpolationTypes, neutral values always represent the underlying value. |
| + if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != underlyingValue->type()) |
| + return false; |
| + } |
| for (const auto& checker : m_conversionCheckers) { |
| if (!checker->isValid(state)) |
| return false; |
| @@ -63,23 +97,41 @@ bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& sta |
| return true; |
| } |
| -void InvalidatableStyleInterpolation::ensureValidInterpolation(const StyleResolverState& state) const |
| +void InvalidatableStyleInterpolation::ensureValidInterpolation(const StyleResolverState& state, const InterpolationValue* underlyingValue) const |
| { |
| - if (m_cachedConversion && isCacheValid(state)) |
| + if (m_cachedConversion && isCacheValid(state, underlyingValue)) |
| return; |
| m_conversionCheckers.clear(); |
| - if (!maybeCachePairwiseConversion(&state)) { |
| + if (!maybeCachePairwiseConversion(&state, underlyingValue)) { |
| m_cachedConversion = FlipPrimitiveInterpolation::create( |
| - convertSingleKeyframe(m_startKeyframe, state), |
| - convertSingleKeyframe(m_endKeyframe, state)); |
| + convertSingleKeyframe(m_startKeyframe, state, underlyingValue), |
| + convertSingleKeyframe(m_endKeyframe, state, underlyingValue)); |
| + } |
| + m_cachedConversion->interpolateValue(m_currentFraction, m_cachedValue); |
| +} |
| + |
| +void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& state) const |
| +{ |
| + if ((m_startKeyframe.value() && m_startKeyframe.value()->isInheritedValue()) |
| + || (m_endKeyframe.value() && m_endKeyframe.value()->isInheritedValue())) { |
| + state.parentStyle()->setHasExplicitlyInheritedProperties(); |
|
dstockwell
2015/07/02 23:57:46
Are you sure that parentStyle is never null here?
alancutter (OOO until 2018)
2015/07/03 01:38:22
Nope, added check.
|
| } |
| - m_cachedConversion->interpolate(m_currentFraction, m_cachedValue); |
| } |
| void InvalidatableStyleInterpolation::apply(StyleResolverState& state) const |
| { |
| - ensureValidInterpolation(state); |
| - m_cachedValue->type().apply(m_cachedValue->interpolableValue(), m_cachedValue->nonInterpolableValue(), state); |
| + OwnPtrWillBeRawPtr<InterpolationValue> underlyingValue = dependsOnUnderlyingValue() ? maybeConvertUnderlyingValue(state) : nullptr; |
| + ensureValidInterpolation(state, underlyingValue.get()); |
| + if (!m_cachedValue) |
| + return; |
| + const InterpolableValue* appliedInterpolableValue = &m_cachedValue->interpolableValue(); |
| + if (underlyingValue && m_cachedValue->type() == underlyingValue->type()) { |
| + double underlyingFraction = m_cachedConversion->interpolateUnderlyingFraction(m_startKeyframe.underlyingFraction(), m_endKeyframe.underlyingFraction(), m_currentFraction); |
| + underlyingValue->interpolableValue().scaleAndAdd(underlyingFraction, m_cachedValue->interpolableValue()); |
| + appliedInterpolableValue = &underlyingValue->interpolableValue(); |
| + } |
| + m_cachedValue->type().apply(*appliedInterpolableValue, m_cachedValue->nonInterpolableValue(), state); |
| + setFlagIfInheritUsed(state); |
| } |
| } // namespace blink |