Index: Source/core/animation/InvalidatableStyleInterpolation.cpp |
diff --git a/Source/core/animation/InvalidatableStyleInterpolation.cpp b/Source/core/animation/InvalidatableStyleInterpolation.cpp |
index d0f20a686b362d16feadb1ca1e5c59b8d394b7e9..b6856731a3f5701b45becb9f59dfe2f1e96980dc 100644 |
--- a/Source/core/animation/InvalidatableStyleInterpolation.cpp |
+++ b/Source/core/animation/InvalidatableStyleInterpolation.cpp |
@@ -120,20 +120,64 @@ void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s |
} |
} |
-void InvalidatableStyleInterpolation::apply(StyleResolverState& state) const |
+void InvalidatableStyleInterpolation::applyStack(const ActiveInterpolations& interpolations, StyleResolverState& state) |
{ |
- OwnPtr<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(); |
+ ASSERT(interpolations.size() > 0); |
+ size_t startingIndex = 0; |
+ |
+ // Compute the underlying value to composite onto. |
+ OwnPtr<InterpolationValue> underlyingValueOwner = nullptr; |
dstockwell
2015/09/07 03:11:37
Let's see if we can encapsulate this ownptr/rawptr
alancutter (OOO until 2018)
2015/09/07 03:36:46
Done.
|
+ InterpolationValue* underlyingValue = nullptr; |
+ const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableStyleInterpolation(*interpolations.at(startingIndex)); |
+ if (firstInterpolation.dependsOnUnderlyingValue()) { |
+ underlyingValueOwner = firstInterpolation.maybeConvertUnderlyingValue(state); |
+ underlyingValue = underlyingValueOwner.get(); |
+ } else { |
+ firstInterpolation.ensureValidInterpolation(state, nullptr); |
dstockwell
2015/09/07 03:11:37
Should ensureValidInterpolation just return the m_
alancutter (OOO until 2018)
2015/09/07 03:36:46
Good idea, done.
|
+ // Fast path for replace interpolations that are the last to apply. |
+ if (interpolations.size() == 1) { |
+ const InterpolationValue* firstValue = firstInterpolation.m_cachedValue.get(); |
+ if (firstValue) { |
+ firstInterpolation.setFlagIfInheritUsed(state); |
+ firstValue->type().apply(firstValue->interpolableValue(), firstValue->nonInterpolableValue(), state); |
+ } |
+ return; |
+ } |
+ underlyingValue = firstInterpolation.m_cachedValue.get(); |
+ startingIndex++; |
+ } |
+ |
+ // Composite interpolations onto the underlying value. |
+ bool shouldApply = false; |
+ for (size_t i = startingIndex; i < interpolations.size(); i++) { |
+ const InvalidatableStyleInterpolation& currentInterpolation = toInvalidatableStyleInterpolation(*interpolations.at(i)); |
+ ASSERT(currentInterpolation.dependsOnUnderlyingValue()); |
+ currentInterpolation.ensureValidInterpolation(state, underlyingValue); |
+ const InterpolationValue* currentValue = currentInterpolation.m_cachedValue.get(); |
+ if (!currentValue) |
+ continue; |
+ shouldApply = true; |
+ currentInterpolation.setFlagIfInheritUsed(state); |
+ if (!underlyingValue || underlyingValue->type() != currentValue->type()) { |
+ // We keep track of the current value as the new underlying value but do not mutate it, instead perform copy on write. |
+ underlyingValue = const_cast<InterpolationValue*>(currentValue); |
+ underlyingValueOwner.clear(); |
+ } else { |
+ double underlyingFraction = currentInterpolation.m_cachedConversion->interpolateUnderlyingFraction( |
+ currentInterpolation.m_startKeyframe->underlyingFraction(), |
+ currentInterpolation.m_endKeyframe->underlyingFraction(), |
+ currentInterpolation.m_currentFraction); |
+ if (!underlyingValueOwner) { |
+ underlyingValueOwner = underlyingValue->clone(); |
+ underlyingValue = underlyingValueOwner.get(); |
+ } |
+ underlyingValue->interpolableValue().scaleAndAdd(underlyingFraction, currentInterpolation.m_cachedValue->interpolableValue()); |
+ } |
+ } |
+ |
+ if (shouldApply && underlyingValue) { |
+ underlyingValue->type().apply(underlyingValue->interpolableValue(), underlyingValue->nonInterpolableValue(), state); |
} |
- m_cachedValue->type().apply(*appliedInterpolableValue, m_cachedValue->nonInterpolableValue(), state); |
- setFlagIfInheritUsed(state); |
} |
} // namespace blink |