| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/animation/InvalidatableStyleInterpolation.h" |
| 7 |
| 8 #include "core/animation/StringKeyframe.h" |
| 9 |
| 10 namespace blink { |
| 11 |
| 12 class PairwiseConversionCache : public InvalidatableStyleInterpolation::CachedCo
nversion { |
| 13 public: |
| 14 static PassOwnPtrWillBeRawPtr<PairwiseConversionCache> create( |
| 15 PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid, |
| 16 const AnimationType& type, |
| 17 PassOwnPtrWillBeRawPtr<InterpolableValue> startInterpolableValue, |
| 18 PassOwnPtrWillBeRawPtr<InterpolableValue> endInterpolableValue, |
| 19 PassRefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue) |
| 20 { |
| 21 return adoptPtrWillBeNoop(new PairwiseConversionCache(isInvalid, type, s
tartInterpolableValue, endInterpolableValue, nonInterpolableValue)); |
| 22 } |
| 23 |
| 24 virtual void interpolate(double fraction, AnimationValue& result) const |
| 25 { |
| 26 ASSERT_UNUSED(m_type, result.type == &m_type); |
| 27 ASSERT(result.nonInterpolableValue == m_nonInterpolableValue); |
| 28 m_startInterpolableValue->interpolate(*m_endInterpolableValue, fraction,
*result.interpolableValue); |
| 29 } |
| 30 |
| 31 DEFINE_INLINE_VIRTUAL_TRACE() |
| 32 { |
| 33 CachedConversion::trace(visitor); |
| 34 visitor->trace(m_startInterpolableValue); |
| 35 visitor->trace(m_endInterpolableValue); |
| 36 visitor->trace(m_nonInterpolableValue); |
| 37 } |
| 38 |
| 39 private: |
| 40 PairwiseConversionCache( |
| 41 PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid, |
| 42 const AnimationType& type, |
| 43 PassOwnPtrWillBeRawPtr<InterpolableValue> startInterpolableValue, |
| 44 PassOwnPtrWillBeRawPtr<InterpolableValue> endInterpolableValue, |
| 45 PassRefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue) |
| 46 : CachedConversion(isInvalid) |
| 47 , m_type(type) |
| 48 , m_startInterpolableValue(startInterpolableValue) |
| 49 , m_endInterpolableValue(endInterpolableValue) |
| 50 , m_nonInterpolableValue(nonInterpolableValue) |
| 51 { } |
| 52 |
| 53 const AnimationType& m_type; |
| 54 OwnPtrWillBeMember<InterpolableValue> m_startInterpolableValue; |
| 55 OwnPtrWillBeMember<InterpolableValue> m_endInterpolableValue; |
| 56 RefPtrWillBeMember<NonInterpolableValue> m_nonInterpolableValue; |
| 57 }; |
| 58 |
| 59 class DefaultConversionCache : public InvalidatableStyleInterpolation::CachedCon
version { |
| 60 public: |
| 61 static PassOwnPtrWillBeRawPtr<DefaultConversionCache> create( |
| 62 PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid, |
| 63 AnimationValue& start, |
| 64 AnimationValue& end) |
| 65 { |
| 66 return adoptPtrWillBeNoop(new DefaultConversionCache(isInvalid, start, e
nd)); |
| 67 } |
| 68 |
| 69 static bool isBeforeFlip(double fraction) { return fraction < 0.5; } |
| 70 |
| 71 virtual void interpolate(double fraction, AnimationValue& result) const |
| 72 { |
| 73 if (!std::isnan(m_lastFraction) && isBeforeFlip(fraction) == isBeforeFli
p(m_lastFraction)) |
| 74 return; |
| 75 result.copy(isBeforeFlip(fraction) ? m_start : m_end); |
| 76 m_lastFraction = fraction; |
| 77 } |
| 78 |
| 79 DEFINE_INLINE_VIRTUAL_TRACE() |
| 80 { |
| 81 CachedConversion::trace(visitor); |
| 82 visitor->trace(m_start); |
| 83 visitor->trace(m_end); |
| 84 } |
| 85 |
| 86 private: |
| 87 DefaultConversionCache( |
| 88 PassRefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid, |
| 89 AnimationValue& start, |
| 90 AnimationValue& end) |
| 91 : CachedConversion(isInvalid) |
| 92 , m_lastFraction(std::numeric_limits<double>::quiet_NaN()) |
| 93 { |
| 94 m_start.consume(start); |
| 95 m_end.consume(end); |
| 96 } |
| 97 |
| 98 AnimationValue m_start; |
| 99 AnimationValue m_end; |
| 100 mutable double m_lastFraction; |
| 101 }; |
| 102 |
| 103 |
| 104 InvalidatableStyleInterpolation::InvalidatableStyleInterpolation( |
| 105 const Vector<const AnimationType*>& applicableTypes, |
| 106 PassRefPtrWillBeRawPtr<CSSPropertySpecificKeyframe> startKeyframe, |
| 107 PassRefPtrWillBeRawPtr<CSSPropertySpecificKeyframe> endKeyframe) |
| 108 : StyleInterpolation(nullptr, nullptr, applicableTypes.first()->property()) |
| 109 , m_applicableTypes(applicableTypes) |
| 110 , m_startKeyframe(startKeyframe) |
| 111 , m_endKeyframe(endKeyframe) |
| 112 , m_cachedConversion(nullptr) |
| 113 { |
| 114 maybeCachePairwiseConversion(nullptr); |
| 115 interpolate(0, 0); |
| 116 } |
| 117 |
| 118 bool InvalidatableStyleInterpolation::maybeCachePairwiseConversion(const StyleRe
solverState* state) const |
| 119 { |
| 120 for (const auto& animationType : m_applicableTypes) { |
| 121 RefPtrWillBeRawPtr<InterpolationIsInvalid> isInvalid; |
| 122 OwnPtrWillBeRawPtr<InterpolableValue> startInterpolableValue; |
| 123 OwnPtrWillBeRawPtr<InterpolableValue> endInterpolableValue; |
| 124 RefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue; |
| 125 if (animationType->maybeConvertPairwise(*m_startKeyframe, *m_endKeyframe
, state, isInvalid, startInterpolableValue, endInterpolableValue, nonInterpolabl
eValue)) { |
| 126 m_cachedConversion = PairwiseConversionCache::create( |
| 127 isInvalid.release(), |
| 128 *animationType, |
| 129 startInterpolableValue.release(), |
| 130 endInterpolableValue.release(), |
| 131 nonInterpolableValue.release()); |
| 132 return true; |
| 133 } |
| 134 } |
| 135 return false; |
| 136 } |
| 137 |
| 138 void InvalidatableStyleInterpolation::interpolate(int, double fraction) |
| 139 { |
| 140 m_currentFraction = fraction; |
| 141 if (m_cachedConversion) |
| 142 m_cachedConversion->interpolate(fraction, m_cachedValue); |
| 143 else |
| 144 m_cachedValue.clear(); |
| 145 } |
| 146 |
| 147 void InvalidatableStyleInterpolation::validateCache(const StyleResolverState& st
ate) const |
| 148 { |
| 149 if (m_cachedConversion && !m_cachedConversion->isInvalid(state)) |
| 150 return; |
| 151 m_cachedConversion = nullptr; |
| 152 if (!maybeCachePairwiseConversion(&state)) |
| 153 cacheDefaultConversion(state); |
| 154 m_cachedConversion->interpolate(m_currentFraction, m_cachedValue); |
| 155 } |
| 156 |
| 157 void InvalidatableStyleInterpolation::cacheDefaultConversion(const StyleResolver
State& state) const |
| 158 { |
| 159 RefPtrWillBeRawPtr<InterpolationIsInvalid> startIsInvalid; |
| 160 AnimationValue startValue = convertSingleKeyframe(state, *m_startKeyframe, s
tartIsInvalid); |
| 161 |
| 162 RefPtrWillBeRawPtr<InterpolationIsInvalid> endIsInvalid; |
| 163 AnimationValue endValue = convertSingleKeyframe(state, *m_endKeyframe, endIs
Invalid); |
| 164 |
| 165 InterpolationIsInvalid::chain(startIsInvalid, endIsInvalid.release()); |
| 166 m_cachedConversion = DefaultConversionCache::create(startIsInvalid.release()
, startValue, endValue); |
| 167 } |
| 168 |
| 169 AnimationValue InvalidatableStyleInterpolation::convertSingleKeyframe(const Styl
eResolverState& state, const CSSPropertySpecificKeyframe& keyframe, RefPtrWillBe
RawPtr<InterpolationIsInvalid>& resultIsInvalid) const |
| 170 { |
| 171 for (const auto& animationType : m_applicableTypes) { |
| 172 OwnPtrWillBeRawPtr<InterpolableValue> interpolableValue; |
| 173 RefPtrWillBeRawPtr<NonInterpolableValue> nonInterpolableValue; |
| 174 if (animationType->maybeConvertSingle(keyframe, &state, resultIsInvalid,
interpolableValue, nonInterpolableValue)) |
| 175 return AnimationValue(animationType, interpolableValue.release(), no
nInterpolableValue.release()); |
| 176 } |
| 177 ASSERT_NOT_REACHED(); |
| 178 } |
| 179 |
| 180 void InvalidatableStyleInterpolation::apply(StyleResolverState& state) const |
| 181 { |
| 182 validateCache(state); |
| 183 if (m_cachedValue) |
| 184 m_cachedValue.type->apply(*m_cachedValue.interpolableValue, m_cachedValu
e.nonInterpolableValue.get(), state); |
| 185 } |
| 186 |
| 187 } // namespace blink |
| OLD | NEW |