| 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 "core/animation/InvalidatableInterpolation.h" | 5 #include "core/animation/InvalidatableInterpolation.h" |
| 6 | 6 |
| 7 #include "core/animation/InterpolationEnvironment.h" | 7 #include "core/animation/InterpolationEnvironment.h" |
| 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 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 namespace blink { | 12 namespace blink { |
| 13 | 13 |
| 14 void InvalidatableInterpolation::interpolate(int, double fraction) { | 14 void InvalidatableInterpolation::interpolate(int, double fraction) { |
| 15 if (fraction == m_currentFraction) | 15 if (fraction == m_currentFraction) |
| 16 return; | 16 return; |
| 17 | 17 |
| 18 if (m_currentFraction == 0 || m_currentFraction == 1 || fraction == 0 || | 18 if (m_currentFraction == 0 || m_currentFraction == 1 || fraction == 0 || |
| 19 fraction == 1) | 19 fraction == 1) { |
| 20 clearCache(); | 20 clearConversionCache(); |
| 21 } |
| 21 | 22 |
| 22 m_currentFraction = fraction; | 23 m_currentFraction = fraction; |
| 23 if (m_isCached && m_cachedPairConversion) | 24 if (m_isConversionCached && m_cachedPairConversion) |
| 24 m_cachedPairConversion->interpolateValue(fraction, m_cachedValue); | 25 m_cachedPairConversion->interpolateValue(fraction, m_cachedValue); |
| 25 // We defer the interpolation to ensureValidInterpolation() if | 26 // We defer the interpolation to ensureValidConversion() if |
| 26 // m_cachedPairConversion is null. | 27 // m_cachedPairConversion is null. |
| 27 } | 28 } |
| 28 | 29 |
| 29 std::unique_ptr<PairwisePrimitiveInterpolation> | 30 std::unique_ptr<PairwisePrimitiveInterpolation> |
| 30 InvalidatableInterpolation::maybeConvertPairwise( | 31 InvalidatableInterpolation::maybeConvertPairwise( |
| 31 const InterpolationEnvironment& environment, | 32 const InterpolationEnvironment& environment, |
| 32 const UnderlyingValueOwner& underlyingValueOwner) const { | 33 const UnderlyingValueOwner& underlyingValueOwner) const { |
| 33 DCHECK(m_currentFraction != 0 && m_currentFraction != 1); | 34 DCHECK(m_currentFraction != 0 && m_currentFraction != 1); |
| 34 for (const auto& interpolationType : m_interpolationTypes) { | 35 for (const auto& interpolationType : m_interpolationTypes) { |
| 35 if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) && | 36 if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) && |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 return (m_startKeyframe->underlyingFraction() != 0 && | 104 return (m_startKeyframe->underlyingFraction() != 0 && |
| 104 m_currentFraction != 1) || | 105 m_currentFraction != 1) || |
| 105 (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0); | 106 (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0); |
| 106 } | 107 } |
| 107 | 108 |
| 108 bool InvalidatableInterpolation::isNeutralKeyframeActive() const { | 109 bool InvalidatableInterpolation::isNeutralKeyframeActive() const { |
| 109 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || | 110 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || |
| 110 (m_endKeyframe->isNeutral() && m_currentFraction != 0); | 111 (m_endKeyframe->isNeutral() && m_currentFraction != 0); |
| 111 } | 112 } |
| 112 | 113 |
| 113 void InvalidatableInterpolation::clearCache() const { | 114 void InvalidatableInterpolation::clearConversionCache() const { |
| 114 m_isCached = false; | 115 m_isConversionCached = false; |
| 115 m_cachedPairConversion.reset(); | 116 m_cachedPairConversion.reset(); |
| 116 m_conversionCheckers.clear(); | 117 m_conversionCheckers.clear(); |
| 117 m_cachedValue.reset(); | 118 m_cachedValue.reset(); |
| 118 } | 119 } |
| 119 | 120 |
| 120 bool InvalidatableInterpolation::isCacheValid( | 121 bool InvalidatableInterpolation::isConversionCacheValid( |
| 121 const InterpolationEnvironment& environment, | 122 const InterpolationEnvironment& environment, |
| 122 const UnderlyingValueOwner& underlyingValueOwner) const { | 123 const UnderlyingValueOwner& underlyingValueOwner) const { |
| 123 if (!m_isCached) | 124 if (!m_isConversionCached) |
| 124 return false; | 125 return false; |
| 125 if (isNeutralKeyframeActive()) { | 126 if (isNeutralKeyframeActive()) { |
| 126 if (m_cachedPairConversion && m_cachedPairConversion->isFlip()) | 127 if (m_cachedPairConversion && m_cachedPairConversion->isFlip()) |
| 127 return false; | 128 return false; |
| 128 // Pairwise interpolation can never happen between different | 129 // Pairwise interpolation can never happen between different |
| 129 // InterpolationTypes, neutral values always represent the underlying value. | 130 // InterpolationTypes, neutral values always represent the underlying value. |
| 130 if (!underlyingValueOwner || !m_cachedValue || | 131 if (!underlyingValueOwner || !m_cachedValue || |
| 131 m_cachedValue->type() != underlyingValueOwner.type()) | 132 m_cachedValue->type() != underlyingValueOwner.type()) |
| 132 return false; | 133 return false; |
| 133 } | 134 } |
| 134 for (const auto& checker : m_conversionCheckers) { | 135 for (const auto& checker : m_conversionCheckers) { |
| 135 if (!checker->isValid(environment, underlyingValueOwner.value())) | 136 if (!checker->isValid(environment, underlyingValueOwner.value())) |
| 136 return false; | 137 return false; |
| 137 } | 138 } |
| 138 return true; | 139 return true; |
| 139 } | 140 } |
| 140 | 141 |
| 141 const TypedInterpolationValue* | 142 const TypedInterpolationValue* |
| 142 InvalidatableInterpolation::ensureValidInterpolation( | 143 InvalidatableInterpolation::ensureValidConversion( |
| 143 const InterpolationEnvironment& environment, | 144 const InterpolationEnvironment& environment, |
| 144 const UnderlyingValueOwner& underlyingValueOwner) const { | 145 const UnderlyingValueOwner& underlyingValueOwner) const { |
| 145 DCHECK(!std::isnan(m_currentFraction)); | 146 DCHECK(!std::isnan(m_currentFraction)); |
| 146 if (isCacheValid(environment, underlyingValueOwner)) | 147 if (isConversionCacheValid(environment, underlyingValueOwner)) |
| 147 return m_cachedValue.get(); | 148 return m_cachedValue.get(); |
| 148 clearCache(); | 149 clearConversionCache(); |
| 149 if (m_currentFraction == 0) { | 150 if (m_currentFraction == 0) { |
| 150 m_cachedValue = convertSingleKeyframe(*m_startKeyframe, environment, | 151 m_cachedValue = convertSingleKeyframe(*m_startKeyframe, environment, |
| 151 underlyingValueOwner); | 152 underlyingValueOwner); |
| 152 } else if (m_currentFraction == 1) { | 153 } else if (m_currentFraction == 1) { |
| 153 m_cachedValue = convertSingleKeyframe(*m_endKeyframe, environment, | 154 m_cachedValue = convertSingleKeyframe(*m_endKeyframe, environment, |
| 154 underlyingValueOwner); | 155 underlyingValueOwner); |
| 155 } else { | 156 } else { |
| 156 std::unique_ptr<PairwisePrimitiveInterpolation> pairwiseConversion = | 157 std::unique_ptr<PairwisePrimitiveInterpolation> pairwiseConversion = |
| 157 maybeConvertPairwise(environment, underlyingValueOwner); | 158 maybeConvertPairwise(environment, underlyingValueOwner); |
| 158 if (pairwiseConversion) { | 159 if (pairwiseConversion) { |
| 159 m_cachedValue = pairwiseConversion->initialValue(); | 160 m_cachedValue = pairwiseConversion->initialValue(); |
| 160 m_cachedPairConversion = std::move(pairwiseConversion); | 161 m_cachedPairConversion = std::move(pairwiseConversion); |
| 161 } else { | 162 } else { |
| 162 m_cachedPairConversion = FlipPrimitiveInterpolation::create( | 163 m_cachedPairConversion = FlipPrimitiveInterpolation::create( |
| 163 convertSingleKeyframe(*m_startKeyframe, environment, | 164 convertSingleKeyframe(*m_startKeyframe, environment, |
| 164 underlyingValueOwner), | 165 underlyingValueOwner), |
| 165 convertSingleKeyframe(*m_endKeyframe, environment, | 166 convertSingleKeyframe(*m_endKeyframe, environment, |
| 166 underlyingValueOwner)); | 167 underlyingValueOwner)); |
| 167 } | 168 } |
| 168 m_cachedPairConversion->interpolateValue(m_currentFraction, m_cachedValue); | 169 m_cachedPairConversion->interpolateValue(m_currentFraction, m_cachedValue); |
| 169 } | 170 } |
| 170 m_isCached = true; | 171 m_isConversionCached = true; |
| 171 return m_cachedValue.get(); | 172 return m_cachedValue.get(); |
| 172 } | 173 } |
| 173 | 174 |
| 174 void InvalidatableInterpolation::setFlagIfInheritUsed( | 175 void InvalidatableInterpolation::setFlagIfInheritUsed( |
| 175 InterpolationEnvironment& environment) const { | 176 InterpolationEnvironment& environment) const { |
| 176 if (!m_property.isCSSProperty() && !m_property.isPresentationAttribute()) | 177 if (!m_property.isCSSProperty() && !m_property.isPresentationAttribute()) |
| 177 return; | 178 return; |
| 178 if (!environment.state().parentStyle()) | 179 if (!environment.state().parentStyle()) |
| 179 return; | 180 return; |
| 180 const CSSValue* startValue = | 181 const CSSValue* startValue = |
| (...skipping 24 matching lines...) Expand all Loading... |
| 205 | 206 |
| 206 // Compute the underlying value to composite onto. | 207 // Compute the underlying value to composite onto. |
| 207 UnderlyingValueOwner underlyingValueOwner; | 208 UnderlyingValueOwner underlyingValueOwner; |
| 208 const InvalidatableInterpolation& firstInterpolation = | 209 const InvalidatableInterpolation& firstInterpolation = |
| 209 toInvalidatableInterpolation(*interpolations.at(startingIndex)); | 210 toInvalidatableInterpolation(*interpolations.at(startingIndex)); |
| 210 if (firstInterpolation.dependsOnUnderlyingValue()) { | 211 if (firstInterpolation.dependsOnUnderlyingValue()) { |
| 211 underlyingValueOwner.set( | 212 underlyingValueOwner.set( |
| 212 firstInterpolation.maybeConvertUnderlyingValue(environment)); | 213 firstInterpolation.maybeConvertUnderlyingValue(environment)); |
| 213 } else { | 214 } else { |
| 214 const TypedInterpolationValue* firstValue = | 215 const TypedInterpolationValue* firstValue = |
| 215 firstInterpolation.ensureValidInterpolation(environment, | 216 firstInterpolation.ensureValidConversion(environment, |
| 216 underlyingValueOwner); | 217 underlyingValueOwner); |
| 217 // Fast path for replace interpolations that are the only one to apply. | 218 // Fast path for replace interpolations that are the only one to apply. |
| 218 if (interpolations.size() == 1) { | 219 if (interpolations.size() == 1) { |
| 219 if (firstValue) { | 220 if (firstValue) { |
| 220 firstInterpolation.setFlagIfInheritUsed(environment); | 221 firstInterpolation.setFlagIfInheritUsed(environment); |
| 221 firstValue->type().apply(firstValue->interpolableValue(), | 222 firstValue->type().apply(firstValue->interpolableValue(), |
| 222 firstValue->getNonInterpolableValue(), | 223 firstValue->getNonInterpolableValue(), |
| 223 environment); | 224 environment); |
| 224 } | 225 } |
| 225 return; | 226 return; |
| 226 } | 227 } |
| 227 underlyingValueOwner.set(firstValue); | 228 underlyingValueOwner.set(firstValue); |
| 228 startingIndex++; | 229 startingIndex++; |
| 229 } | 230 } |
| 230 | 231 |
| 231 // Composite interpolations onto the underlying value. | 232 // Composite interpolations onto the underlying value. |
| 232 bool shouldApply = false; | 233 bool shouldApply = false; |
| 233 for (size_t i = startingIndex; i < interpolations.size(); i++) { | 234 for (size_t i = startingIndex; i < interpolations.size(); i++) { |
| 234 const InvalidatableInterpolation& currentInterpolation = | 235 const InvalidatableInterpolation& currentInterpolation = |
| 235 toInvalidatableInterpolation(*interpolations.at(i)); | 236 toInvalidatableInterpolation(*interpolations.at(i)); |
| 236 DCHECK(currentInterpolation.dependsOnUnderlyingValue()); | 237 DCHECK(currentInterpolation.dependsOnUnderlyingValue()); |
| 237 const TypedInterpolationValue* currentValue = | 238 const TypedInterpolationValue* currentValue = |
| 238 currentInterpolation.ensureValidInterpolation(environment, | 239 currentInterpolation.ensureValidConversion(environment, |
| 239 underlyingValueOwner); | 240 underlyingValueOwner); |
| 240 if (!currentValue) | 241 if (!currentValue) |
| 241 continue; | 242 continue; |
| 242 shouldApply = true; | 243 shouldApply = true; |
| 243 currentInterpolation.setFlagIfInheritUsed(environment); | 244 currentInterpolation.setFlagIfInheritUsed(environment); |
| 244 double underlyingFraction = currentInterpolation.underlyingFraction(); | 245 double underlyingFraction = currentInterpolation.underlyingFraction(); |
| 245 if (underlyingFraction == 0 || !underlyingValueOwner || | 246 if (underlyingFraction == 0 || !underlyingValueOwner || |
| 246 underlyingValueOwner.type() != currentValue->type()) | 247 underlyingValueOwner.type() != currentValue->type()) |
| 247 underlyingValueOwner.set(currentValue); | 248 underlyingValueOwner.set(currentValue); |
| 248 else | 249 else |
| 249 currentValue->type().composite(underlyingValueOwner, underlyingFraction, | 250 currentValue->type().composite(underlyingValueOwner, underlyingFraction, |
| 250 currentValue->value(), | 251 currentValue->value(), |
| 251 currentInterpolation.m_currentFraction); | 252 currentInterpolation.m_currentFraction); |
| 252 } | 253 } |
| 253 | 254 |
| 254 if (shouldApply && underlyingValueOwner) | 255 if (shouldApply && underlyingValueOwner) |
| 255 underlyingValueOwner.type().apply( | 256 underlyingValueOwner.type().apply( |
| 256 *underlyingValueOwner.value().interpolableValue, | 257 *underlyingValueOwner.value().interpolableValue, |
| 257 underlyingValueOwner.value().nonInterpolableValue.get(), environment); | 258 underlyingValueOwner.value().nonInterpolableValue.get(), environment); |
| 258 } | 259 } |
| 259 | 260 |
| 260 } // namespace blink | 261 } // namespace blink |
| OLD | NEW |