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

Side by Side Diff: Source/core/animation/css/CSSAnimations.cpp

Issue 26382004: Web Animations CSS: Implement CSS Transitions backed on Web Animations model (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: fix logic for elapsedTime in event Created 7 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 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/animation/css/CSSAnimations.h" 32 #include "core/animation/css/CSSAnimations.h"
33 33
34 #include "StylePropertyShorthand.h"
34 #include "core/animation/ActiveAnimations.h" 35 #include "core/animation/ActiveAnimations.h"
35 #include "core/animation/DocumentTimeline.h" 36 #include "core/animation/DocumentTimeline.h"
36 #include "core/animation/KeyframeAnimationEffect.h" 37 #include "core/animation/KeyframeAnimationEffect.h"
38 #include "core/animation/css/CSSAnimatableValueFactory.h"
37 #include "core/css/CSSKeyframeRule.h" 39 #include "core/css/CSSKeyframeRule.h"
38 #include "core/css/resolver/StyleResolver.h" 40 #include "core/css/resolver/StyleResolver.h"
39 #include "core/dom/Element.h" 41 #include "core/dom/Element.h"
40 #include "core/events/EventNames.h" 42 #include "core/events/EventNames.h"
43 #include "core/events/TransitionEvent.h"
41 #include "core/events/WebKitAnimationEvent.h" 44 #include "core/events/WebKitAnimationEvent.h"
45 // FIXME: Remove this once all properties are supported
46 #include "core/page/animation/CSSPropertyAnimation.h"
42 #include "core/platform/animation/CSSAnimationDataList.h" 47 #include "core/platform/animation/CSSAnimationDataList.h"
43 #include "core/platform/animation/TimingFunction.h" 48 #include "core/platform/animation/TimingFunction.h"
44 #include "wtf/HashSet.h" 49 #include "wtf/HashSet.h"
45 50
46 namespace { 51 namespace {
47 52
48 using namespace WebCore; 53 using namespace WebCore;
49 54
50 bool isEarlierPhase(TimedItem::Phase target, TimedItem::Phase reference) 55 bool isEarlierPhase(TimedItem::Phase target, TimedItem::Phase reference)
51 { 56 {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 CSSAnimationUpdateScope::~CSSAnimationUpdateScope() 141 CSSAnimationUpdateScope::~CSSAnimationUpdateScope()
137 { 142 {
138 if (!m_target) 143 if (!m_target)
139 return; 144 return;
140 ActiveAnimations* activeAnimations = m_target->activeAnimations(); 145 ActiveAnimations* activeAnimations = m_target->activeAnimations();
141 CSSAnimations* cssAnimations = activeAnimations ? activeAnimations->cssAnima tions() : 0; 146 CSSAnimations* cssAnimations = activeAnimations ? activeAnimations->cssAnima tions() : 0;
142 if (cssAnimations) 147 if (cssAnimations)
143 cssAnimations->maybeApplyPendingUpdate(m_target); 148 cssAnimations->maybeApplyPendingUpdate(m_target);
144 } 149 }
145 150
146 bool CSSAnimations::needsUpdate(const Element* element, const RenderStyle* style ) 151 PassOwnPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const RenderStyle* style, StyleResolver* resolver)
152 {
153 ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
154 OwnPtr<CSSAnimationUpdate> update = adoptPtr(new CSSAnimationUpdate());
155 updateAnimationUpdate(update.get(), element, style, resolver);
dstockwell 2013/10/08 21:02:59 I think calculateAnimationUpdate and calculateTran
Timothy Loh 2013/10/09 01:33:07 Done.
156 updateTransitionUpdate(update.get(), element, style);
157 return update->isEmpty() ? nullptr : update.release();
158 }
159
160 void CSSAnimations::updateAnimationUpdate(CSSAnimationUpdate* update, Element* e lement, const RenderStyle* style, StyleResolver* resolver)
147 { 161 {
148 ActiveAnimations* activeAnimations = element->activeAnimations(); 162 ActiveAnimations* activeAnimations = element->activeAnimations();
149 const CSSAnimationDataList* animations = style->animations(); 163 const CSSAnimationDataList* animationDataList = style->animations();
150 const CSSAnimations* cssAnimations = activeAnimations ? activeAnimations->cs sAnimations() : 0; 164 const CSSAnimations* cssAnimations = activeAnimations ? activeAnimations->cs sAnimations() : 0;
151 EDisplay display = style->display();
152 return (display != NONE && animations && animations->size()) || (cssAnimatio ns && !cssAnimations->isEmpty());
dstockwell 2013/10/08 21:02:59 where did this display != NONE check go?
Timothy Loh 2013/10/09 01:33:07 Looks redundant - if display is none and cssAnimat
153 }
154 165
155 PassOwnPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const RenderStyle* style, const CSSAnimations* cssAnimations, const CSSAnimation DataList* animationDataList, StyleResolver* resolver)
156 {
157 OwnPtr<CSSAnimationUpdate> update;
158 HashSet<AtomicString> inactive; 166 HashSet<AtomicString> inactive;
159 if (cssAnimations) 167 if (cssAnimations)
160 for (AnimationMap::const_iterator iter = cssAnimations->m_animations.beg in(); iter != cssAnimations->m_animations.end(); ++iter) 168 for (AnimationMap::const_iterator iter = cssAnimations->m_animations.beg in(); iter != cssAnimations->m_animations.end(); ++iter)
161 inactive.add(iter->key); 169 inactive.add(iter->key);
162 170
163 if (style->display() != NONE) { 171 if (style->display() != NONE) {
164 for (size_t i = 0; animationDataList && i < animationDataList->size(); + +i) { 172 for (size_t i = 0; animationDataList && i < animationDataList->size(); + +i) {
165 const CSSAnimationData* animationData = animationDataList->animation (i); 173 const CSSAnimationData* animationData = animationDataList->animation (i);
166 if (animationData->isNoneAnimation()) 174 if (animationData->isNoneAnimation())
167 continue; 175 continue;
168 ASSERT(animationData->isValidAnimation()); 176 ASSERT(animationData->isValidAnimation());
169 AtomicString animationName(animationData->name()); 177 AtomicString animationName(animationData->name());
170 178
171 if (cssAnimations) { 179 if (cssAnimations) {
172 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName)); 180 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName));
173 if (existing != cssAnimations->m_animations.end()) { 181 if (existing != cssAnimations->m_animations.end()) {
174 // FIXME: The play-state of this animation might have change d, record the change in the update. 182 // FIXME: The play-state of this animation might have change d, record the change in the update.
175 inactive.remove(animationName); 183 inactive.remove(animationName);
176 continue; 184 continue;
177 } 185 }
178 } 186 }
179 187
180 Timing timing; 188 Timing timing;
181 RefPtr<TimingFunction> defaultTimingFunction = timingFromAnimationDa ta(animationData, timing); 189 RefPtr<TimingFunction> defaultTimingFunction = timingFromAnimationDa ta(animationData, timing);
182 Vector<std::pair<KeyframeAnimationEffect::KeyframeVector, RefPtr<Tim ingFunction> > > keyframesAndTimingFunctions; 190 Vector<std::pair<KeyframeAnimationEffect::KeyframeVector, RefPtr<Tim ingFunction> > > keyframesAndTimingFunctions;
183 resolver->resolveKeyframes(element, style, animationName, defaultTim ingFunction.get(), keyframesAndTimingFunctions); 191 resolver->resolveKeyframes(element, style, animationName, defaultTim ingFunction.get(), keyframesAndTimingFunctions);
184 if (!keyframesAndTimingFunctions.isEmpty()) { 192 if (!keyframesAndTimingFunctions.isEmpty()) {
185 if (!update)
186 update = adoptPtr(new CSSAnimationUpdate());
187 HashSet<RefPtr<InertAnimation> > animations; 193 HashSet<RefPtr<InertAnimation> > animations;
188 for (size_t j = 0; j < keyframesAndTimingFunctions.size(); ++j) { 194 for (size_t j = 0; j < keyframesAndTimingFunctions.size(); ++j) {
189 ASSERT(!keyframesAndTimingFunctions[j].first.isEmpty()); 195 ASSERT(!keyframesAndTimingFunctions[j].first.isEmpty());
190 timing.timingFunction = keyframesAndTimingFunctions[j].secon d; 196 timing.timingFunction = keyframesAndTimingFunctions[j].secon d;
191 // FIXME: crbug.com/268791 - Keyframes are already normalize d, perhaps there should be a flag on KeyframeAnimationEffect to skip normalizati on. 197 // FIXME: crbug.com/268791 - Keyframes are already normalize d, perhaps there should be a flag on KeyframeAnimationEffect to skip normalizati on.
192 animations.add(InertAnimation::create(KeyframeAnimationEffec t::create(keyframesAndTimingFunctions[j].first), timing)); 198 animations.add(InertAnimation::create(KeyframeAnimationEffec t::create(keyframesAndTimingFunctions[j].first), timing));
193 } 199 }
194 update->startAnimation(animationName, animations); 200 update->startAnimation(animationName, animations);
195 } 201 }
196 } 202 }
197 } 203 }
198 204
199 if (!inactive.isEmpty() && !update)
200 update = adoptPtr(new CSSAnimationUpdate());
201 for (HashSet<AtomicString>::const_iterator iter = inactive.begin(); iter != inactive.end(); ++iter) 205 for (HashSet<AtomicString>::const_iterator iter = inactive.begin(); iter != inactive.end(); ++iter)
202 update->cancelAnimation(*iter, cssAnimations->m_animations.get(*iter)); 206 update->cancelAnimation(*iter, cssAnimations->m_animations.get(*iter));
203
204 return update.release();
205 } 207 }
206 208
207 void CSSAnimations::maybeApplyPendingUpdate(Element* element) 209 void CSSAnimations::maybeApplyPendingUpdate(Element* element)
208 { 210 {
209 if (!element->renderer()) 211 if (!element->renderer())
210 m_pendingUpdate = nullptr; 212 m_pendingUpdate = nullptr;
211 213
212 if (!m_pendingUpdate) 214 if (!m_pendingUpdate)
213 return; 215 return;
214 216
215 OwnPtr<CSSAnimationUpdate> update = m_pendingUpdate.release(); 217 OwnPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();
216 218
217 for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationN ames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) { 219 for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationN ames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) {
218 const HashSet<RefPtr<Player> >& players = m_animations.take(*iter); 220 const HashSet<RefPtr<Player> >& players = m_animations.take(*iter);
219 for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); it er != players.end(); ++iter) 221 for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); it er != players.end(); ++iter)
220 (*iter)->cancel(); 222 (*iter)->cancel();
221 } 223 }
222 224
223 // FIXME: Apply updates to play-state. 225 // FIXME: Apply updates to play-state.
224 226
225 for (Vector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update- >newAnimations().begin(); iter != update->newAnimations().end(); ++iter) { 227 for (Vector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update- >newAnimations().begin(); iter != update->newAnimations().end(); ++iter) {
226 OwnPtr<CSSAnimations::EventDelegate> eventDelegate = adoptPtr(new EventD elegate(element, iter->name)); 228 OwnPtr<AnimationEventDelegate> eventDelegate = adoptPtr(new AnimationEve ntDelegate(element, iter->name));
227 HashSet<RefPtr<Player> > players; 229 HashSet<RefPtr<Player> > players;
228 for (HashSet<RefPtr<InertAnimation> >::const_iterator animationsIter = i ter->animations.begin(); animationsIter != iter->animations.end(); ++animationsI ter) { 230 for (HashSet<RefPtr<InertAnimation> >::const_iterator animationsIter = i ter->animations.begin(); animationsIter != iter->animations.end(); ++animationsI ter) {
229 const InertAnimation* inertAnimation = animationsIter->get(); 231 const InertAnimation* inertAnimation = animationsIter->get();
230 // The event delegate is set on the the first animation only. We 232 // The event delegate is set on the the first animation only. We
231 // rely on the behavior of OwnPtr::release() to achieve this. 233 // rely on the behavior of OwnPtr::release() to achieve this.
232 RefPtr<Animation> animation = Animation::create(element, inertAnimat ion->effect(), inertAnimation->specified(), eventDelegate.release()); 234 RefPtr<Animation> animation = Animation::create(element, inertAnimat ion->effect(), inertAnimation->specified(), eventDelegate.release());
233 players.add(element->document().timeline()->play(animation.get())); 235 players.add(element->document().timeline()->play(animation.get()));
234 } 236 }
235 m_animations.set(iter->name, players); 237 m_animations.set(iter->name, players);
236 } 238 }
239
240 Vector<CSSPropertyID> removedTransitions;
241 for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transit ions.end(); ++iter) {
dstockwell 2013/10/08 21:02:59 Why are we iterating over the transition map rathe
Timothy Loh 2013/10/09 01:33:07 Because I'm silly :(
242 Player* player = iter->value.get();
243 CSSPropertyID id = iter->key;
244 if (update->endedTransitions().contains(id)) {
245 player->cancel();
246 removedTransitions.append(id);
247 }
248 }
249 for (int i = 0; i < removedTransitions.size(); ++i)
dstockwell 2013/10/08 21:02:59 Should this be size_t?
Timothy Loh 2013/10/09 01:33:07 Loop removed (changed to loop over cancelled trans
250 m_transitions.remove(removedTransitions[i]);
Steve Block 2013/10/09 00:57:12 Why do you use two passes to remove the cancelled
Timothy Loh 2013/10/09 01:33:07 Doug had the same comment. Fixed.
251
252 HashMap<CSSPropertyID, RefPtr<InertAnimation> >::const_iterator iter;
253 for (iter = update->newTransitions().begin(); iter != update->newTransitions ().end(); ++iter) {
254 CSSPropertyID id = iter->key;
255 OwnPtr<TransitionEventDelegate> eventDelegate = adoptPtr(new TransitionE ventDelegate(element, id));
256 RefPtr<Animation> transition = Animation::create(element, iter->value->e ffect(), iter->value->specified(), eventDelegate.release());
257 // FIXME: We'll probably want a separate DocumentTimeline for transition s, or
258 // at least to not have transitions also added to the default AnimationS tack.
259 Player* player = element->document().timeline()->play(transition.get()). get();
260 m_transitions.set(id, player);
261 }
262 }
263
264 namespace {
Steve Block 2013/10/09 00:57:12 You should merge this with the anonymous namespace
Timothy Loh 2013/10/09 07:39:23 Done. Also moved the existing function timingFromA
265
266 struct TransitionDetails {
267 TransitionDetails(PassRefPtr<AnimatableValue> from, PassRefPtr<AnimatableVal ue> to, const CSSAnimationData* anim)
268 : from(from), to(to), anim(anim)
dstockwell 2013/10/08 21:02:59 place to and anim on separate lines for consistenc
Timothy Loh 2013/10/09 01:33:07 Done.
269 {
270 }
271 TransitionDetails() { } // The HashMap calls the default ctor
272 RefPtr<AnimatableValue> from;
273 RefPtr<AnimatableValue> to;
274 const CSSAnimationData* anim;
275 };
276 typedef HashMap<CSSPropertyID, TransitionDetails> StyleChange;
277
278 void updateIfPropertyChanged(const CSSAnimationData* anim, CSSPropertyID id, con st RenderStyle* oldStyle, const RenderStyle* newStyle, StyleChange& styleChange)
279 {
280 RefPtr<AnimatableValue> from = CSSAnimatableValueFactory::create(id, oldStyl e);
dstockwell 2013/10/08 21:02:59 If there's already a transition running on this pr
281 RefPtr<AnimatableValue> to = CSSAnimatableValueFactory::create(id, newStyle) ;
282 // If we have multiple transitions on the same property, we will use the
283 // last one since we iterate over them in order and this will override
284 // a previously set TransitionDetails.
285 if (!from->equals(to.get()))
286 styleChange.add(id, TransitionDetails(from, to, anim));
287 }
288
289 void computeStyleChange(const RenderStyle* oldStyle, const RenderStyle* newStyle , StyleChange& styleChange, HashSet<CSSPropertyID>& listedProperties)
290 {
291 if (!newStyle->transitions())
292 return;
293
294 for (size_t i = 0; i < newStyle->transitions()->size(); ++i) {
295 const CSSAnimationData* anim = newStyle->transitions()->animation(i);
296 CSSAnimationData::AnimationMode mode = anim->animationMode();
297 if (anim->duration() + anim->delay() <= 0 || mode == CSSAnimationData::A nimateNone)
298 continue;
299
300 if (mode == CSSAnimationData::AnimateAll) {
301 const Vector<CSSPropertyID>& animatableProperties = CSSAnimations::a nimatableProperties();
302 for (unsigned i = 0; i < animatableProperties.size(); ++i) {
303 CSSPropertyID id = animatableProperties[i];
304 listedProperties.add(id);
305 // FIXME: We haven't yet added support for all animatable proper ties,
306 // so this check lets us transition 'all' without failing to pul l
307 // values out of the RenderStyles.
308 if (CSSPropertyAnimation::propertiesEqual(id, oldStyle, newStyle ))
dstockwell 2013/10/08 21:02:59 Could we just skip over the specific properties th
Steve Block 2013/10/09 00:57:12 I don't see how testing for equality means we skip
Timothy Loh 2013/10/09 01:33:07 Not sure what you mean here. The check is just so
Timothy Loh 2013/10/09 07:39:23 OK. Will take this out for now. This takes it from
309 continue;
310 updateIfPropertyChanged(anim, id, oldStyle, newStyle, styleChang e);
311 }
312 continue;
313 }
314
dstockwell 2013/10/08 21:02:59 ASSERT mode == AnimateSingleProperty
Timothy Loh 2013/10/09 01:33:07 Done.
315 const StylePropertyShorthand& propertyList = shorthandForProperty(anim-> property());
316 if (!propertyList.length()) {
317 listedProperties.add(anim->property());
318 updateIfPropertyChanged(anim, anim->property(), oldStyle, newStyle, styleChange);
319 } else {
320 for (unsigned i = 0; i < propertyList.length(); ++i) {
321 CSSPropertyID id = propertyList.properties()[i];
322 if (!CSSAnimations::isAnimatableProperty(id))
323 continue;
324 listedProperties.add(id);
325 updateIfPropertyChanged(anim, id, oldStyle, newStyle, styleChang e);
Steve Block 2013/10/09 00:57:12 Can you merge this block with the AnimateAll case
Timothy Loh 2013/10/09 07:39:23 OK, I changed animatableProperties to return a con
326 }
327 }
328 }
329 }
330
331 } // namespace
332
333 void CSSAnimations::updateTransitionUpdate(CSSAnimationUpdate* update, CSSProper tyID id, const AnimatableValue* from, const AnimatableValue* to, const CSSAnimat ionData* anim, const TransitionMap* transitions)
dstockwell 2013/10/08 21:02:59 calculateTransitionUpdateForProperty
Timothy Loh 2013/10/09 01:33:07 Done.
334 {
335 // FIXME: Skip the rest of this if there is a running animation on this prop erty
336
337 Timing timing;
338 RefPtr<TimingFunction> timingFunction = timingFromAnimationData(anim, timing );
339 timing.timingFunction = timingFunction;
340 timing.fillMode = Timing::FillModeBoth;
341
342 if (transitions) {
343 TransitionMap::const_iterator existingTransitionIter = transitions->find (id);
344
345 if (existingTransitionIter != transitions->end() && !update->endedTransi tions().contains(id)) {
346 const Animation* animation = static_cast<const Animation*>(existingT ransitionIter->value->source());
dstockwell 2013/10/08 21:02:59 I don't like reaching in here to pull out the targ
Steve Block 2013/10/09 00:57:12 Agreed
Timothy Loh 2013/10/09 07:39:23 OK. Plumbing these explicitly through now. Also ch
347 const KeyframeAnimationEffect* existingEffect = static_cast<const Ke yframeAnimationEffect*>(animation->effect());
348
349 ASSERT(existingEffect->getFrames().size() == 2);
350 const AnimatableValue* existingTo = existingEffect->getFrames()[1]-> propertyValue(id);
351
352 if (existingTo->equals(to))
353 return;
354 update->endTransition(id);
355 }
356 }
357
358 KeyframeAnimationEffect::KeyframeVector keyframes;
359
360 RefPtr<Keyframe> startKeyframe = Keyframe::create();
361 startKeyframe->setPropertyValue(id, from);
362 startKeyframe->setOffset(0);
363 keyframes.append(startKeyframe);
364
365 RefPtr<Keyframe> endKeyframe = Keyframe::create();
366 endKeyframe->setPropertyValue(id, to);
367 endKeyframe->setOffset(1);
368 keyframes.append(endKeyframe);
369
370 RefPtr<KeyframeAnimationEffect> effect = KeyframeAnimationEffect::create(key frames);
371
372 update->startTransition(id, InertAnimation::create(effect, timing));
373 }
374
375 void CSSAnimations::updateTransitionUpdate(CSSAnimationUpdate* update, const Ele ment* element, const RenderStyle* style)
376 {
377 ActiveAnimations* activeAnimations = element->activeAnimations();
378 const CSSAnimations* cssAnimations = activeAnimations ? activeAnimations->cs sAnimations() : 0;
379 const TransitionMap* transitions = cssAnimations ? &cssAnimations->m_transit ions : 0;
380
381 HashSet<CSSPropertyID> listedProperties;
382 if (style->display() != NONE && element->renderer() && element->renderer()-> style()) {
dstockwell 2013/10/08 21:02:59 if display is none, there's should be nothing to d
Timothy Loh 2013/10/09 01:33:07 For animations, it looks like we'll set all the ru
383 StyleChange styleChange;
384 computeStyleChange(element->renderer()->style(), style, styleChange, lis tedProperties);
385 for (StyleChange::const_iterator iter = styleChange.begin(); iter != sty leChange.end(); ++iter) {
386 CSSPropertyID id = iter->key;
387 AnimatableValue* from = iter->value.from.get();
388 AnimatableValue* to = iter->value.to.get();
389 const CSSAnimationData* anim = iter->value.anim;
390 updateTransitionUpdate(update, id, from, to, anim, transitions);
391 }
392 }
393
394 if (transitions) {
395 for (TransitionMap::const_iterator iter = transitions->begin(); iter != transitions->end(); ++iter) {
396 const TimedItem* timedItem = iter->value->source();
397 bool isReversed = timedItem->specified().playbackRate < 0;
dstockwell 2013/10/08 21:02:59 Reversing doesn't seem to be implemented, can we r
Timothy Loh 2013/10/09 01:33:07 Whoops, I pulled most of it out for a separate pat
398 TimedItem::Phase end = isReversed ? TimedItem::PhaseBefore : TimedIt em::PhaseAfter;
399 if (timedItem->phase() == end || !listedProperties.contains(iter->ke y))
400 update->endTransition(iter->key);
401 }
402 }
403 }
404
405
406 AnimationEffect::CompositableValueMap CSSAnimations::compositableValuesForTransi tions(const CSSAnimations* cssAnimations, const CSSAnimationUpdate* update)
dstockwell 2013/10/08 21:02:59 If the transitions are being added to the document
Timothy Loh 2013/10/09 07:39:23 This mean that frame 0 will show the end state, si
407 {
408 // FIXME: Transitions shouldn't apply values for properties with a running C SS Animation.
409 AnimationEffect::CompositableValueMap result;
410
411 if (cssAnimations) {
412 const TransitionMap& transitions = cssAnimations->m_transitions;
413 for (TransitionMap::const_iterator iter = transitions.begin(); iter != t ransitions.end(); ++iter) {
414 CSSPropertyID id = iter->key;
415 if (update && update->endedTransitions().contains(id))
416 continue;
417 Player* player = iter->value.get();
418 Animation* animation = static_cast<Animation*>(player->source());
419 ASSERT(animation && animation->compositableValues());
420 const AnimationEffect::CompositableValueMap* compositableValues = an imation->compositableValues();
421 ASSERT(compositableValues->size() == 1 && compositableValues->contai ns(id));
422 result.set(id, compositableValues->get(id));
423 }
424 }
425
426 if (update) {
427 HashMap<CSSPropertyID, RefPtr<InertAnimation> >::const_iterator iter;
dstockwell 2013/10/08 21:02:59 Put this on the next line
Timothy Loh 2013/10/09 01:33:07 Makes the line a bit long but OK.
428 for (iter = update->newTransitions().begin(); iter != update->newTransit ions().end(); ++iter) {
429 CSSPropertyID id = iter->key;
430 InertAnimation* animation = iter->value.get();
431 OwnPtr<AnimationEffect::CompositableValueMap> compositableValues = a nimation->sample();
432 ASSERT(compositableValues->size() == 1 && compositableValues->contai ns(id));
433 result.set(id, compositableValues->get(id));
434 }
435 }
436
437 return result;
237 } 438 }
238 439
239 void CSSAnimations::cancel() 440 void CSSAnimations::cancel()
240 { 441 {
241 for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animation s.end(); ++iter) { 442 for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animation s.end(); ++iter) {
242 const HashSet<RefPtr<Player> >& players = iter->value; 443 const HashSet<RefPtr<Player> >& players = iter->value;
243 for (HashSet<RefPtr<Player> >::const_iterator animationsIter = players.b egin(); animationsIter != players.end(); ++animationsIter) 444 for (HashSet<RefPtr<Player> >::const_iterator animationsIter = players.b egin(); animationsIter != players.end(); ++animationsIter)
244 (*animationsIter)->cancel(); 445 (*animationsIter)->cancel();
245 } 446 }
246 447
448 for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transit ions.end(); ++iter)
449 iter->value->cancel();
450
247 m_animations.clear(); 451 m_animations.clear();
dstockwell 2013/10/08 21:02:59 m_transitions.clear()
Timothy Loh 2013/10/09 01:33:07 Done.
248 m_pendingUpdate = nullptr; 452 m_pendingUpdate = nullptr;
249 } 453 }
250 454
251 void CSSAnimations::EventDelegate::maybeDispatch(Document::ListenerType listener Type, AtomicString& eventName, double elapsedTime) 455 void CSSAnimations::AnimationEventDelegate::maybeDispatch(Document::ListenerType listenerType, AtomicString& eventName, double elapsedTime)
252 { 456 {
253 if (m_target->document().hasListenerType(listenerType)) 457 if (m_target->document().hasListenerType(listenerType))
254 m_target->document().timeline()->addEventToDispatch(m_target, WebKitAnim ationEvent::create(eventName, m_name, elapsedTime)); 458 m_target->document().timeline()->addEventToDispatch(m_target, WebKitAnim ationEvent::create(eventName, m_name, elapsedTime));
255 } 459 }
256 460
257 void CSSAnimations::EventDelegate::onEventCondition(const TimedItem* timedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) 461 void CSSAnimations::AnimationEventDelegate::onEventCondition(const TimedItem* ti medItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIter ation)
258 { 462 {
259 // Events for a single document are queued and dispatched as a group at 463 // Events for a single document are queued and dispatched as a group at
260 // the end of DocumentTimeline::serviceAnimations. 464 // the end of DocumentTimeline::serviceAnimations.
261 // FIXME: Events which are queued outside of serviceAnimations should 465 // FIXME: Events which are queued outside of serviceAnimations should
262 // trigger a timer to dispatch when control is released. 466 // trigger a timer to dispatch when control is released.
263 const TimedItem::Phase currentPhase = timedItem->phase(); 467 const TimedItem::Phase currentPhase = timedItem->phase();
264 const double currentIteration = timedItem->currentIteration(); 468 const double currentIteration = timedItem->currentIteration();
265 469
266 // Note that the elapsedTime is measured from when the animation starts play ing. 470 // Note that the elapsedTime is measured from when the animation starts play ing.
267 if (!isFirstSample && previousPhase == TimedItem::PhaseActive && currentPhas e == TimedItem::PhaseActive && previousIteration != currentIteration) { 471 if (!isFirstSample && previousPhase == TimedItem::PhaseActive && currentPhas e == TimedItem::PhaseActive && previousIteration != currentIteration) {
(...skipping 12 matching lines...) Expand all
280 ASSERT(timedItem->specified().startDelay > 0 || isFirstSample); 484 ASSERT(timedItem->specified().startDelay > 0 || isFirstSample);
281 // The spec states that the elapsed time should be 485 // The spec states that the elapsed time should be
282 // 'delay < 0 ? -delay : 0', but we always use 0 to match the existing 486 // 'delay < 0 ? -delay : 0', but we always use 0 to match the existing
283 // implementation. See crbug.com/279611 487 // implementation. See crbug.com/279611
284 maybeDispatch(Document::ANIMATIONSTART_LISTENER, eventNames().animations tartEvent, 0); 488 maybeDispatch(Document::ANIMATIONSTART_LISTENER, eventNames().animations tartEvent, 0);
285 } 489 }
286 if ((isFirstSample || isEarlierPhase(previousPhase, TimedItem::PhaseAfter)) && currentPhase == TimedItem::PhaseAfter) 490 if ((isFirstSample || isEarlierPhase(previousPhase, TimedItem::PhaseAfter)) && currentPhase == TimedItem::PhaseAfter)
287 maybeDispatch(Document::ANIMATIONEND_LISTENER, eventNames().animationend Event, timedItem->activeDuration()); 491 maybeDispatch(Document::ANIMATIONEND_LISTENER, eventNames().animationend Event, timedItem->activeDuration());
288 } 492 }
289 493
494 void CSSAnimations::TransitionEventDelegate::onEventCondition(const TimedItem* t imedItem, bool isFirstSample, TimedItem::Phase previousPhase, double previousIte ration)
495 {
496 // Events for a single document are queued and dispatched as a group at
497 // the end of DocumentTimeline::serviceAnimations.
498 // FIXME: Events which are queued outside of serviceAnimations should
499 // trigger a timer to dispatch when control is released.
500 const TimedItem::Phase currentPhase = timedItem->phase();
501 if (currentPhase == TimedItem::PhaseActive || previousPhase == currentPhase)
dstockwell 2013/10/08 21:02:59 Shouldn't we only be firing when currentPhase beco
Timothy Loh 2013/10/09 01:33:07 Tweaked condition slightly.
502 return;
503 if (m_target->document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
504 String propertyName = getPropertyNameString(m_id);
505 const Timing& timing = timedItem->specified();
506 double elapsedTime = timing.iterationDuration;
507 const AtomicString& eventType = eventNames().transitionendEvent;
508 String pseudoElement = PseudoElement::pseudoElementNameForEvents(m_targe t->pseudoId());
509 m_target->document().timeline()->addEventToDispatch(m_target, Transition Event::create(eventType, propertyName, elapsedTime, pseudoElement));
510 }
511 }
512
513
290 bool CSSAnimations::isAnimatableProperty(CSSPropertyID property) 514 bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
291 { 515 {
292 switch (property) { 516 switch (property) {
293 case CSSPropertyBackgroundColor: 517 case CSSPropertyBackgroundColor:
294 case CSSPropertyBackgroundImage: 518 case CSSPropertyBackgroundImage:
295 case CSSPropertyBackgroundPositionX: 519 case CSSPropertyBackgroundPositionX:
296 case CSSPropertyBackgroundPositionY: 520 case CSSPropertyBackgroundPositionY:
297 case CSSPropertyBackgroundSize: 521 case CSSPropertyBackgroundSize:
298 case CSSPropertyBaselineShift: 522 case CSSPropertyBaselineShift:
299 case CSSPropertyBorderBottomColor: 523 case CSSPropertyBorderBottomColor:
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 case CSSPropertyWidth: 615 case CSSPropertyWidth:
392 case CSSPropertyWordSpacing: 616 case CSSPropertyWordSpacing:
393 case CSSPropertyZIndex: 617 case CSSPropertyZIndex:
394 case CSSPropertyZoom: 618 case CSSPropertyZoom:
395 return true; 619 return true;
396 default: 620 default:
397 return false; 621 return false;
398 } 622 }
399 } 623 }
400 624
625 const Vector<CSSPropertyID>& CSSAnimations::animatableProperties()
626 {
627 DEFINE_STATIC_LOCAL(Vector<CSSPropertyID>, properties, ());
628 if (properties.isEmpty()) {
629 for (int i = firstCSSProperty; i < lastCSSProperty; ++i) {
630 CSSPropertyID id = convertToCSSPropertyID(i);
631 if (isAnimatableProperty(id))
632 properties.append(id);
633 }
634 }
635 return properties;
636 }
637
401 } // namespace WebCore 638 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698