Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(479)

Unified Diff: Source/core/animation/InvalidatableStyleInterpolation.cpp

Issue 1329843002: Support per property CSS Animation stacks (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Lint Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/animation/InvalidatableStyleInterpolation.cpp
diff --git a/Source/core/animation/InvalidatableStyleInterpolation.cpp b/Source/core/animation/InvalidatableStyleInterpolation.cpp
index d0f20a686b362d16feadb1ca1e5c59b8d394b7e9..0b787637b2c21f15f926df526a477adaa882ca44 100644
--- a/Source/core/animation/InvalidatableStyleInterpolation.cpp
+++ b/Source/core/animation/InvalidatableStyleInterpolation.cpp
@@ -97,10 +97,10 @@ bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& sta
return true;
}
-void InvalidatableStyleInterpolation::ensureValidInterpolation(const StyleResolverState& state, const InterpolationValue* underlyingValue) const
+const InterpolationValue* InvalidatableStyleInterpolation::ensureValidInterpolation(const StyleResolverState& state, const InterpolationValue* underlyingValue) const
{
if (m_cachedConversion && isCacheValid(state, underlyingValue))
- return;
+ return m_cachedValue.get();
m_conversionCheckers.clear();
if (!maybeCachePairwiseConversion(&state, underlyingValue)) {
m_cachedConversion = FlipPrimitiveInterpolation::create(
@@ -108,6 +108,7 @@ void InvalidatableStyleInterpolation::ensureValidInterpolation(const StyleResolv
convertSingleKeyframe(*m_endKeyframe, state, underlyingValue));
}
m_cachedConversion->interpolateValue(m_currentFraction, m_cachedValue);
+ return m_cachedValue.get();
}
void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& state) const
@@ -120,20 +121,97 @@ void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s
}
}
-void InvalidatableStyleInterpolation::apply(StyleResolverState& state) const
+// Handles memory management of underlying InterpolationValues in applyStack()
+// Ensures we perform copy on write if we are not the owner of an underlying InterpolationValue.
+// This functions similar to a DataRef except on OwnPtr'd objects.
+class UnderlyingValue {
+ STACK_ALLOCATED();
+public:
+ UnderlyingValue()
+ : m_owner()
+ , m_pointer(nullptr)
+ { }
+
+ void set(const InterpolationValue* interpolationValue)
+ {
+ // By clearing m_owner we will perform a copy when attempting to access()
+ // m_pointer as a mutable reference, thus upholding the const contract for
+ // this instance of interpolationValue despite the const_cast.
+ m_owner.clear();
+ m_pointer = const_cast<InterpolationValue*>(interpolationValue);
+ }
+ void set(PassOwnPtr<InterpolationValue> interpolationValue)
+ {
+ m_owner = interpolationValue;
+ m_pointer = m_owner.get();
+ }
+ InterpolationValue& access()
+ {
+ ASSERT(m_pointer);
+ if (!m_owner)
+ set(m_pointer->clone());
+ return *m_pointer;
+ }
+ const InterpolationValue* get() const { return m_pointer; }
+ operator bool() const { return m_pointer; }
+ const InterpolationValue* operator->() const
+ {
+ ASSERT(m_pointer);
+ return m_pointer;
+ }
+
+private:
+ OwnPtr<InterpolationValue> m_owner;
+ InterpolationValue* m_pointer;
+};
+
+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.isEmpty());
+ size_t startingIndex = 0;
+
+ // Compute the underlying value to composite onto.
+ UnderlyingValue underlyingValue;
+ const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableStyleInterpolation(*interpolations.at(startingIndex));
+ if (firstInterpolation.dependsOnUnderlyingValue()) {
+ underlyingValue.set(firstInterpolation.maybeConvertUnderlyingValue(state));
+ } else {
+ const InterpolationValue* firstValue = firstInterpolation.ensureValidInterpolation(state, nullptr);
+ // Fast path for replace interpolations that are the only one to apply.
+ if (interpolations.size() == 1) {
+ if (firstValue) {
+ firstInterpolation.setFlagIfInheritUsed(state);
+ firstValue->type().apply(firstValue->interpolableValue(), firstValue->nonInterpolableValue(), state);
+ }
+ return;
+ }
+ underlyingValue.set(firstValue);
+ 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());
+ const InterpolationValue* currentValue = currentInterpolation.ensureValidInterpolation(state, underlyingValue.get());
+ if (!currentValue)
+ continue;
+ shouldApply = true;
+ currentInterpolation.setFlagIfInheritUsed(state);
+ if (!underlyingValue || underlyingValue->type() != currentValue->type()) {
+ underlyingValue.set(currentValue);
+ } else {
+ double underlyingFraction = currentInterpolation.m_cachedConversion->interpolateUnderlyingFraction(
+ currentInterpolation.m_startKeyframe->underlyingFraction(),
+ currentInterpolation.m_endKeyframe->underlyingFraction(),
+ currentInterpolation.m_currentFraction);
+ underlyingValue.access().interpolableValue().scaleAndAdd(underlyingFraction, currentInterpolation.m_cachedValue->interpolableValue());
+ }
}
- m_cachedValue->type().apply(*appliedInterpolableValue, m_cachedValue->nonInterpolableValue(), state);
- setFlagIfInheritUsed(state);
+
+ if (shouldApply && underlyingValue)
+ underlyingValue->type().apply(underlyingValue->interpolableValue(), underlyingValue->nonInterpolableValue(), state);
}
} // namespace blink
« no previous file with comments | « Source/core/animation/InvalidatableStyleInterpolation.h ('k') | Source/core/animation/css/CSSAnimationUpdate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698