Changeset 200047 in webkit
- Timestamp:
- Apr 25, 2016, 1:56:47 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r200043 r200047 1 2016-04-25 Simon Fraser <simon.fraser@apple.com> 2 3 Toggling animation-play-state can re-start a finished animation 4 https://bugs.webkit.org/show_bug.cgi?id=156731 5 6 Reviewed by Dean Jackson. 7 8 * animations/animation-direction-reverse-expected.txt: 9 * animations/animation-direction-reverse.html: This is a progression. The test was detecting a 10 restarted animation. 11 * animations/change-completed-animation-expected.txt: Added. 12 * animations/change-completed-animation-transform-expected.html: Added. 13 * animations/change-completed-animation-transform.html: Added. Ref test that ensures that the final 14 state for normal and accelerated animations is correct. 15 * animations/change-completed-animation.html: Added. Tests that changing a property doesn't trigger 16 another animation, by detecting a second animationstart event. 17 1 18 2016-04-25 Simon Fraser <simon.fraser@apple.com> 2 19 -
trunk/LayoutTests/animations/animation-direction-reverse-expected.txt
r107162 r200047 1 1 PASS - "webkitTransform" property for "box" element at 0.5s saw something close to: 1,0,0,1,150,0 2 2 PASS - "webkitTransform" property for "box" element at 1s saw something close to: 1,0,0,1,100,0 3 PASS - "webkitTransform" property for "box" element at 2.5s saw something close to: 1,0,0,1,200,03 PASS - "webkitTransform" property for "box" element at 2.5s saw something close to: none 4 4 -
trunk/LayoutTests/animations/animation-direction-reverse.html
r107162 r200047 35 35 ["move1", 0.5, "box", "webkitTransform", [1,0,0,1, 150,0], 20], 36 36 ["move1", 1.0, "box", "webkitTransform", [1,0,0,1,100,0], 20], 37 ["move1", 2.5, "box", "webkitTransform", [1,0,0,1, 200,0], 20],37 ["move1", 2.5, "box", "webkitTransform", 'none', 20], 38 38 ]; 39 39 -
trunk/Source/WebCore/ChangeLog
r200046 r200047 1 2016-04-25 Simon Fraser <simon.fraser@apple.com> 2 3 Toggling animation-play-state can re-start a finished animation 4 https://bugs.webkit.org/show_bug.cgi?id=156731 5 6 Reviewed by Dean Jackson. 7 8 After an animation completed, CompositeAnimation::updateKeyframeAnimations() cleared 9 all state that the animation had run on the element, so changing the value of some 10 animation property triggered the animation to run again. This is wrong, since animation-name 11 still applied to the element. 12 13 Fix by keeping state for keyframe animations in the Done state in the m_keyframeAnimations 14 map. This allows for the removal of the index property on KeyframeAnimation. 15 16 Tests: animations/change-completed-animation-transform.html 17 animations/change-completed-animation.html 18 19 * page/animation/AnimationBase.cpp: 20 (WebCore::AnimationBase::timeToNextService): 21 * page/animation/AnimationBase.h: 22 (WebCore::AnimationBase::isAnimatingProperty): 23 * page/animation/CompositeAnimation.cpp: Add animations that should stick around to AnimationNameMap, 24 and swap with m_keyframeAnimations at the end. 25 (WebCore::CompositeAnimation::updateKeyframeAnimations): 26 * page/animation/KeyframeAnimation.cpp: 27 (WebCore::KeyframeAnimation::KeyframeAnimation): 28 (WebCore::KeyframeAnimation::getAnimatedStyle): 29 * page/animation/KeyframeAnimation.h: 30 1 31 2016-04-25 Alberto Garcia <berto@igalia.com> 2 32 -
trunk/Source/WebCore/page/animation/AnimationBase.cpp
r200042 r200047 561 561 // Returns the time at which next service is required. -1 means no service is required. 0 means 562 562 // service is required now, and > 0 means service is required that many seconds in the future. 563 if (paused() || isNew() || m_animationState == AnimationState::FillingForwards)563 if (paused() || isNew() || postActive() || fillingForwards()) 564 564 return -1; 565 565 -
trunk/Source/WebCore/page/animation/AnimationBase.h
r199964 r200047 182 182 return true; 183 183 184 if ((runningState & Running) && !inPausedState() && (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState < =AnimationState::Done))184 if ((runningState & Running) && !inPausedState() && (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState < AnimationState::Done)) 185 185 return true; 186 186 -
trunk/Source/WebCore/page/animation/CompositeAnimation.cpp
r200041 r200047 204 204 m_keyframeAnimations.checkConsistency(); 205 205 206 if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations())) { 207 // The current and target animations are the same so we just need to toss any 208 // animation which is finished (postActive). 209 for (auto& animation : m_keyframeAnimations.values()) { 210 if (animation->postActive()) 211 animation->setIndex(-1); 212 } 213 } else { 214 // Mark all existing animations as no longer active. 215 for (auto& animation : m_keyframeAnimations.values()) 216 animation->setIndex(-1); 206 if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations())) 207 return; 217 208 218 209 #if ENABLE(CSS_ANIMATIONS_LEVEL_2) 219 210 m_hasScrollTriggeredAnimation = false; 220 211 #endif 221 212 222 // Toss the animation order map. 223 m_keyframeAnimationOrderMap.clear(); 224 225 static NeverDestroyed<const AtomicString> none("none", AtomicString::ConstructFromLiteral); 226 227 // Now mark any still active animations as active and add any new animations. 228 if (targetStyle->animations()) { 229 int numAnims = targetStyle->animations()->size(); 230 for (int i = 0; i < numAnims; ++i) { 231 Animation& animation = targetStyle->animations()->animation(i); 232 AtomicString animationName(animation.name()); 233 234 if (!animation.isValidAnimation()) 213 AnimationNameMap newAnimations; 214 215 // Toss the animation order map. 216 m_keyframeAnimationOrderMap.clear(); 217 218 static NeverDestroyed<const AtomicString> none("none", AtomicString::ConstructFromLiteral); 219 220 // Now mark any still active animations as active and add any new animations. 221 if (targetStyle->animations()) { 222 int numAnims = targetStyle->animations()->size(); 223 for (int i = 0; i < numAnims; ++i) { 224 Animation& animation = targetStyle->animations()->animation(i); 225 AtomicString animationName(animation.name()); 226 227 if (!animation.isValidAnimation()) 228 continue; 229 230 // See if there is a current animation for this name. 231 RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl()); 232 if (keyframeAnim) { 233 newAnimations.add(keyframeAnim->name().impl(), keyframeAnim); 234 235 if (keyframeAnim->postActive()) 235 236 continue; 236 237 // See if there is a current animation for this name.238 RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl());239 240 if (keyframeAnim) {241 // If this animation is postActive, skip it so it gets removed at the end of this function.242 if (keyframeAnim->postActive())243 continue;244 237 245 238 #if ENABLE(CSS_ANIMATIONS_LEVEL_2) 246 247 239 if (animation.trigger()->isScrollAnimationTrigger()) 240 m_hasScrollTriggeredAnimation = true; 248 241 #endif 249 242 250 // This one is still active. 251 252 // Animations match, but play states may differ. Update if needed. 253 keyframeAnim->updatePlayState(animation.playState()); 254 255 // Set the saved animation to this new one, just in case the play state has changed. 256 keyframeAnim->setAnimation(animation); 257 keyframeAnim->setIndex(i); 258 } else if ((animation.duration() || animation.delay()) && animation.iterationCount() && animationName != none) { 259 keyframeAnim = KeyframeAnimation::create(animation, renderer, i, this, targetStyle); 260 LOG(Animations, "Creating KeyframeAnimation %p on renderer %p with keyframes %s, duration %.2f, delay %.2f, iterations %.2f", keyframeAnim.get(), renderer, animation.name().utf8().data(), animation.duration(), animation.delay(), animation.iterationCount()); 261 if (m_suspended) { 262 keyframeAnim->updatePlayState(AnimPlayStatePaused); 263 LOG(Animations, " (created in suspended/paused state)"); 264 } 243 // Animations match, but play states may differ. Update if needed. 244 keyframeAnim->updatePlayState(animation.playState()); 245 246 // Set the saved animation to this new one, just in case the play state has changed. 247 keyframeAnim->setAnimation(animation); 248 } else if ((animation.duration() || animation.delay()) && animation.iterationCount() && animationName != none) { 249 keyframeAnim = KeyframeAnimation::create(animation, renderer, this, targetStyle); 250 LOG(Animations, "Creating KeyframeAnimation %p on renderer %p with keyframes %s, duration %.2f, delay %.2f, iterations %.2f", keyframeAnim.get(), renderer, animation.name().utf8().data(), animation.duration(), animation.delay(), animation.iterationCount()); 251 252 if (m_suspended) { 253 keyframeAnim->updatePlayState(AnimPlayStatePaused); 254 LOG(Animations, " (created in suspended/paused state)"); 255 } 265 256 #if !LOG_DISABLED 266 267 257 for (auto propertyID : keyframeAnim->keyframes().properties()) 258 LOG(Animations, " property %s", getPropertyName(propertyID)); 268 259 #endif 269 260 270 261 #if ENABLE(CSS_ANIMATIONS_LEVEL_2) 271 272 262 if (animation.trigger()->isScrollAnimationTrigger()) 263 m_hasScrollTriggeredAnimation = true; 273 264 #endif 274 265 275 m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim); 276 } 277 278 // Add this to the animation order map. 279 if (keyframeAnim) 280 m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl()); 266 newAnimations.set(keyframeAnim->name().impl(), keyframeAnim); 281 267 } 268 269 // Add this to the animation order map. 270 if (keyframeAnim) 271 m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl()); 282 272 } 283 273 } 284 274 285 275 // Make a list of animations to be removed. 286 Vector<AtomicStringImpl*> animsToBeRemoved;287 276 for (auto& animation : m_keyframeAnimations.values()) { 288 if (animation->index() < 0) { 289 animsToBeRemoved.append(animation->name().impl()); 277 if (!newAnimations.contains(animation->name().impl())) { 290 278 animationController().animationWillBeRemoved(animation.get()); 291 279 animation->clear(); … … 294 282 } 295 283 296 // Now remove the animations from the list. 297 for (auto* nameForRemoval : animsToBeRemoved) 298 m_keyframeAnimations.remove(nameForRemoval); 284 std::swap(newAnimations, m_keyframeAnimations); 299 285 } 300 286 -
trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp
r200042 r200047 42 42 namespace WebCore { 43 43 44 KeyframeAnimation::KeyframeAnimation(Animation& animation, RenderElement* renderer, int index,CompositeAnimation* compositeAnimation, RenderStyle* unanimatedStyle)44 KeyframeAnimation::KeyframeAnimation(Animation& animation, RenderElement* renderer, CompositeAnimation* compositeAnimation, RenderStyle* unanimatedStyle) 45 45 : AnimationBase(animation, renderer, compositeAnimation) 46 46 , m_keyframes(animation.name()) 47 47 , m_unanimatedStyle(RenderStyle::clonePtr(*unanimatedStyle)) 48 , m_index(index)49 48 { 50 49 // Get the keyframe RenderStyles … … 191 190 void KeyframeAnimation::getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle) 192 191 { 193 // If we're in the delay phase and we're not backwards filling, tell the caller 194 // to use the current style. 195 if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards()) 192 // If we're done, or in the delay phase and we're not backwards filling, tell the caller to use the current style. 193 if (postActive() || (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards())) 196 194 return; 197 195 -
trunk/Source/WebCore/page/animation/KeyframeAnimation.h
r199964 r200047 41 41 class KeyframeAnimation final : public AnimationBase { 42 42 public: 43 static Ref<KeyframeAnimation> create(Animation& animation, RenderElement* renderer, int index,CompositeAnimation* compositeAnimation, RenderStyle* unanimatedStyle)43 static Ref<KeyframeAnimation> create(Animation& animation, RenderElement* renderer, CompositeAnimation* compositeAnimation, RenderStyle* unanimatedStyle) 44 44 { 45 return adoptRef(*new KeyframeAnimation(animation, renderer, index,compositeAnimation, unanimatedStyle));45 return adoptRef(*new KeyframeAnimation(animation, renderer, compositeAnimation, unanimatedStyle)); 46 46 } 47 47 … … 54 54 55 55 const AtomicString& name() const { return m_keyframes.animationName(); } 56 int index() const { return m_index; }57 void setIndex(int i) { m_index = i; }58 56 59 57 bool hasAnimationForProperty(CSSPropertyID) const; … … 91 89 92 90 private: 93 KeyframeAnimation(Animation&, RenderElement*, int index,CompositeAnimation*, RenderStyle* unanimatedStyle);91 KeyframeAnimation(Animation&, RenderElement*, CompositeAnimation*, RenderStyle* unanimatedStyle); 94 92 virtual ~KeyframeAnimation(); 95 93 … … 100 98 std::unique_ptr<RenderStyle> m_unanimatedStyle; // The style just before we started animation 101 99 102 int m_index; // The order in which this animation appears in the animation-name style.103 100 bool m_startEventDispatched { false }; 104 101 };
Note:
See TracChangeset
for help on using the changeset viewer.