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

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

Issue 2397113002: Move content up to KeyframeEffectReadOnly (Closed)
Patch Set: Created 4 years, 2 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/KeyframeEffectReadOnly.h" 5 #include "core/animation/KeyframeEffectReadOnly.h"
6 6
7 #include "bindings/core/v8/Dictionary.h" 7 #include "bindings/core/v8/Dictionary.h"
8 #include "bindings/core/v8/ExceptionState.h" 8 #include "bindings/core/v8/ExceptionState.h"
9 #include "core/animation/Animation.h"
10 #include "core/animation/CompositorAnimations.h"
9 #include "core/animation/EffectInput.h" 11 #include "core/animation/EffectInput.h"
12 #include "core/animation/ElementAnimations.h"
13 #include "core/animation/Interpolation.h"
10 #include "core/animation/KeyframeEffect.h" 14 #include "core/animation/KeyframeEffect.h"
11 #include "core/animation/KeyframeEffectOptions.h" 15 #include "core/animation/KeyframeEffectOptions.h"
16 #include "core/animation/PropertyHandle.h"
12 #include "core/animation/SampledEffect.h" 17 #include "core/animation/SampledEffect.h"
13 #include "core/animation/TimingInput.h" 18 #include "core/animation/TimingInput.h"
14 #include "core/dom/Element.h" 19 #include "core/dom/Element.h"
20 #include "core/dom/NodeComputedStyle.h"
15 #include "core/frame/UseCounter.h" 21 #include "core/frame/UseCounter.h"
22 #include "core/paint/PaintLayer.h"
23 #include "core/svg/SVGElement.h"
16 24
17 namespace blink { 25 namespace blink {
18 26
19 // Web Animations API Bindings constructors. We never actually want to create a 27 // Web Animations API Bindings constructors. We never actually want to create a
20 // KeyframeEffectReadOnly object, we just want to provide a read-only interface 28 // KeyframeEffectReadOnly object, we just want to provide a read-only interface
21 // to the KeyframeEffect object, so pass straight through to the subclass 29 // to the KeyframeEffect object, so pass straight through to the subclass
22 // factory methods. 30 // factory methods.
23 KeyframeEffectReadOnly* KeyframeEffectReadOnly::create( 31 KeyframeEffectReadOnly* KeyframeEffectReadOnly::create(
24 ExecutionContext* executionContext, 32 ExecutionContext* executionContext,
25 Element* element, 33 Element* element,
(...skipping 27 matching lines...) Expand all
53 EffectModel* model, 61 EffectModel* model,
54 const Timing& timing, 62 const Timing& timing,
55 Priority priority, 63 Priority priority,
56 EventDelegate* eventDelegate) 64 EventDelegate* eventDelegate)
57 : AnimationEffectReadOnly(timing, eventDelegate), 65 : AnimationEffectReadOnly(timing, eventDelegate),
58 m_target(target), 66 m_target(target),
59 m_model(model), 67 m_model(model),
60 m_sampledEffect(nullptr), 68 m_sampledEffect(nullptr),
61 m_priority(priority) {} 69 m_priority(priority) {}
62 70
71 void KeyframeEffectReadOnly::attach(Animation* animation) {
72 if (m_target) {
73 m_target->ensureElementAnimations().animations().add(animation);
74 m_target->setNeedsAnimationStyleRecalc();
75 if (RuntimeEnabledFeatures::webAnimationsSVGEnabled() &&
76 m_target->isSVGElement())
77 toSVGElement(m_target)->setWebAnimationsPending();
78 }
79 AnimationEffectReadOnly::attach(animation);
80 }
81
82 void KeyframeEffectReadOnly::detach() {
83 if (m_target)
84 m_target->elementAnimations()->animations().remove(animation());
85 if (m_sampledEffect)
86 clearEffects();
87 AnimationEffectReadOnly::detach();
88 }
89
90 void KeyframeEffectReadOnly::specifiedTimingChanged() {
91 if (animation()) {
92 // FIXME: Needs to consider groups when added.
93 DCHECK_EQ(animation()->effect(), this);
94 animation()->setCompositorPending(true);
95 }
96 }
97
98 static AnimationStack& ensureAnimationStack(Element* element) {
99 return element->ensureElementAnimations().animationStack();
100 }
101
102 bool KeyframeEffectReadOnly::hasMultipleTransformProperties() const {
103 if (!m_target->computedStyle())
104 return false;
105
106 unsigned transformPropertyCount = 0;
107 if (m_target->computedStyle()->hasTransformOperations())
108 transformPropertyCount++;
109 if (m_target->computedStyle()->rotate())
110 transformPropertyCount++;
111 if (m_target->computedStyle()->scale())
112 transformPropertyCount++;
113 if (m_target->computedStyle()->translate())
114 transformPropertyCount++;
115 return transformPropertyCount > 1;
116 }
117
118 // Returns true if transform, translate, rotate or scale is composited
119 // and a motion path or other transform properties
120 // has been introduced on the element
121 bool KeyframeEffectReadOnly::hasIncompatibleStyle() {
122 if (!m_target->computedStyle())
123 return false;
124
125 bool affectsTransform =
126 animation()->affects(*m_target, CSSPropertyTransform) ||
127 animation()->affects(*m_target, CSSPropertyScale) ||
128 animation()->affects(*m_target, CSSPropertyRotate) ||
129 animation()->affects(*m_target, CSSPropertyTranslate);
130
131 if (animation()->hasActiveAnimationsOnCompositor()) {
132 if (m_target->computedStyle()->hasOffset() && affectsTransform)
133 return true;
134 return hasMultipleTransformProperties();
135 }
136
137 return false;
138 }
139
140 void KeyframeEffectReadOnly::applyEffects() {
141 DCHECK(isInEffect());
142 DCHECK(animation());
143 if (!m_target || !m_model)
144 return;
145
146 if (hasIncompatibleStyle())
147 animation()->cancelAnimationOnCompositor();
148
149 double iteration = currentIteration();
150 DCHECK_GE(iteration, 0);
151 bool changed = false;
152 if (m_sampledEffect) {
153 changed = m_model->sample(clampTo<int>(iteration, 0), progress(),
154 iterationDuration(),
155 m_sampledEffect->mutableInterpolations());
156 } else {
157 Vector<RefPtr<Interpolation>> interpolations;
158 m_model->sample(clampTo<int>(iteration, 0), progress(), iterationDuration(),
159 interpolations);
160 if (!interpolations.isEmpty()) {
161 SampledEffect* sampledEffect = SampledEffect::create(this);
162 sampledEffect->mutableInterpolations().swap(interpolations);
163 m_sampledEffect = sampledEffect;
164 ensureAnimationStack(m_target).add(sampledEffect);
165 changed = true;
166 } else {
167 return;
168 }
169 }
170
171 if (changed) {
172 m_target->setNeedsAnimationStyleRecalc();
173 if (RuntimeEnabledFeatures::webAnimationsSVGEnabled() &&
174 m_target->isSVGElement())
175 toSVGElement(*m_target).setWebAnimationsPending();
176 }
177 }
178
179 void KeyframeEffectReadOnly::clearEffects() {
180 DCHECK(animation());
181 DCHECK(m_sampledEffect);
182
183 m_sampledEffect->clear();
184 m_sampledEffect = nullptr;
185 restartAnimationOnCompositor();
186 m_target->setNeedsAnimationStyleRecalc();
187 if (RuntimeEnabledFeatures::webAnimationsSVGEnabled() &&
188 m_target->isSVGElement())
189 toSVGElement(*m_target).clearWebAnimatedAttributes();
190 invalidate();
191 }
192
193 void KeyframeEffectReadOnly::updateChildrenAndEffects() const {
194 if (!m_model)
195 return;
196 DCHECK(animation());
197 if (isInEffect() && !animation()->effectSuppressed())
198 const_cast<KeyframeEffectReadOnly*>(this)->applyEffects();
199 else if (m_sampledEffect)
200 const_cast<KeyframeEffectReadOnly*>(this)->clearEffects();
201 }
202
203 double KeyframeEffectReadOnly::calculateTimeToEffectChange(
204 bool forwards,
205 double localTime,
206 double timeToNextIteration) const {
207 const double startTime = specifiedTiming().startDelay;
208 const double endTimeMinusEndDelay = startTime + activeDurationInternal();
209 const double endTime = endTimeMinusEndDelay + specifiedTiming().endDelay;
210 const double afterTime = std::min(endTimeMinusEndDelay, endTime);
211
212 switch (getPhase()) {
213 case PhaseNone:
214 return std::numeric_limits<double>::infinity();
215 case PhaseBefore:
216 DCHECK_GE(startTime, localTime);
217 return forwards ? startTime - localTime
218 : std::numeric_limits<double>::infinity();
219 case PhaseActive:
220 if (forwards) {
221 // Need service to apply fill / fire events.
222 const double timeToEnd = afterTime - localTime;
223 if (requiresIterationEvents()) {
224 return std::min(timeToEnd, timeToNextIteration);
225 }
226 return timeToEnd;
227 }
228 return 0;
229 case PhaseAfter:
230 DCHECK_GE(localTime, afterTime);
231 // If this KeyframeEffect is still in effect then it will need to update
232 // when its parent goes out of effect. We have no way of knowing when
233 // that will be, however, so the parent will need to supply it.
234 return forwards ? std::numeric_limits<double>::infinity()
235 : localTime - afterTime;
236 default:
237 NOTREACHED();
238 return std::numeric_limits<double>::infinity();
239 }
240 }
241
242 void KeyframeEffectReadOnly::notifySampledEffectRemovedFromAnimationStack() {
243 m_sampledEffect = nullptr;
244 }
245
246 bool KeyframeEffectReadOnly::isCandidateForAnimationOnCompositor(
247 double animationPlaybackRate) const {
248 // Do not put transforms on compositor if more than one of them are defined
249 // in computed style because they need to be explicitly ordered
250 if (!model() || !m_target ||
251 (m_target->computedStyle() && m_target->computedStyle()->hasOffset()) ||
252 hasMultipleTransformProperties())
253 return false;
254
255 return CompositorAnimations::isCandidateForAnimationOnCompositor(
256 specifiedTiming(), *m_target, animation(), *model(),
257 animationPlaybackRate);
258 }
259
260 bool KeyframeEffectReadOnly::maybeStartAnimationOnCompositor(
261 int group,
262 double startTime,
263 double currentTime,
264 double animationPlaybackRate) {
265 DCHECK(!hasActiveAnimationsOnCompositor());
266 if (!isCandidateForAnimationOnCompositor(animationPlaybackRate))
267 return false;
268 if (!CompositorAnimations::canStartAnimationOnCompositor(*m_target))
269 return false;
270 CompositorAnimations::startAnimationOnCompositor(
271 *m_target, group, startTime, currentTime, specifiedTiming(), *animation(),
272 *model(), m_compositorAnimationIds, animationPlaybackRate);
273 DCHECK(!m_compositorAnimationIds.isEmpty());
274 return true;
275 }
276
277 bool KeyframeEffectReadOnly::hasActiveAnimationsOnCompositor() const {
278 return !m_compositorAnimationIds.isEmpty();
279 }
280
281 bool KeyframeEffectReadOnly::hasActiveAnimationsOnCompositor(
282 CSSPropertyID property) const {
283 return hasActiveAnimationsOnCompositor() && affects(PropertyHandle(property));
284 }
285
286 bool KeyframeEffectReadOnly::affects(PropertyHandle property) const {
287 return m_model && m_model->affects(property);
288 }
289
290 bool KeyframeEffectReadOnly::cancelAnimationOnCompositor() {
291 // FIXME: cancelAnimationOnCompositor is called from withins style recalc.
292 // This queries compositingState, which is not necessarily up to date.
293 // https://code.google.com/p/chromium/issues/detail?id=339847
294 DisableCompositingQueryAsserts disabler;
295 if (!hasActiveAnimationsOnCompositor())
296 return false;
297 if (!m_target || !m_target->layoutObject())
298 return false;
299 DCHECK(animation());
300 for (const auto& compositorAnimationId : m_compositorAnimationIds) {
301 CompositorAnimations::cancelAnimationOnCompositor(*m_target, *animation(),
302 compositorAnimationId);
303 }
304 m_compositorAnimationIds.clear();
305 return true;
306 }
307
308 void KeyframeEffectReadOnly::restartAnimationOnCompositor() {
309 if (cancelAnimationOnCompositor())
310 animation()->setCompositorPending(true);
311 }
312
313 void KeyframeEffectReadOnly::cancelIncompatibleAnimationsOnCompositor() {
314 if (m_target && animation() && model()) {
315 CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(
316 *m_target, *animation(), *model());
317 }
318 }
319
320 void KeyframeEffectReadOnly::pauseAnimationForTestingOnCompositor(
321 double pauseTime) {
322 DCHECK(hasActiveAnimationsOnCompositor());
323 if (!m_target || !m_target->layoutObject())
324 return;
325 DCHECK(animation());
326 for (const auto& compositorAnimationId : m_compositorAnimationIds) {
327 CompositorAnimations::pauseAnimationForTestingOnCompositor(
328 *m_target, *animation(), compositorAnimationId, pauseTime);
329 }
330 }
331
332 void KeyframeEffectReadOnly::attachCompositedLayers() {
333 DCHECK(m_target);
334 DCHECK(animation());
335 CompositorAnimations::attachCompositedLayers(*m_target, *animation());
336 }
337
63 DEFINE_TRACE(KeyframeEffectReadOnly) { 338 DEFINE_TRACE(KeyframeEffectReadOnly) {
64 visitor->trace(m_target); 339 visitor->trace(m_target);
65 visitor->trace(m_model); 340 visitor->trace(m_model);
66 visitor->trace(m_sampledEffect); 341 visitor->trace(m_sampledEffect);
67 AnimationEffectReadOnly::trace(visitor); 342 AnimationEffectReadOnly::trace(visitor);
68 } 343 }
69 344
70 } // namespace blink 345 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698