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, UnderlyingValue()); | 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_isCachePending && 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 UnderlyingValue& underlyingValue) const | 27 PassOwnPtr<PairwisePrimitiveInterpolation> InvalidatableStyleInterpolation::mayb
eConvertPairwise(const StyleResolverState* state, const UnderlyingValue& underly
ingValue) 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, underlyingV
alue, m_conversionCheckers); | 33 OwnPtr<PairwisePrimitiveInterpolation> pairwiseConversion = interpolatio
nType->maybeConvertPairwise(*m_startKeyframe, *m_endKeyframe, state, underlyingV
alue, m_conversionCheckers); |
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 UnderlyingValue& underlyingValue) const | 40 PassOwnPtr<InterpolationValue> InvalidatableStyleInterpolation::convertSingleKey
frame(const CSSPropertySpecificKeyframe& keyframe, const StyleResolverState& sta
te, const UnderlyingValue& 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 UnderlyingValue conversionUnderlyingValue; | 45 UnderlyingValue conversionUnderlyingValue; |
55 if (underlyingValue && underlyingValue->type() == *interpolationType) | 46 if (underlyingValue && underlyingValue->type() == *interpolationType) |
56 conversionUnderlyingValue.set(underlyingValue.get()); | 47 conversionUnderlyingValue.set(underlyingValue.get()); |
(...skipping 20 matching lines...) Expand all Loading... |
77 bool InvalidatableStyleInterpolation::dependsOnUnderlyingValue() const | 68 bool InvalidatableStyleInterpolation::dependsOnUnderlyingValue() const |
78 { | 69 { |
79 return (m_startKeyframe->underlyingFraction() != 0 && m_currentFraction != 1
) || (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0); | 70 return (m_startKeyframe->underlyingFraction() != 0 && m_currentFraction != 1
) || (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0); |
80 } | 71 } |
81 | 72 |
82 bool InvalidatableStyleInterpolation::isNeutralKeyframeActive() const | 73 bool InvalidatableStyleInterpolation::isNeutralKeyframeActive() const |
83 { | 74 { |
84 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || (m_endKey
frame->isNeutral() && m_currentFraction != 0); | 75 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || (m_endKey
frame->isNeutral() && m_currentFraction != 0); |
85 } | 76 } |
86 | 77 |
| 78 void InvalidatableStyleInterpolation::clearCache() const |
| 79 { |
| 80 m_isCachePending = true; |
| 81 m_cachedPairConversion.clear(); |
| 82 m_conversionCheckers.clear(); |
| 83 m_cachedValue.clear(); |
| 84 } |
| 85 |
87 bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& sta
te, const UnderlyingValue& underlyingValue) const | 86 bool InvalidatableStyleInterpolation::isCacheValid(const StyleResolverState& sta
te, const UnderlyingValue& underlyingValue) const |
88 { | 87 { |
| 88 if (m_isCachePending) |
| 89 return false; |
89 if (isNeutralKeyframeActive()) { | 90 if (isNeutralKeyframeActive()) { |
90 if (m_cachedConversion->isFlip()) | 91 if (m_cachedPairConversion && m_cachedPairConversion->isFlip()) |
91 return false; | 92 return false; |
92 // Pairwise interpolation can never happen between different Interpolati
onTypes, neutral values always represent the underlying value. | 93 // Pairwise interpolation can never happen between different Interpolati
onTypes, neutral values always represent the underlying value. |
93 if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != under
lyingValue->type()) | 94 if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != under
lyingValue->type()) |
94 return false; | 95 return false; |
95 } | 96 } |
96 for (const auto& checker : m_conversionCheckers) { | 97 for (const auto& checker : m_conversionCheckers) { |
97 UnderlyingValue checkedUnderlyingValue; | 98 UnderlyingValue checkedUnderlyingValue; |
98 if (underlyingValue && underlyingValue->type() == checker->type()) | 99 if (underlyingValue && underlyingValue->type() == checker->type()) |
99 checkedUnderlyingValue.set(underlyingValue.get()); | 100 checkedUnderlyingValue.set(underlyingValue.get()); |
100 if (!checker->isValid(state, checkedUnderlyingValue)) | 101 if (!checker->isValid(state, checkedUnderlyingValue)) |
101 return false; | 102 return false; |
102 } | 103 } |
103 return true; | 104 return true; |
104 } | 105 } |
105 | 106 |
106 const InterpolationValue* InvalidatableStyleInterpolation::ensureValidInterpolat
ion(const StyleResolverState& state, const UnderlyingValue& underlyingValue) con
st | 107 const InterpolationValue* InvalidatableStyleInterpolation::ensureValidInterpolat
ion(const StyleResolverState& state, const UnderlyingValue& underlyingValue) con
st |
107 { | 108 { |
108 if (m_cachedConversion && isCacheValid(state, underlyingValue)) | 109 if (isCacheValid(state, underlyingValue)) |
109 return m_cachedValue.get(); | 110 return m_cachedValue.get(); |
110 m_conversionCheckers.clear(); | 111 clearCache(); |
111 if (!maybeCachePairwiseConversion(&state, underlyingValue)) { | 112 if (m_currentFraction == 0) { |
112 m_cachedConversion = FlipPrimitiveInterpolation::create( | 113 m_cachedValue = convertSingleKeyframe(*m_startKeyframe, state, underlyin
gValue); |
113 convertSingleKeyframe(*m_startKeyframe, state, underlyingValue), | 114 } else if (m_currentFraction == 1) { |
114 convertSingleKeyframe(*m_endKeyframe, state, underlyingValue)); | 115 m_cachedValue = convertSingleKeyframe(*m_endKeyframe, state, underlyingV
alue); |
| 116 } else { |
| 117 OwnPtr<PairwisePrimitiveInterpolation> pairwiseConversion = maybeConvert
Pairwise(&state, underlyingValue); |
| 118 if (pairwiseConversion) { |
| 119 m_cachedValue = pairwiseConversion->initialValue(); |
| 120 m_cachedPairConversion = pairwiseConversion.release(); |
| 121 } else { |
| 122 m_cachedPairConversion = FlipPrimitiveInterpolation::create( |
| 123 convertSingleKeyframe(*m_startKeyframe, state, underlyingValue), |
| 124 convertSingleKeyframe(*m_endKeyframe, state, underlyingValue)); |
| 125 } |
| 126 m_cachedPairConversion->interpolateValue(m_currentFraction, m_cachedValu
e); |
115 } | 127 } |
116 m_cachedConversion->interpolateValue(m_currentFraction, m_cachedValue); | 128 m_isCachePending = false; |
117 return m_cachedValue.get(); | 129 return m_cachedValue.get(); |
118 } | 130 } |
119 | 131 |
120 void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s
tate) const | 132 void InvalidatableStyleInterpolation::setFlagIfInheritUsed(StyleResolverState& s
tate) const |
121 { | 133 { |
122 if (!state.parentStyle()) | 134 if (!state.parentStyle()) |
123 return; | 135 return; |
124 if ((m_startKeyframe->value() && m_startKeyframe->value()->isInheritedValue(
)) | 136 if ((m_startKeyframe->value() && m_startKeyframe->value()->isInheritedValue(
)) |
125 || (m_endKeyframe->value() && m_endKeyframe->value()->isInheritedValue()
)) { | 137 || (m_endKeyframe->value() && m_endKeyframe->value()->isInheritedValue()
)) { |
126 state.parentStyle()->setHasExplicitlyInheritedProperties(); | 138 state.parentStyle()->setHasExplicitlyInheritedProperties(); |
127 } | 139 } |
128 } | 140 } |
129 | 141 |
130 double InvalidatableStyleInterpolation::underlyingFraction() const | 142 double InvalidatableStyleInterpolation::underlyingFraction() const |
131 { | 143 { |
132 return m_cachedConversion->interpolateUnderlyingFraction(m_startKeyframe->un
derlyingFraction(), m_endKeyframe->underlyingFraction(), m_currentFraction); | 144 if (m_currentFraction == 0) |
| 145 return m_startKeyframe->underlyingFraction(); |
| 146 if (m_currentFraction == 1) |
| 147 return m_endKeyframe->underlyingFraction(); |
| 148 return m_cachedPairConversion->interpolateUnderlyingFraction(m_startKeyframe
->underlyingFraction(), m_endKeyframe->underlyingFraction(), m_currentFraction); |
133 } | 149 } |
134 | 150 |
135 void InvalidatableStyleInterpolation::applyStack(const ActiveInterpolations& int
erpolations, StyleResolverState& state) | 151 void InvalidatableStyleInterpolation::applyStack(const ActiveInterpolations& int
erpolations, StyleResolverState& state) |
136 { | 152 { |
137 ASSERT(!interpolations.isEmpty()); | 153 ASSERT(!interpolations.isEmpty()); |
138 size_t startingIndex = 0; | 154 size_t startingIndex = 0; |
139 | 155 |
140 // Compute the underlying value to composite onto. | 156 // Compute the underlying value to composite onto. |
141 UnderlyingValue underlyingValue; | 157 UnderlyingValue underlyingValue; |
142 const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableS
tyleInterpolation(*interpolations.at(startingIndex)); | 158 const InvalidatableStyleInterpolation& firstInterpolation = toInvalidatableS
tyleInterpolation(*interpolations.at(startingIndex)); |
(...skipping 28 matching lines...) Expand all Loading... |
171 underlyingValue.set(currentValue); | 187 underlyingValue.set(currentValue); |
172 else | 188 else |
173 currentValue->type().composite(underlyingValue, underlyingFraction,
*currentValue); | 189 currentValue->type().composite(underlyingValue, underlyingFraction,
*currentValue); |
174 } | 190 } |
175 | 191 |
176 if (shouldApply && underlyingValue) | 192 if (shouldApply && underlyingValue) |
177 underlyingValue->type().apply(underlyingValue->interpolableValue(), unde
rlyingValue->nonInterpolableValue(), state); | 193 underlyingValue->type().apply(underlyingValue->interpolableValue(), unde
rlyingValue->nonInterpolableValue(), state); |
178 } | 194 } |
179 | 195 |
180 } // namespace blink | 196 } // namespace blink |
OLD | NEW |