Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: third_party/WebKit/Source/core/animation/InvalidatableInterpolation.cpp

Issue 2236193002: WIP: Implement CSS transitions on top of InterpolationTypes instead of AnimatableValues (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@_environmentStyle
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "core/animation/InvalidatableInterpolation.h"
6
7 #include "core/animation/InterpolationEnvironment.h"
8 #include "core/animation/StringKeyframe.h"
9 #include "core/css/resolver/StyleResolverState.h"
10 #include <memory>
11
12 namespace blink {
13
14 void InvalidatableInterpolation::interpolate(int, double fraction)
15 {
16 if (fraction == m_currentFraction)
17 return;
18
19 if (m_currentFraction == 0 || m_currentFraction == 1 || fraction == 0 || fra ction == 1)
20 clearCache();
21
22 m_currentFraction = fraction;
23 if (m_isCached && m_cachedPairConversion)
24 m_cachedPairConversion->interpolateValue(fraction, m_cachedValue);
25 // We defer the interpolation to ensureValidInterpolation() if m_cachedPairC onversion is null.
26 }
27
28 std::unique_ptr<PairwisePrimitiveInterpolation> InvalidatableInterpolation::mayb eConvertPairwise(const InterpolationEnvironment& environment, const UnderlyingVa lueOwner& underlyingValueOwner) const
29 {
30 ASSERT(m_currentFraction != 0 && m_currentFraction != 1);
31 for (const auto& interpolationType : m_interpolationTypes) {
32 if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) && (!un derlyingValueOwner || underlyingValueOwner.type() != *interpolationType))
33 continue;
34 ConversionCheckers conversionCheckers;
35 PairwiseInterpolationValue result = interpolationType->maybeConvertPairw ise(*m_startKeyframe, *m_endKeyframe, environment, underlyingValueOwner.value(), conversionCheckers);
36 addConversionCheckers(*interpolationType, conversionCheckers);
37 if (result) {
38 return PairwisePrimitiveInterpolation::create(*interpolationType,
39 std::move(result.startInterpolableValue),
40 std::move(result.endInterpolableValue),
41 result.nonInterpolableValue.release());
42 }
43 }
44 return nullptr;
45 }
46
47 std::unique_ptr<TypedInterpolationValue> InvalidatableInterpolation::convertSing leKeyframe(const PropertySpecificKeyframe& keyframe, const InterpolationEnvironm ent& environment, const UnderlyingValueOwner& underlyingValueOwner) const
48 {
49 if (keyframe.isNeutral() && !underlyingValueOwner)
50 return nullptr;
51 for (const auto& interpolationType : m_interpolationTypes) {
52 if (keyframe.isNeutral() && underlyingValueOwner.type() != *interpolatio nType)
53 continue;
54 ConversionCheckers conversionCheckers;
55 InterpolationValue result = interpolationType->maybeConvertSingle(keyfra me, environment, underlyingValueOwner.value(), conversionCheckers);
56 addConversionCheckers(*interpolationType, conversionCheckers);
57 if (result)
58 return TypedInterpolationValue::create(*interpolationType, std::move (result.interpolableValue), result.nonInterpolableValue.release());
59 }
60 ASSERT(keyframe.isNeutral());
61 return nullptr;
62 }
63
64 void InvalidatableInterpolation::addConversionCheckers(const InterpolationType& type, ConversionCheckers& conversionCheckers) const
65 {
66 for (size_t i = 0; i < conversionCheckers.size(); i++) {
67 conversionCheckers[i]->setType(type);
68 m_conversionCheckers.append(std::move(conversionCheckers[i]));
69 }
70 }
71
72 std::unique_ptr<TypedInterpolationValue> InvalidatableInterpolation::maybeConver tUnderlyingValue(const InterpolationEnvironment& environment) const
73 {
74 for (const auto& interpolationType : m_interpolationTypes) {
75 InterpolationValue result = interpolationType->maybeConvertUnderlyingVal ue(environment);
76 if (result)
77 return TypedInterpolationValue::create(*interpolationType, std::move (result.interpolableValue), result.nonInterpolableValue.release());
78 }
79 return nullptr;
80 }
81
82 bool InvalidatableInterpolation::dependsOnUnderlyingValue() const
83 {
84 return (m_startKeyframe->underlyingFraction() != 0 && m_currentFraction != 1 ) || (m_endKeyframe->underlyingFraction() != 0 && m_currentFraction != 0);
85 }
86
87 bool InvalidatableInterpolation::isNeutralKeyframeActive() const
88 {
89 return (m_startKeyframe->isNeutral() && m_currentFraction != 1) || (m_endKey frame->isNeutral() && m_currentFraction != 0);
90 }
91
92 void InvalidatableInterpolation::clearCache() const
93 {
94 m_isCached = false;
95 m_cachedPairConversion.reset();
96 m_conversionCheckers.clear();
97 m_cachedValue.reset();
98 }
99
100 bool InvalidatableInterpolation::isCacheValid(const InterpolationEnvironment& en vironment, const UnderlyingValueOwner& underlyingValueOwner) const
101 {
102 if (!m_isCached)
103 return false;
104 if (isNeutralKeyframeActive()) {
105 if (m_cachedPairConversion && m_cachedPairConversion->isFlip())
106 return false;
107 // Pairwise interpolation can never happen between different Interpolati onTypes, neutral values always represent the underlying value.
108 if (!underlyingValueOwner || !m_cachedValue || m_cachedValue->type() != underlyingValueOwner.type())
109 return false;
110 }
111 for (const auto& checker : m_conversionCheckers) {
112 if (!checker->isValid(environment, underlyingValueOwner.value()))
113 return false;
114 }
115 return true;
116 }
117
118 const TypedInterpolationValue* InvalidatableInterpolation::ensureValidInterpolat ion(const InterpolationEnvironment& environment, const UnderlyingValueOwner& und erlyingValueOwner) const
119 {
120 ASSERT(!std::isnan(m_currentFraction));
121 if (isCacheValid(environment, underlyingValueOwner))
122 return m_cachedValue.get();
123 clearCache();
124 if (m_currentFraction == 0) {
125 m_cachedValue = convertSingleKeyframe(*m_startKeyframe, environment, und erlyingValueOwner);
126 } else if (m_currentFraction == 1) {
127 m_cachedValue = convertSingleKeyframe(*m_endKeyframe, environment, under lyingValueOwner);
128 } else {
129 std::unique_ptr<PairwisePrimitiveInterpolation> pairwiseConversion = may beConvertPairwise(environment, underlyingValueOwner);
130 if (pairwiseConversion) {
131 m_cachedValue = pairwiseConversion->initialValue();
132 m_cachedPairConversion = std::move(pairwiseConversion);
133 } else {
134 m_cachedPairConversion = FlipPrimitiveInterpolation::create(
135 convertSingleKeyframe(*m_startKeyframe, environment, underlyingV alueOwner),
136 convertSingleKeyframe(*m_endKeyframe, environment, underlyingVal ueOwner));
137 }
138 m_cachedPairConversion->interpolateValue(m_currentFraction, m_cachedValu e);
139 }
140 m_isCached = true;
141 return m_cachedValue.get();
142 }
143
144 void InvalidatableInterpolation::setFlagIfInheritUsed(InterpolationEnvironment& environment) const
145 {
146 if (!m_property.isCSSProperty() && !m_property.isPresentationAttribute())
147 return;
148 if (!environment.state().parentStyle())
149 return;
150 const CSSValue* startValue = toCSSPropertySpecificKeyframe(*m_startKeyframe) .value();
151 const CSSValue* endValue = toCSSPropertySpecificKeyframe(*m_endKeyframe).val ue();
152 if ((startValue && startValue->isInheritedValue())
153 || (endValue && endValue->isInheritedValue())) {
154 environment.state().parentStyle()->setHasExplicitlyInheritedProperties() ;
155 }
156 }
157
158 double InvalidatableInterpolation::underlyingFraction() const
159 {
160 if (m_currentFraction == 0)
161 return m_startKeyframe->underlyingFraction();
162 if (m_currentFraction == 1)
163 return m_endKeyframe->underlyingFraction();
164 return m_cachedPairConversion->interpolateUnderlyingFraction(m_startKeyframe ->underlyingFraction(), m_endKeyframe->underlyingFraction(), m_currentFraction);
165 }
166
167 void InvalidatableInterpolation::applyStack(const ActiveInterpolations& interpol ations, InterpolationEnvironment& environment)
168 {
169 ASSERT(!interpolations.isEmpty());
170 size_t startingIndex = 0;
171
172 // Compute the underlying value to composite onto.
173 UnderlyingValueOwner underlyingValueOwner;
174 const InvalidatableInterpolation& firstInterpolation = toInvalidatableInterp olation(*interpolations.at(startingIndex));
175 if (firstInterpolation.dependsOnUnderlyingValue()) {
176 underlyingValueOwner.set(firstInterpolation.maybeConvertUnderlyingValue( environment));
177 } else {
178 const TypedInterpolationValue* firstValue = firstInterpolation.ensureVal idInterpolation(environment, underlyingValueOwner);
179 // Fast path for replace interpolations that are the only one to apply.
180 if (interpolations.size() == 1) {
181 if (firstValue) {
182 firstInterpolation.setFlagIfInheritUsed(environment);
183 firstValue->type().apply(firstValue->interpolableValue(), firstV alue->getNonInterpolableValue(), environment);
184 }
185 return;
186 }
187 underlyingValueOwner.set(firstValue);
188 startingIndex++;
189 }
190
191 // Composite interpolations onto the underlying value.
192 bool shouldApply = false;
193 for (size_t i = startingIndex; i < interpolations.size(); i++) {
194 const InvalidatableInterpolation& currentInterpolation = toInvalidatable Interpolation(*interpolations.at(i));
195 ASSERT(currentInterpolation.dependsOnUnderlyingValue());
196 const TypedInterpolationValue* currentValue = currentInterpolation.ensur eValidInterpolation(environment, underlyingValueOwner);
197 if (!currentValue)
198 continue;
199 shouldApply = true;
200 currentInterpolation.setFlagIfInheritUsed(environment);
201 double underlyingFraction = currentInterpolation.underlyingFraction();
202 if (underlyingFraction == 0 || !underlyingValueOwner || underlyingValueO wner.type() != currentValue->type())
203 underlyingValueOwner.set(currentValue);
204 else
205 currentValue->type().composite(underlyingValueOwner, underlyingFract ion, currentValue->value(), currentInterpolation.m_currentFraction);
206 }
207
208 if (shouldApply && underlyingValueOwner)
209 underlyingValueOwner.type().apply(*underlyingValueOwner.value().interpol ableValue, underlyingValueOwner.value().nonInterpolableValue.get(), environment) ;
210 }
211
212 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698