Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/animation/InvalidatableStyleInterpolation.h" | 6 #include "core/animation/InvalidatableStyleInterpolation.h" |
| 7 | 7 |
| 8 #include "core/animation/StringKeyframe.h" | 8 #include "core/animation/StringKeyframe.h" |
| 9 #include "core/css/resolver/StyleResolverState.h" | 9 #include "core/css/resolver/StyleResolverState.h" |
| 10 | 10 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != under lyingValue->type()) | 90 if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != under lyingValue->type()) |
| 91 return false; | 91 return false; |
| 92 } | 92 } |
| 93 for (const auto& checker : m_conversionCheckers) { | 93 for (const auto& checker : m_conversionCheckers) { |
| 94 if (!checker->isValid(state)) | 94 if (!checker->isValid(state)) |
| 95 return false; | 95 return false; |
| 96 } | 96 } |
| 97 return true; | 97 return true; |
| 98 } | 98 } |
| 99 | 99 |
| 100 void InvalidatableStyleInterpolation::ensureValidInterpolation(const StyleResolv erState& state, const InterpolationValue* underlyingValue) const | 100 const InterpolationValue* InvalidatableStyleInterpolation::ensureValidInterpolat ion(const StyleResolverState& state, const InterpolationValue* underlyingValue) const |
| 101 { | 101 { |
| 102 if (m_cachedConversion && isCacheValid(state, underlyingValue)) | 102 if (m_cachedConversion && isCacheValid(state, underlyingValue)) |
| 103 return; | 103 return m_cachedValue.get(); |
| 104 m_conversionCheckers.clear(); | 104 m_conversionCheckers.clear(); |
| 105 if (!maybeCachePairwiseConversion(&state, underlyingValue)) { | 105 if (!maybeCachePairwiseConversion(&state, underlyingValue)) { |
| 106 m_cachedConversion = FlipPrimitiveInterpolation::create( | 106 m_cachedConversion = FlipPrimitiveInterpolation::create( |
| 107 convertSingleKeyframe(*m_startKeyframe, state, underlyingValue), | 107 convertSingleKeyframe(*m_startKeyframe, state, underlyingValue), |
| 108 convertSingleKeyframe(*m_endKeyframe, state, underlyingValue)); | 108 convertSingleKeyframe(*m_endKeyframe, state, underlyingValue)); |
| 109 } | 109 } |
| 110 m_cachedConversion->interpolateValue(m_currentFraction, m_cachedValue); | 110 m_cachedConversion->interpolateValue(m_currentFraction, m_cachedValue); |
| 111 return m_cachedValue.get(); | |
| 111 } | 112 } |
| 112 | 113 |
| 113 void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s tate) const | 114 void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s tate) const |
| 114 { | 115 { |
| 115 if (!state.parentStyle()) | 116 if (!state.parentStyle()) |
| 116 return; | 117 return; |
| 117 if ((m_startKeyframe->value() && m_startKeyframe->value()->isInheritedValue( )) | 118 if ((m_startKeyframe->value() && m_startKeyframe->value()->isInheritedValue( )) |
| 118 || (m_endKeyframe->value() && m_endKeyframe->value()->isInheritedValue() )) { | 119 || (m_endKeyframe->value() && m_endKeyframe->value()->isInheritedValue() )) { |
| 119 state.parentStyle()->setHasExplicitlyInheritedProperties(); | 120 state.parentStyle()->setHasExplicitlyInheritedProperties(); |
| 120 } | 121 } |
| 121 } | 122 } |
| 122 | 123 |
| 123 void InvalidatableStyleInterpolation::apply(StyleResolverState& state) const | 124 // Handles memory management of underlying InterpolationValues in applyStack() |
| 125 // Ensures we perform copy on write if we are not the owner of an underlying Int erpolationValue. | |
| 126 // This functions similar to a DataRef except on OwnPtr'd objects. | |
| 127 class UnderlyingValue { | |
| 128 STACK_ALLOCATED(); | |
| 129 public: | |
| 130 UnderlyingValue() | |
| 131 : m_owner() | |
| 132 , m_pointer(nullptr) | |
| 133 { } | |
| 134 | |
| 135 void set(const InterpolationValue* interpolationValue) | |
| 136 { | |
| 137 m_owner.clear(); | |
| 138 m_pointer = const_cast<InterpolationValue*>(interpolationValue); | |
|
dstockwell
2015/09/07 03:46:23
comment why this is safe
alancutter (OOO until 2018)
2015/09/07 04:34:12
Done.
| |
| 139 } | |
| 140 void set(PassOwnPtr<InterpolationValue> interpolateValue) | |
| 141 { | |
| 142 m_owner = interpolateValue; | |
| 143 m_pointer = m_owner.get(); | |
| 144 } | |
| 145 InterpolationValue& access() | |
| 146 { | |
| 147 ASSERT(m_pointer); | |
| 148 if (!m_owner) | |
| 149 set(m_pointer->clone()); | |
| 150 return *m_pointer; | |
| 151 } | |
| 152 const InterpolationValue* get() const { return m_pointer; } | |
| 153 operator bool() const { return m_pointer; } | |
| 154 const InterpolationValue* operator->() const | |
| 155 { | |
| 156 ASSERT(m_pointer); | |
| 157 return m_pointer; | |
| 158 } | |
| 159 | |
| 160 private: | |
| 161 OwnPtr<InterpolationValue> m_owner; | |
| 162 InterpolationValue* m_pointer; | |
| 163 }; | |
| 164 | |
| 165 void InvalidatableStyleInterpolation::applyStack(const ActiveInterpolations& int erpolations, StyleResolverState& state) | |
| 124 { | 166 { |
| 125 OwnPtr<InterpolationValue> underlyingValue = dependsOnUnderlyingValue() ? ma ybeConvertUnderlyingValue(state) : nullptr; | 167 ASSERT(interpolations.size() > 0); |
| 126 ensureValidInterpolation(state, underlyingValue.get()); | 168 size_t startingIndex = 0; |
| 127 if (!m_cachedValue) | 169 |
| 128 return; | 170 // Compute the underlying value to composite onto. |
| 129 const InterpolableValue* appliedInterpolableValue = &m_cachedValue->interpol ableValue(); | 171 UnderlyingValue underlyingValue; |
| 130 if (underlyingValue && m_cachedValue->type() == underlyingValue->type()) { | 172 const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableS tyleInterpolation(*interpolations.at(startingIndex)); |
| 131 double underlyingFraction = m_cachedConversion->interpolateUnderlyingFra ction(m_startKeyframe->underlyingFraction(), m_endKeyframe->underlyingFraction() , m_currentFraction); | 173 if (firstInterpolation.dependsOnUnderlyingValue()) { |
| 132 underlyingValue->interpolableValue().scaleAndAdd(underlyingFraction, m_c achedValue->interpolableValue()); | 174 underlyingValue.set(firstInterpolation.maybeConvertUnderlyingValue(state )); |
| 133 appliedInterpolableValue = &underlyingValue->interpolableValue(); | 175 } else { |
| 176 const InterpolationValue* firstValue = firstInterpolation.ensureValidInt erpolation(state, nullptr); | |
| 177 // Fast path for replace interpolations that are the only one to apply. | |
| 178 if (interpolations.size() == 1) { | |
| 179 if (firstValue) { | |
|
dstockwell
2015/09/07 03:46:23
merge with previous line
alancutter (OOO until 2018)
2015/09/07 04:34:12
It would not be equivalent due to the return state
| |
| 180 firstInterpolation.setFlagIfInheritUsed(state); | |
| 181 firstValue->type().apply(firstValue->interpolableValue(), firstV alue->nonInterpolableValue(), state); | |
| 182 } | |
| 183 return; | |
| 184 } | |
| 185 underlyingValue.set(firstValue); | |
| 186 startingIndex++; | |
| 134 } | 187 } |
| 135 m_cachedValue->type().apply(*appliedInterpolableValue, m_cachedValue->nonInt erpolableValue(), state); | 188 |
| 136 setFlagIfInheritUsed(state); | 189 // Composite interpolations onto the underlying value. |
| 190 bool shouldApply = false; | |
| 191 for (size_t i = startingIndex; i < interpolations.size(); i++) { | |
| 192 const InvalidatableStyleInterpolation& currentInterpolation = toInvalida tableStyleInterpolation(*interpolations.at(i)); | |
| 193 ASSERT(currentInterpolation.dependsOnUnderlyingValue()); | |
| 194 const InterpolationValue* currentValue = currentInterpolation.ensureVali dInterpolation(state, underlyingValue.get()); | |
| 195 if (!currentValue) | |
| 196 continue; | |
| 197 shouldApply = true; | |
| 198 currentInterpolation.setFlagIfInheritUsed(state); | |
| 199 if (!underlyingValue || underlyingValue->type() != currentValue->type()) { | |
| 200 underlyingValue.set(currentValue); | |
| 201 } else { | |
| 202 double underlyingFraction = currentInterpolation.m_cachedConversion- >interpolateUnderlyingFraction( | |
| 203 currentInterpolation.m_startKeyframe->underlyingFraction(), | |
| 204 currentInterpolation.m_endKeyframe->underlyingFraction(), | |
| 205 currentInterpolation.m_currentFraction); | |
| 206 underlyingValue.access().interpolableValue().scaleAndAdd(underlyingF raction, currentInterpolation.m_cachedValue->interpolableValue()); | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 if (shouldApply && underlyingValue) { | |
| 211 underlyingValue->type().apply(underlyingValue->interpolableValue(), unde rlyingValue->nonInterpolableValue(), state); | |
| 212 } | |
| 137 } | 213 } |
| 138 | 214 |
| 139 } // namespace blink | 215 } // namespace blink |
| OLD | NEW |