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 |
11 namespace blink { | 11 namespace blink { |
12 | 12 |
13 InvalidatableStyleInterpolation::InvalidatableStyleInterpolation( | 13 void InvalidatableStyleInterpolation::interpolate(int, double fraction) |
14 const Vector<const InterpolationType*>& interpolationTypes, | |
15 const CSSPropertySpecificKeyframe& startKeyframe, | |
16 const CSSPropertySpecificKeyframe& endKeyframe) | |
17 : StyleInterpolation(nullptr, nullptr, interpolationTypes.first()->property(
)) | |
18 , m_interpolationTypes(interpolationTypes) | |
19 , m_startKeyframe(&startKeyframe) | |
20 , m_endKeyframe(&endKeyframe) | |
21 { | 14 { |
22 maybeCachePairwiseConversion(nullptr, nullptr); | 15 if (fraction == m_currentFraction) |
23 interpolate(0, 0); | 16 return; |
| 17 |
| 18 if (m_currentFraction == 0 || m_currentFraction == 1 || fraction == 0 || fra
ction == 1) |
| 19 clearCache(); |
| 20 |
| 21 m_currentFraction = fraction; |
| 22 if (m_isCached && m_cachedPairConversion) |
| 23 m_cachedPairConversion->interpolateValue(fraction, m_cachedValue); |
| 24 // We defer the interpolation to ensureValidInterpolation() if m_cachedPairC
onversion is null. |
24 } | 25 } |
25 | 26 |
26 bool InvalidatableStyleInterpolation::maybeCachePairwiseConversion(const StyleRe
solverState* state, const InterpolationValue* underlyingValue) const | 27 PassOwnPtr<PairwisePrimitiveInterpolation> InvalidatableStyleInterpolation::mayb
eConvertPairwise(const StyleResolverState* state, const InterpolationValue* unde
rlyingValue) const |
27 { | 28 { |
| 29 ASSERT(m_currentFraction != 0 && m_currentFraction != 1); |
28 for (const auto& interpolationType : m_interpolationTypes) { | 30 for (const auto& interpolationType : m_interpolationTypes) { |
29 if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) && (!un
derlyingValue || underlyingValue->type() != *interpolationType)) | 31 if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) && (!un
derlyingValue || underlyingValue->type() != *interpolationType)) |
30 continue; | 32 continue; |
31 OwnPtr<PairwisePrimitiveInterpolation> pairwiseConversion = interpolatio
nType->maybeConvertPairwise(*m_startKeyframe, *m_endKeyframe, state, m_conversio
nCheckers); | 33 OwnPtr<PairwisePrimitiveInterpolation> pairwiseConversion = interpolatio
nType->maybeConvertPairwise(*m_startKeyframe, *m_endKeyframe, state, m_conversio
nCheckers); |
32 if (pairwiseConversion) { | 34 if (pairwiseConversion) |
33 m_cachedValue = pairwiseConversion->initialValue(); | 35 return pairwiseConversion.release(); |
34 m_cachedConversion = pairwiseConversion.release(); | |
35 return true; | |
36 } | |
37 } | 36 } |
38 return false; | 37 return nullptr; |
39 } | |
40 | |
41 void InvalidatableStyleInterpolation::interpolate(int, double fraction) | |
42 { | |
43 m_currentFraction = fraction; | |
44 if (m_cachedConversion) | |
45 m_cachedConversion->interpolateValue(fraction, m_cachedValue); | |
46 // We defer the interpolation to ensureValidInterpolation() if m_cachedConve
rsion is null. | |
47 } | 38 } |
48 | 39 |
49 PassOwnPtr<InterpolationValue> InvalidatableStyleInterpolation::convertSingleKey
frame(const CSSPropertySpecificKeyframe& keyframe, const StyleResolverState& sta
te, const InterpolationValue* underlyingValue) const | 40 PassOwnPtr<InterpolationValue> InvalidatableStyleInterpolation::convertSingleKey
frame(const CSSPropertySpecificKeyframe& keyframe, const StyleResolverState& sta
te, const InterpolationValue* underlyingValue) const |
50 { | 41 { |
51 if (keyframe.isNeutral() && !underlyingValue) | 42 if (keyframe.isNeutral() && !underlyingValue) |
52 return nullptr; | 43 return nullptr; |
53 for (const auto& interpolationType : m_interpolationTypes) { | 44 for (const auto& interpolationType : m_interpolationTypes) { |
54 if (keyframe.isNeutral() && underlyingValue->type() != *interpolationTyp
e) | 45 if (keyframe.isNeutral() && underlyingValue->type() != *interpolationTyp
e) |
55 continue; | 46 continue; |
56 OwnPtr<InterpolationValue> result = interpolationType->maybeConvertSingl
e(keyframe, &state, m_conversionCheckers); | 47 OwnPtr<InterpolationValue> result = interpolationType->maybeConvertSingl
e(keyframe, &state, m_conversionCheckers); |
(...skipping 17 matching lines...) Expand all Loading... |
74 bool InvalidatableStyleInterpolation::dependsOnUnderlyingValue() const | 65 bool InvalidatableStyleInterpolation::dependsOnUnderlyingValue() const |
75 { | 66 { |
76 return (m_startKeyframe->underlyingFraction() != 0 && m_currentFraction != 1
) || (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0); | 67 return (m_startKeyframe->underlyingFraction() != 0 && m_currentFraction != 1
) || (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0); |
77 } | 68 } |
78 | 69 |
79 bool InvalidatableStyleInterpolation::isNeutralKeyframeActive() const | 70 bool InvalidatableStyleInterpolation::isNeutralKeyframeActive() const |
80 { | 71 { |
81 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || (m_endKey
frame->isNeutral() && m_currentFraction != 0); | 72 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || (m_endKey
frame->isNeutral() && m_currentFraction != 0); |
82 } | 73 } |
83 | 74 |
| 75 void InvalidatableStyleInterpolation::clearCache() const |
| 76 { |
| 77 m_isCached = false; |
| 78 m_cachedPairConversion.clear(); |
| 79 m_conversionCheckers.clear(); |
| 80 m_cachedValue.clear(); |
| 81 } |
| 82 |
84 bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& sta
te, const InterpolationValue* underlyingValue) const | 83 bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& sta
te, const InterpolationValue* underlyingValue) const |
85 { | 84 { |
| 85 if (!m_isCached) |
| 86 return false; |
86 if (isNeutralKeyframeActive()) { | 87 if (isNeutralKeyframeActive()) { |
87 if (m_cachedConversion->isFlip()) | 88 if (m_cachedPairConversion && m_cachedPairConversion->isFlip()) |
88 return false; | 89 return false; |
89 // Pairwise interpolation can never happen between different Interpolati
onTypes, neutral values always represent the underlying value. | 90 // Pairwise interpolation can never happen between different Interpolati
onTypes, neutral values always represent the underlying value. |
90 if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != under
lyingValue->type()) | 91 if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != under
lyingValue->type()) |
91 return false; | 92 return false; |
92 } | 93 } |
93 for (const auto& checker : m_conversionCheckers) { | 94 for (const auto& checker : m_conversionCheckers) { |
94 if (!checker->isValid(state)) | 95 if (!checker->isValid(state)) |
95 return false; | 96 return false; |
96 } | 97 } |
97 return true; | 98 return true; |
98 } | 99 } |
99 | 100 |
100 const InterpolationValue* InvalidatableStyleInterpolation::ensureValidInterpolat
ion(const StyleResolverState& state, const InterpolationValue* underlyingValue)
const | 101 const InterpolationValue* InvalidatableStyleInterpolation::ensureValidInterpolat
ion(const StyleResolverState& state, const InterpolationValue* underlyingValue)
const |
101 { | 102 { |
102 if (m_cachedConversion && isCacheValid(state, underlyingValue)) | 103 ASSERT(!std::isnan(m_currentFraction)); |
| 104 if (isCacheValid(state, underlyingValue)) |
103 return m_cachedValue.get(); | 105 return m_cachedValue.get(); |
104 m_conversionCheckers.clear(); | 106 clearCache(); |
105 if (!maybeCachePairwiseConversion(&state, underlyingValue)) { | 107 if (m_currentFraction == 0) { |
106 m_cachedConversion = FlipPrimitiveInterpolation::create( | 108 m_cachedValue = convertSingleKeyframe(*m_startKeyframe, state, underlyin
gValue); |
107 convertSingleKeyframe(*m_startKeyframe, state, underlyingValue), | 109 } else if (m_currentFraction == 1) { |
108 convertSingleKeyframe(*m_endKeyframe, state, underlyingValue)); | 110 m_cachedValue = convertSingleKeyframe(*m_endKeyframe, state, underlyingV
alue); |
| 111 } else { |
| 112 OwnPtr<PairwisePrimitiveInterpolation> pairwiseConversion = maybeConvert
Pairwise(&state, underlyingValue); |
| 113 if (pairwiseConversion) { |
| 114 m_cachedValue = pairwiseConversion->initialValue(); |
| 115 m_cachedPairConversion = pairwiseConversion.release(); |
| 116 } else { |
| 117 m_cachedPairConversion = FlipPrimitiveInterpolation::create( |
| 118 convertSingleKeyframe(*m_startKeyframe, state, underlyingValue), |
| 119 convertSingleKeyframe(*m_endKeyframe, state, underlyingValue)); |
| 120 } |
| 121 m_cachedPairConversion->interpolateValue(m_currentFraction, m_cachedValu
e); |
109 } | 122 } |
110 m_cachedConversion->interpolateValue(m_currentFraction, m_cachedValue); | 123 m_isCached = true; |
111 return m_cachedValue.get(); | 124 return m_cachedValue.get(); |
112 } | 125 } |
113 | 126 |
114 void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s
tate) const | 127 void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s
tate) const |
115 { | 128 { |
116 if (!state.parentStyle()) | 129 if (!state.parentStyle()) |
117 return; | 130 return; |
118 if ((m_startKeyframe->value() && m_startKeyframe->value()->isInheritedValue(
)) | 131 if ((m_startKeyframe->value() && m_startKeyframe->value()->isInheritedValue(
)) |
119 || (m_endKeyframe->value() && m_endKeyframe->value()->isInheritedValue()
)) { | 132 || (m_endKeyframe->value() && m_endKeyframe->value()->isInheritedValue()
)) { |
120 state.parentStyle()->setHasExplicitlyInheritedProperties(); | 133 state.parentStyle()->setHasExplicitlyInheritedProperties(); |
121 } | 134 } |
122 } | 135 } |
123 | 136 |
124 double InvalidatableStyleInterpolation::underlyingFraction() const | 137 double InvalidatableStyleInterpolation::underlyingFraction() const |
125 { | 138 { |
126 return m_cachedConversion->interpolateUnderlyingFraction(m_startKeyframe->un
derlyingFraction(), m_endKeyframe->underlyingFraction(), m_currentFraction); | 139 if (m_currentFraction == 0) |
| 140 return m_startKeyframe->underlyingFraction(); |
| 141 if (m_currentFraction == 1) |
| 142 return m_endKeyframe->underlyingFraction(); |
| 143 return m_cachedPairConversion->interpolateUnderlyingFraction(m_startKeyframe
->underlyingFraction(), m_endKeyframe->underlyingFraction(), m_currentFraction); |
127 } | 144 } |
128 | 145 |
129 void InvalidatableStyleInterpolation::applyStack(const ActiveInterpolations& int
erpolations, StyleResolverState& state) | 146 void InvalidatableStyleInterpolation::applyStack(const ActiveInterpolations& int
erpolations, StyleResolverState& state) |
130 { | 147 { |
131 ASSERT(!interpolations.isEmpty()); | 148 ASSERT(!interpolations.isEmpty()); |
132 size_t startingIndex = 0; | 149 size_t startingIndex = 0; |
133 | 150 |
134 // Compute the underlying value to composite onto. | 151 // Compute the underlying value to composite onto. |
135 UnderlyingValue underlyingValue; | 152 UnderlyingValue underlyingValue; |
136 const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableS
tyleInterpolation(*interpolations.at(startingIndex)); | 153 const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableS
tyleInterpolation(*interpolations.at(startingIndex)); |
(...skipping 28 matching lines...) Expand all Loading... |
165 underlyingValue.set(currentValue); | 182 underlyingValue.set(currentValue); |
166 else | 183 else |
167 currentValue->type().composite(underlyingValue, underlyingFraction,
*currentValue); | 184 currentValue->type().composite(underlyingValue, underlyingFraction,
*currentValue); |
168 } | 185 } |
169 | 186 |
170 if (shouldApply && underlyingValue) | 187 if (shouldApply && underlyingValue) |
171 underlyingValue->type().apply(underlyingValue->interpolableValue(), unde
rlyingValue->nonInterpolableValue(), state); | 188 underlyingValue->type().apply(underlyingValue->interpolableValue(), unde
rlyingValue->nonInterpolableValue(), state); |
172 } | 189 } |
173 | 190 |
174 } // namespace blink | 191 } // namespace blink |
OLD | NEW |