Changeset 34382 in webkit
- Timestamp:
- Jun 5, 2008 1:51:32 PM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r34381 r34382 1 2008-06-04 David Hyatt <hyatt@apple.com> 2 3 Fix for <rdar://problem/5957994> Height doesn't animate 4 5 Improve the behavior when transitions are dynamically changed. Make sure to leave older transitions 6 running and let them obsolete themselves when they finish. 7 8 Reviewed by Dan Bernstein 9 10 Added WebCore/manual-tests/transitions2.html (must be tested manually) 11 12 * manual-tests/transitions.html: 13 * manual-tests/transitions2.html: Added. 14 * page/AnimationController.cpp: 15 (WebCore::ImplicitAnimation::property): 16 (WebCore::ImplicitAnimation::setFinished): 17 (WebCore::ImplicitAnimation::markedForDeath): 18 (WebCore::ImplicitAnimation::setMarkedForDeath): 19 (WebCore::ImplicitAnimation::ImplicitAnimation): 20 (WebCore::ImplicitAnimation::reset): 21 (WebCore::ImplicitAnimation::animate): 22 (WebCore::CompositeImplicitAnimation::animate): 23 1 24 2008-06-05 Eric Seidel <eric@webkit.org> 2 25 -
trunk/WebCore/manual-tests/transitions.html
r30319 r34382 32 32 {className:"", description:"instantly change into a small green square then animate to yellow over 5 seconds"}, 33 33 {className:"square", description:"instantly change into a big yellow square"}, 34 {className:"green", description:"instantly change into a green square and then animate to a rectang e over 2 seconds"},34 {className:"green", description:"instantly change into a green square and then animate to a rectangle over 2 seconds"}, 35 35 {className:"", description:"instantly change into a small green square then animate to yellow over 5 seconds"}, 36 36 {className:"green", description:"instantly change into a green rectangle"}, 37 {className:"square", description:"instantly change into a green rectangle then animate to yellow over 5 seconds"},37 {className:"square", description:"instantly change into a green square then animate to yellow over 5 seconds"}, 38 38 {className:"", description:"instantly change into a rectangle then animate into a square over 2 seconds"} 39 39 ]; -
trunk/WebCore/page/AnimationController.cpp
r32334 r34382 69 69 double progress() const; 70 70 71 int property() const { return m_property; } 72 71 73 bool finished() const { return m_finished; } 74 void setFinished(bool f) { m_finished = f; } 75 76 bool stale() const { return m_stale; } 77 void setStale() { m_stale = true; } 72 78 73 79 private: … … 87 93 bool m_paused; 88 94 double m_pauseTime; 95 96 bool m_stale; 89 97 }; 90 98 … … 96 104 97 105 bool animating() const; 98 99 bool hasAnimationForProperty(int prop) const { return m_animations.contains(prop); }100 106 101 107 void reset(RenderObject*); … … 117 123 , m_paused(false) 118 124 , m_pauseTime(m_startTime) 125 , m_stale(false) 119 126 { 120 127 } … … 127 134 void ImplicitAnimation::reset(RenderObject* renderer, RenderStyle* from, RenderStyle* to) 128 135 { 136 setFinished(false); 137 129 138 if (m_fromStyle) 130 139 m_fromStyle->deref(renderer->renderArena()); … … 137 146 if (m_toStyle) 138 147 m_toStyle->ref(); 139 m_finished = false;140 148 if (from || to) 141 149 m_startTime = currentTime(); 150 151 // If we are stale, attempt to update to a new transition using the new |from| style. If we are able to find a new transition, 152 // then we will unmark ourselves for death. 153 if (stale() && from && to) { 154 for (const Transition* transition = from->transitions(); transition; transition = transition->next()) { 155 if (m_property != transition->property()) 156 continue; 157 int duration = transition->duration(); 158 int repeatCount = transition->repeatCount(); 159 if (duration && repeatCount) { 160 m_duration = duration / 1000.0; 161 m_repeatCount = repeatCount; 162 m_stale = false; 163 break; 164 } 165 } 166 } 167 168 // If we did not find a new transition, then mark ourselves as being finished so that we can be removed. 169 if (stale()) 170 setFinished(true); 142 171 } 143 172 … … 227 256 228 257 #define BLEND(prop, getter, setter) \ 229 if (m_property == prop && m_toStyle->getter() != targetStyle->getter()) \258 if (m_property == prop && m_toStyle->getter() != targetStyle->getter()) {\ 230 259 reset(renderer, currentStyle, targetStyle); \ 231 \ 232 if ((m_property == cAnimateAll && !animation->hasAnimationForProperty(prop)) || m_property == prop) { \ 260 if (stale()) \ 261 return; \ 262 } \ 263 if (m_property == cAnimateAll || m_property == prop) { \ 233 264 if (m_fromStyle->getter() != m_toStyle->getter()) {\ 234 m_finished = false; \265 setFinished(false); \ 235 266 if (!animatedStyle) \ 236 267 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \ … … 242 273 243 274 #define BLEND_MAYBE_INVALID_COLOR(prop, getter, setter) \ 244 if (m_property == prop && m_toStyle->getter() != targetStyle->getter()) \275 if (m_property == prop && m_toStyle->getter() != targetStyle->getter()) { \ 245 276 reset(renderer, currentStyle, targetStyle); \ 246 \ 247 if ((m_property == cAnimateAll && !animation->hasAnimationForProperty(prop)) || m_property == prop) { \ 277 if (stale()) \ 278 return; \ 279 } \ 280 if (m_property == cAnimateAll || m_property == prop) { \ 248 281 Color fromColor = m_fromStyle->getter(); \ 249 282 Color toColor = m_toStyle->getter(); \ … … 254 287 toColor = m_toStyle->color(); \ 255 288 if (fromColor != toColor) {\ 256 m_finished = false; \289 setFinished(false); \ 257 290 if (!animatedStyle) \ 258 291 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \ … … 265 298 266 299 #define BLEND_SHADOW(prop, getter, setter) \ 267 if (m_property == prop && (!m_toStyle->getter() || !targetStyle->getter() || *m_toStyle->getter() != *targetStyle->getter())) \300 if (m_property == prop && (!m_toStyle->getter() || !targetStyle->getter() || *m_toStyle->getter() != *targetStyle->getter())) { \ 268 301 reset(renderer, currentStyle, targetStyle); \ 269 \ 270 if ((m_property == cAnimateAll && !animation->hasAnimationForProperty(prop)) || m_property == prop) { \ 302 if (stale()) \ 303 return; \ 304 } \ 305 if (m_property == cAnimateAll || m_property == prop) { \ 271 306 if (m_fromStyle->getter() && m_toStyle->getter() && *m_fromStyle->getter() != *m_toStyle->getter()) {\ 272 m_finished = false; \307 setFinished(false); \ 273 308 if (!animatedStyle) \ 274 309 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \ … … 284 319 // every single animatable property. For now we'll just diff the styles to ask that question, 285 320 // but we should really exclude non-animatable properties. 286 if (!m_toStyle || (m_property == cAnimateAll && targetStyle->diff(m_toStyle))) 321 if (!m_toStyle || (m_property == cAnimateAll && targetStyle->diff(m_toStyle))) { 287 322 reset(renderer, currentStyle, targetStyle); 323 if (stale()) 324 return; 325 } 288 326 289 327 // FIXME: Blow up shorthands so that they can be honored. 290 m_finished = true;328 setFinished(true); 291 329 BLEND(CSSPropertyLeft, left, setLeft); 292 330 BLEND(CSSPropertyRight, right, setRight); … … 347 385 const Transition* currentTransitions = currentStyle->transitions(); 348 386 const Transition* targetTransitions = targetStyle->transitions(); 349 if (currentTransitions != targetTransitions && !(currentTransitions && targetTransitions && *currentTransitions == *targetTransitions)) { 350 reset(renderer); 351 deleteAllValues(m_animations); 352 m_animations.clear(); 353 } 354 355 // Get the animation layers from the target style. 356 // For each one, we need to create a new animation unless one exists already (later occurrences of duplicate 357 // triggers in the layer list get ignored). 387 bool transitionsChanged = currentTransitions != targetTransitions && !(currentTransitions && targetTransitions && *currentTransitions == *targetTransitions); 388 358 389 if (m_animations.isEmpty()) { 390 // For each transition, we create a new animation unless one exists already (later occurrences of duplicate 391 // triggers in the layer list get ignored). 359 392 for (const Transition* transition = currentTransitions; transition; transition = transition->next()) { 360 393 int property = transition->property(); … … 367 400 } 368 401 } 369 402 370 403 // Now that we have animation objects ready, let them know about the new goal state. We want them 371 404 // to fill in a RenderStyle*& only if needed. 372 405 RenderStyle* result = 0; 373 406 HashMap<int, ImplicitAnimation*>::iterator end = m_animations.end(); 374 for (HashMap<int, ImplicitAnimation*>::iterator it = m_animations.begin(); it != end; ++it) 407 Vector<int> obsoleteTransitions; 408 409 // Look at the "all" animation first. 410 ImplicitAnimation* allAnimation = m_animations.get(cAnimateAll); 411 if (allAnimation) { 412 allAnimation->animate(this, renderer, currentStyle, targetStyle, result); 413 if (transitionsChanged) 414 // Mark the "all" animation as stale if the set of transitions changed. Stale animations continue 415 // to blend on a timer, and then remove themselves when finished. 416 allAnimation->setStale(); 417 418 // If the animation is done and we are marked as stale, then we can be removed after the 419 // iteration of the hashmap is finished. 420 if (allAnimation->finished() && allAnimation->stale()) 421 obsoleteTransitions.append(cAnimateAll); 422 } 423 424 // Now look at the specialized animations. 425 for (HashMap<int, ImplicitAnimation*>::iterator it = m_animations.begin(); it != end; ++it) { 426 // Skip over the "all" animation, since we animated it already. 427 if (it->second->property() == cAnimateAll) 428 continue; 429 375 430 it->second->animate(this, renderer, currentStyle, targetStyle, result); 431 if (transitionsChanged) 432 // Mark any running animations as stale if the set of transitions changed. Stale animations continue 433 // to blend on a timer, and then remove themselves when finished. 434 it->second->setStale(); 435 436 // If the animation is done and we are marked as stale, then we can be removed after the 437 // iteration of the hashmap is finished. 438 if (it->second->finished() && it->second->stale()) 439 obsoleteTransitions.append(it->second->property()); 440 441 } 442 443 // Now cull out any stale animations that are finished. 444 for (unsigned i = 0; i < obsoleteTransitions.size(); ++i) { 445 ImplicitAnimation* animation = m_animations.take(obsoleteTransitions[i]); 446 animation->reset(renderer, 0, 0); 447 delete animation; 448 } 449 450 if (transitionsChanged) { 451 // If our transitions changed we need to add new animations for any transitions that 452 // don't exist yet. If a new transition conflicts with a currently running stale transition, then we will not add it. 453 // The stale transition is responsible for updating itself to the new transition if it ever gets reset or finishes. 454 for (const Transition* transition = targetTransitions; transition; transition = transition->next()) { 455 int property = transition->property(); 456 int duration = transition->duration(); 457 int repeatCount = transition->repeatCount(); 458 if (property && duration && repeatCount && !m_animations.contains(property)) { 459 ImplicitAnimation* animation = new ImplicitAnimation(transition); 460 m_animations.set(property, animation); 461 } 462 } 463 } 376 464 377 465 if (result)
Note: See TracChangeset
for help on using the changeset viewer.