Index: Source/core/animation/InvalidatableStyleInterpolation.cpp |
diff --git a/Source/core/animation/InvalidatableStyleInterpolation.cpp b/Source/core/animation/InvalidatableStyleInterpolation.cpp |
index 0631d399b199108fc9df609a5e288a8fa8ce2f54..a036febb3441751d8240c954f430abec19523580 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,43 @@ 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 (!state.parentStyle()) |
+ return; |
+ if ((m_startKeyframe.value() && m_startKeyframe.value()->isInheritedValue()) |
+ || (m_endKeyframe.value() && m_endKeyframe.value()->isInheritedValue())) { |
+ state.parentStyle()->setHasExplicitlyInheritedProperties(); |
} |
- 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 |