Changeset 35646 in webkit
- Timestamp:
- Aug 8, 2008 1:44:14 PM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 3 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r35645 r35646 1 2008-08-08 Dean Jackson <dino@apple.com> 2 3 Execute CSS Animations using new AnimationController 4 https://bugs.webkit.org/show_bug.cgi?id=20119 5 6 I still need to file some follow-on bugs that EricS noticed. 7 8 Reviewed by Dave Hyatt 9 10 Some new tests: 11 * manual-tests/animate-duration.html: Added. 12 * manual-tests/animate-left.html: Added. 13 * manual-tests/animate-none.html: Added. 14 15 * css/CSSStyleSelector.cpp: 16 * dom/Document.cpp: 17 - don't redo style when page is place into cache 18 * page/AnimationController.cpp: 19 * page/AnimationController.h: 20 - execute the animations 21 * rendering/RenderObject.cpp: 22 * rendering/style/RenderStyle.h: 23 - make border radii const (for blending) 24 1 25 2008-08-08 Kevin McCullough <kmccullough@apple.com> 2 26 -
trunk/WebCore/css/CSSStyleSelector.cpp
r35580 r35646 196 196 } \ 197 197 \ 198 /* Reset any remaining layers to not have the property set. */ \198 /* Reset any remaining animations to not have the property set. */ \ 199 199 for ( ; i < list->size(); ++i) \ 200 200 (*list)[i]->clear##Prop(); \ … … 214 214 size_t childIndex = 0; \ 215 215 if (value->isValueList()) { \ 216 /* Walk each value and put it into a layer, creating new layers as needed. */ \216 /* Walk each value and put it into an animation, creating new animations as needed. */ \ 217 217 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ 218 218 for (unsigned int i = 0; i < valueList->length(); i++) { \ … … 229 229 } \ 230 230 for ( ; childIndex < list->size(); ++childIndex) { \ 231 /* Reset all remaining layers to not have the property set. */ \231 /* Reset all remaining animations to not have the property set. */ \ 232 232 (*list)[childIndex]->clear##Prop(); \ 233 233 } \ … … 245 245 } \ 246 246 \ 247 /* Reset any remaining layers to not have the property set. */ \247 /* Reset any remaining transitions to not have the property set. */ \ 248 248 for ( ; i < list->size(); ++i) \ 249 249 (*list)[i]->clear##Prop(); \ … … 263 263 size_t childIndex = 0; \ 264 264 if (value->isValueList()) { \ 265 /* Walk each value and put it into a layer, creating new layers as needed. */ \265 /* Walk each value and put it into a transition, creating new animations as needed. */ \ 266 266 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ 267 267 for (unsigned int i = 0; i < valueList->length(); i++) { \ … … 278 278 } \ 279 279 for ( ; childIndex < list->size(); ++childIndex) { \ 280 /* Reset all remaining layers to not have the property set. */ \280 /* Reset all remaining transitions to not have the property set. */ \ 281 281 (*list)[childIndex]->clear##Prop(); \ 282 282 } \ -
trunk/WebCore/dom/Document.cpp
r35545 r35646 1162 1162 void Document::updateRendering() 1163 1163 { 1164 if (hasChangedChild() )1164 if (hasChangedChild() && !inPageCache()) 1165 1165 recalcStyle(NoChange); 1166 1166 1167 // tell the animation controller that the style is available and it can start animations1167 // Tell the animation controller that the style is available and it can start animations 1168 1168 if (m_frame) 1169 1169 m_frame->animation()->styleAvailable(); … … 1548 1548 if (f) 1549 1549 f->loader()->startIconLoader(); 1550 1551 // Resume the animations (or start them) 1552 if (f) 1553 f->animation()->resumeAnimations(this); 1550 1554 1551 1555 dispatchImageLoadEventsNow(); -
trunk/WebCore/page/AnimationController.cpp
r35568 r35646 158 158 159 159 class ImplicitAnimation; 160 class KeyframeAnimation; 160 161 class AnimationControllerPrivate; 161 162 … … 174 175 { 175 176 deleteAllValues(m_transitions); 177 deleteAllValues(m_keyframeAnimations); 176 178 } 177 179 … … 183 185 bool hasAnimationForProperty(int prop) const { return m_transitions.contains(prop); } 184 186 185 void setTransitionStartTime(int property, double t);186 187 187 void resetTransitions(RenderObject*); 188 188 void resetAnimations(RenderObject*); 189 189 190 190 void cleanupFinishedAnimations(RenderObject*); 191 192 void setAnimationStartTime(double t); 193 void setTransitionStartTime(int property, double t); 191 194 192 195 void suspendAnimations(); … … 199 202 void styleAvailable(); 200 203 201 bool isAnimatingProperty(int property ) const;204 bool isAnimatingProperty(int property, bool isRunningNow) const; 202 205 203 206 void setWaitingForStyleAvailable(bool waiting); 207 204 208 protected: 205 209 void updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle); 210 void updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle); 211 212 KeyframeAnimation* findKeyframeAnimation(const AtomicString& name); 206 213 207 214 private: 208 215 typedef HashMap<int, ImplicitAnimation*> CSSPropertyTransitionsMap; 216 typedef HashMap<AtomicStringImpl*, KeyframeAnimation*> AnimationNameMap; 209 217 210 218 CSSPropertyTransitionsMap m_transitions; 219 AnimationNameMap m_keyframeAnimations; 211 220 bool m_suspended; 212 221 AnimationControllerPrivate* m_animationController; … … 271 280 272 281 // Animation has actually started, at passed time 273 // This is a callback and is only received when RenderObject::startAnimation() or RenderObject::startTransition()274 // returns true. If RenderObject::275 282 void onAnimationStartResponse(double startTime); 276 283 277 284 // Called to change to or from paused state 278 285 void updatePlayState(bool running); 279 bool playStatePlaying() const { return m_animation ; }286 bool playStatePlaying() const { return m_animation && m_animation->playState() == AnimPlayStatePlaying; } 280 287 281 288 bool waitingToStart() const { return m_animState == STATE_NEW || m_animState == STATE_START_WAIT_TIMER; } … … 303 310 304 311 virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, 305 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle) { }312 const RenderStyle* targetStyle, RenderStyle*& animatedStyle) { } 306 313 virtual void reset(RenderObject* renderer, const RenderStyle* from = 0, const RenderStyle* to = 0) { } 307 314 … … 324 331 // Does this animation/transition involve the given property? 325 332 virtual bool affectsProperty(int property) const { return false; } 326 bool isAnimatingProperty(int property) const 327 { 328 return (!waitingToStart() && !postactive()) && affectsProperty(property); 333 bool isAnimatingProperty(int property, bool isRunningNow) const 334 { 335 if (isRunningNow) 336 return (!waitingToStart() && !postactive()) && affectsProperty(property); 337 338 return !postactive() && affectsProperty(property); 329 339 } 330 340 … … 359 369 double m_startTime; 360 370 double m_pauseTime; 361 RenderObject* 371 RenderObject* m_object; 362 372 363 373 AnimationTimerCallback m_animationTimerCallback; … … 396 406 397 407 virtual void onAnimationEnd(double inElapsedTime); 398 virtual bool startAnimation(double beginTime);399 virtual void endAnimation(bool reset);400 408 401 409 virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, 402 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle);410 const RenderStyle* targetStyle, RenderStyle*& animatedStyle); 403 411 virtual void reset(RenderObject* renderer, const RenderStyle* from = 0, const RenderStyle* to = 0); 404 412 … … 442 450 m_anim->animationEventDispatcherFired(m_element.get(), m_name, m_property, m_reset, m_eventType, m_elapsedTime); 443 451 } 444 452 453 class KeyframeAnimation : public AnimationBase { 454 public: 455 KeyframeAnimation(const Animation* animation, RenderObject* renderer, int index, CompositeAnimation* compAnim) 456 : AnimationBase(animation, renderer, compAnim) 457 , m_keyframes(animation->keyframeList()) 458 , m_name(animation->name()) 459 , m_index(index) 460 { 461 } 462 463 virtual ~KeyframeAnimation() 464 { 465 // Do the cleanup here instead of in the base class so the specialized methods get called 466 if (!postactive()) 467 updateStateMachine(STATE_INPUT_END_ANIMATION, -1); 468 } 469 470 virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, 471 const RenderStyle* targetStyle, RenderStyle*& animatedStyle); 472 473 void setName(const String& s) { m_name = s; } 474 const AtomicString& name() const { return m_name; } 475 int index() const { return m_index; } 476 477 virtual bool shouldFireEvents() const { return true; } 478 479 protected: 480 virtual void onAnimationStart(double inElapsedTime); 481 virtual void onAnimationIteration(double inElapsedTime); 482 virtual void onAnimationEnd(double inElapsedTime); 483 virtual void endAnimation(bool reset); 484 485 virtual void overrideAnimations(); 486 virtual void resumeOverriddenAnimations(); 487 488 bool shouldSendEventForListener(Document::ListenerType inListenerType) 489 { 490 return m_object->document()->hasListenerType(inListenerType); 491 } 492 493 bool sendAnimationEvent(const AtomicString& inEventType, double inElapsedTime); 494 495 virtual bool affectsProperty(int property) const; 496 497 private: 498 // The keyframes that we are blending. 499 RefPtr<KeyframeList> m_keyframes; 500 AtomicString m_name; 501 // The order in which this animation appears in the animation-name style. 502 int m_index; 503 }; 504 445 505 AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim) 446 506 : m_animState(STATE_NEW) … … 461 521 void AnimationBase::updateStateMachine(AnimStateInput input, double param) 462 522 { 463 // if we get a RESTART then we force a new animation, regardless of state523 // If we get a RESTART then we force a new animation, regardless of state 464 524 if (input == STATE_INPUT_MAKE_NEW) { 465 525 if (m_animState == STATE_START_WAIT_STYLE_AVAILABLE) … … 510 570 } 511 571 512 // execute state machine572 // Execute state machine 513 573 switch(m_animState) { 514 574 case STATE_NEW: … … 554 614 555 615 // Send start event, if needed 556 onAnimationStart(0.0f); // the elapsedTime is always 0 here616 onAnimationStart(0.0f); // The elapsedTime is always 0 here 557 617 558 618 // Start the animation … … 715 775 if (!element) 716 776 return; 777 778 // FIXME: Actual event dispatching will be done here 779 780 if (animEventType == EventNames::webkitAnimationEndEvent) { 781 if (element->renderer()) { 782 // Restore the original (unanimated) style 783 setChanged(element->renderer()->element()); 784 } 785 } 717 786 } 718 787 … … 733 802 734 803 double dur = m_animation->duration(); 735 736 if (postactive() || !m_animation->duration() || elapsedTime >= dur) 804 if (m_animation->iterationCount() > 0) 805 dur *= m_animation->iterationCount(); 806 807 if (postactive() || !m_animation->duration() || (m_animation->iterationCount() > 0 && elapsedTime >= dur)) 737 808 return 1.0; 738 809 739 810 // Compute the fractional time, taking into account direction. 740 // There is no need to worry about iterations, we assume that we would have 811 // There is no need to worry about iterations, we assume that we would have 741 812 // short circuited above if we were done 742 double t = elapsedTime / m_animation->duration(); 743 int i = (int) t; 744 t -= i; 813 double fractionalTime = elapsedTime / m_animation->duration(); 814 int integralTime = (int) fractionalTime; 815 fractionalTime -= integralTime; 816 817 if (m_animation->direction() && (integralTime & 1)) 818 fractionalTime = 1 - fractionalTime; 745 819 746 820 if (scale != 1 || offset != 0) 747 t = (t- offset) * scale;821 fractionalTime = (fractionalTime - offset) * scale; 748 822 749 823 if (m_animation->timingFunction().type() == LinearTimingFunction) 750 return t;824 return fractionalTime; 751 825 752 826 // Cubic bezier. 753 double tt = solveCubicBezierFunction(m_animation->timingFunction().x1(),754 m_animation->timingFunction().y1(),755 m_animation->timingFunction().x2(),756 m_animation->timingFunction().y2(),757 t, m_animation->duration());758 return tt;827 double result = solveCubicBezierFunction(m_animation->timingFunction().x1(), 828 m_animation->timingFunction().y1(), 829 m_animation->timingFunction().x2(), 830 m_animation->timingFunction().y2(), 831 fractionalTime, m_animation->duration()); 832 return result; 759 833 } 760 834 … … 766 840 ASSERT(elapsedDuration >= 0); 767 841 768 double totalDuration = m_animation->duration(); 842 double totalDuration = -1; 843 if (m_animation->iterationCount() > 0) 844 totalDuration = m_animation->duration() * m_animation->iterationCount(); 845 769 846 double durationLeft = 0; 770 847 double nextIterationTime = totalDuration; … … 840 917 TransformOperations result; 841 918 for (unsigned i = 0; i < size; i++) { 842 TransformOperation* fromOp = i < fromSize ? from[i].get(): 0;843 TransformOperation* toOp = i < toSize ? to[i].get(): 0;844 TransformOperation* blendedOp = toOp ? toOp->blend(fromOp, progress) : fromOp->blend(0, progress, true);919 RefPtr<TransformOperation> fromOp = i < fromSize ? from[i] : 0; 920 RefPtr<TransformOperation> toOp = i < toSize ? to[i] : 0; 921 RefPtr<TransformOperation> blendedOp = toOp ? toOp->blend(fromOp.get(), progress) : fromOp->blend(0, progress, true); 845 922 if (blendedOp) 846 923 result.append(blendedOp); … … 947 1024 }; 948 1025 949 class PropertyWrapperIntSize : public PropertyWrapperGetter<IntSize> {950 public:951 PropertyWrapperIntSize(int prop, IntSize (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const IntSize&))952 : PropertyWrapperGetter<IntSize>(prop, getter)953 , m_setter(setter)954 { }955 956 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const957 {958 IntSize sizea = (a->*m_getter)();959 IntSize sizeb = (b->*m_getter)();960 961 return (sizea == sizeb);962 }963 964 virtual void blend(RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) const965 {966 IntSize sizea = (a->*m_getter)();967 IntSize sizeb = (b->*m_getter)();968 969 (dst->*m_setter)(blendFunc(sizea, sizeb, prog));970 }971 972 private:973 void (RenderStyle::*m_setter)(const IntSize&);974 };975 976 1026 class PropertyWrapperMaybeInvalidColor : public PropertyWrapperBase { 977 1027 public: … … 1031 1081 void styleAvailable(); 1032 1082 1033 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property ) const;1083 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const; 1034 1084 1035 1085 static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b); … … 1118 1168 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX)); 1119 1169 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY)); 1120 gPropertyWrappers->append(new PropertyWrapper IntSize(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));1121 gPropertyWrappers->append(new PropertyWrapper IntSize(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));1122 gPropertyWrappers->append(new PropertyWrapper IntSize(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));1123 gPropertyWrappers->append(new PropertyWrapper IntSize(CSSPropertyWebkitBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));1170 gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius)); 1171 gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius)); 1172 gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius)); 1173 gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius)); 1124 1174 gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility)); 1125 1175 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom)); … … 1303 1353 } 1304 1354 1305 bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* obj, int property ) const1355 bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const 1306 1356 { 1307 1357 CompositeAnimation* animation = m_compositeAnimations.get(obj); 1308 1358 if (!animation) return false; 1309 1310 return animation->isAnimatingProperty(property );1359 1360 return animation->isAnimatingProperty(property, isRunningNow); 1311 1361 } 1312 1362 … … 1407 1457 } 1408 1458 1459 void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) 1460 { 1461 // Nothing to do if we don't have any animations, and didn't have any before 1462 if (m_keyframeAnimations.isEmpty() && !targetStyle->hasAnimations()) 1463 return; 1464 1465 // Nothing to do if the current and target animations are the same 1466 if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations())) 1467 return; 1468 1469 int numAnims = 0; 1470 bool animsChanged = false; 1471 1472 // see if the lists match 1473 if (targetStyle->animations()) { 1474 for (size_t i = 0; i < targetStyle->animations()->size(); ++i) { 1475 const Animation* anim = (*targetStyle->animations())[i].get(); 1476 1477 if (!anim->isValidAnimation()) 1478 animsChanged = true; 1479 else { 1480 AtomicString name(anim->name()); 1481 KeyframeAnimation* kfAnim = m_keyframeAnimations.get(name.impl()); 1482 if (!kfAnim || !kfAnim->animationsMatch(anim)) 1483 animsChanged = true; 1484 else 1485 if (anim) { 1486 // animations match, but play states may differ. update if needed 1487 kfAnim->updatePlayState(anim->playState() == AnimPlayStatePlaying); 1488 1489 // set the saved animation to this new one, just in case the play state has changed 1490 kfAnim->setAnimation(anim); 1491 } 1492 } 1493 ++numAnims; 1494 } 1495 } 1496 1497 if (!animsChanged && m_keyframeAnimations.size() != numAnims) 1498 animsChanged = true; 1499 1500 if (!animsChanged) 1501 return; 1502 1503 // animations have changed, update the list 1504 resetAnimations(renderer); 1505 1506 if (!targetStyle->animations()) 1507 return; 1508 1509 // add all the new animations 1510 int index = 0; 1511 for (size_t i = 0; i < targetStyle->animations()->size(); ++i) { 1512 const Animation* anim = (*targetStyle->animations())[i].get(); 1513 1514 if (!anim->isValidAnimation()) 1515 continue; 1516 1517 // don't bother adding the animation if it has no keyframes or won't animate 1518 if ((anim->duration() || anim->delay()) && anim->iterationCount() && 1519 anim->keyframeList().get() && !anim->keyframeList()->isEmpty()) { 1520 KeyframeAnimation* kfanim = new KeyframeAnimation(const_cast<Animation*>(anim), renderer, index++, this); 1521 m_keyframeAnimations.set(kfanim->name().impl(), kfanim); 1522 } 1523 } 1524 } 1525 1526 KeyframeAnimation* CompositeAnimation::findKeyframeAnimation(const AtomicString& name) 1527 { 1528 return m_keyframeAnimations.get(name.impl()); 1529 } 1530 1409 1531 RenderStyle* CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) 1410 1532 { … … 1425 1547 } 1426 1548 } 1549 1550 updateKeyframeAnimations(renderer, currentStyle, targetStyle); 1551 1552 // Now that we have animation objects ready, let them know about the new goal state. We want them 1553 // to fill in a RenderStyle*& only if needed. 1554 if (targetStyle->hasAnimations()) { 1555 for (size_t i = 0; i < targetStyle->animations()->size(); ++i) { 1556 const Animation* anim = (*targetStyle->animations())[i].get(); 1557 1558 if (anim->isValidAnimation()) { 1559 AtomicString name(anim->name()); 1560 KeyframeAnimation* keyframeAnim = m_keyframeAnimations.get(name.impl()); 1561 if (keyframeAnim) 1562 keyframeAnim->animate(this, renderer, currentStyle, targetStyle, resultStyle); 1563 } 1564 } 1565 } 1427 1566 1428 1567 cleanupFinishedAnimations(renderer); 1429 1568 1430 1569 return resultStyle ? resultStyle : targetStyle; 1431 1570 } … … 1439 1578 ImplicitAnimation* transition = it->second; 1440 1579 transition->setAnimating(inAnimating); 1580 } 1581 1582 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1583 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1584 KeyframeAnimation* anim = it->second; 1585 anim->setAnimating(inAnimating); 1441 1586 } 1442 1587 } … … 1450 1595 return true; 1451 1596 } 1597 1598 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1599 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1600 KeyframeAnimation* anim = it->second; 1601 if (anim && !anim->paused() && anim->animating() && anim->active()) 1602 return true; 1603 } 1604 1452 1605 return false; 1453 1606 } … … 1462 1615 } 1463 1616 m_transitions.clear(); 1617 } 1618 1619 void CompositeAnimation::resetAnimations(RenderObject* renderer) 1620 { 1621 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1622 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1623 KeyframeAnimation* anim = it->second; 1624 delete anim; 1625 } 1626 m_keyframeAnimations.clear(); 1464 1627 } 1465 1628 … … 1490 1653 m_transitions.remove(*it); 1491 1654 } 1655 1656 // Make a list of animations to be deleted 1657 Vector<AtomicStringImpl*> finishedAnimations; 1658 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1659 1660 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1661 KeyframeAnimation* anim = it->second; 1662 if (!anim) 1663 continue; 1664 if (anim->postactive() && !anim->waitingForEndEvent()) 1665 finishedAnimations.append(anim->name().impl()); 1666 } 1667 1668 // delete them 1669 for (Vector<AtomicStringImpl*>::iterator it = finishedAnimations.begin(); it != finishedAnimations.end(); ++it) { 1670 KeyframeAnimation* kfanim = m_keyframeAnimations.get(*it); 1671 if (kfanim) { 1672 kfanim->reset(renderer); 1673 delete kfanim; 1674 } 1675 m_keyframeAnimations.remove(*it); 1676 } 1677 } 1678 1679 void CompositeAnimation::setAnimationStartTime(double t) 1680 { 1681 // set start time on all animations waiting for it 1682 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1683 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1684 KeyframeAnimation* anim = it->second; 1685 if (anim && anim->waitingForStartTime()) 1686 anim->updateStateMachine(AnimationBase::STATE_INPUT_START_TIME_SET, t); 1687 } 1492 1688 } 1493 1689 … … 1511 1707 m_suspended = true; 1512 1708 1709 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1710 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1711 KeyframeAnimation* anim = it->second; 1712 if (anim) 1713 anim->updatePlayState(false); 1714 } 1715 1513 1716 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1514 1717 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1515 1718 ImplicitAnimation* anim = it->second; 1516 if (anim && anim->hasStyle()) {1719 if (anim && anim->hasStyle()) 1517 1720 anim->updatePlayState(false); 1518 }1519 1721 } 1520 1722 } … … 1526 1728 1527 1729 m_suspended = false; 1528 1730 1731 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1732 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1733 KeyframeAnimation* anim = it->second; 1734 if (anim && anim->playStatePlaying()) 1735 anim->updatePlayState(true); 1736 } 1737 1529 1738 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1530 1739 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1531 1740 ImplicitAnimation* anim = it->second; 1532 if (anim && anim->hasStyle()) {1741 if (anim && anim->hasStyle()) 1533 1742 anim->updatePlayState(true); 1534 }1535 1743 } 1536 1744 } … … 1556 1764 } 1557 1765 1766 static inline bool compareAnimationIndices(const KeyframeAnimation* a, const KeyframeAnimation* b) 1767 { 1768 return a->index() < b->index(); 1769 } 1770 1558 1771 void CompositeAnimation::styleAvailable() 1559 1772 { 1560 1773 if (m_numStyleAvailableWaiters == 0) 1561 1774 return; 1775 1776 // We have to go through animations in the order in which they appear in 1777 // the style, because order matters for additivity. 1778 Vector<KeyframeAnimation*> animations(m_keyframeAnimations.size()); 1779 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1780 size_t i = 0; 1781 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1782 KeyframeAnimation* anim = it->second; 1783 // We can't just insert based on anim->index() because invalid animations don't 1784 // make it into the hash. 1785 animations[i++] = anim; 1786 } 1787 1788 if (animations.size() > 1) 1789 std::stable_sort(animations.begin(), animations.end(), compareAnimationIndices); 1790 1791 for (i = 0; i < animations.size(); ++i) { 1792 KeyframeAnimation* anim = animations[i]; 1793 if (anim && anim->waitingForStyleAvailable()) 1794 anim->updateStateMachine(AnimationBase::STATE_INPUT_STYLE_AVAILABLE, -1); 1795 } 1562 1796 1563 1797 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); … … 1569 1803 } 1570 1804 1571 bool CompositeAnimation::isAnimatingProperty(int property) const 1572 { 1805 bool CompositeAnimation::isAnimatingProperty(int property, bool isRunningNow) const 1806 { 1807 AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); 1808 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { 1809 KeyframeAnimation* anim = it->second; 1810 if (anim && anim->isAnimatingProperty(property, isRunningNow)) 1811 return true; 1812 } 1813 1573 1814 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1574 1815 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1575 1816 ImplicitAnimation* anim = it->second; 1576 if (anim && anim->isAnimatingProperty(property ))1817 if (anim && anim->isAnimatingProperty(property, isRunningNow)) 1577 1818 return true; 1578 1819 } … … 1581 1822 1582 1823 void ImplicitAnimation::animate(CompositeAnimation* animation, RenderObject* renderer, const RenderStyle* currentStyle, 1583 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle)1824 const RenderStyle* targetStyle, RenderStyle*& animatedStyle) 1584 1825 { 1585 1826 if (paused()) … … 1589 1830 // If so, send back the targetStyle (it will get tossed later) 1590 1831 if (postactive()) { 1591 if (! ioAnimatedStyle)1592 ioAnimatedStyle = const_cast<RenderStyle*>(targetStyle);1832 if (!animatedStyle) 1833 animatedStyle = const_cast<RenderStyle*>(targetStyle); 1593 1834 return; 1594 1835 } … … 1600 1841 // Run a cycle of animation. 1601 1842 // We know we will need a new render style, so make one if needed 1602 if (! ioAnimatedStyle)1603 ioAnimatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle);1843 if (!animatedStyle) 1844 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); 1604 1845 1605 1846 double prog = progress(1, 0); 1606 bool needsAnim = AnimationControllerPrivate::blendProperties(m_property, ioAnimatedStyle, m_fromStyle, m_toStyle, prog);1847 bool needsAnim = AnimationControllerPrivate::blendProperties(m_property, animatedStyle, m_fromStyle, m_toStyle, prog); 1607 1848 if (needsAnim) 1608 1849 setAnimating(); 1609 }1610 1611 bool ImplicitAnimation::startAnimation(double beginTime)1612 {1613 return false;1614 }1615 1616 void ImplicitAnimation::endAnimation(bool reset)1617 {1618 1850 } 1619 1851 … … 1630 1862 bool ImplicitAnimation::sendTransitionEvent(const AtomicString& inEventType, double inElapsedTime) 1631 1863 { 1632 return false; // didn't dispatch an event 1864 // FIXME: event dispatching code will go here 1865 return false; // Didn't dispatch an event 1633 1866 } 1634 1867 … … 1680 1913 } 1681 1914 1915 void KeyframeAnimation::animate(CompositeAnimation* animation, RenderObject* renderer, const RenderStyle* currentStyle, 1916 const RenderStyle* targetStyle, RenderStyle*& animatedStyle) 1917 { 1918 // if we have not yet started, we will not have a valid start time, so just start the animation if needed 1919 if (isnew() && m_animation->playState() == AnimPlayStatePlaying) 1920 updateStateMachine(STATE_INPUT_START_ANIMATION, -1); 1921 1922 // If we get this far and the animation is done, it means we are cleaning up a just finished animation. 1923 // If so, we need to send back the targetStyle 1924 if (postactive()) { 1925 if (!animatedStyle) 1926 animatedStyle = const_cast<RenderStyle*>(targetStyle); 1927 return; 1928 } 1929 1930 // if we are waiting for the start timer, we don't want to change the style yet 1931 // Special case - if the delay time is 0, then we do want to set the first frame of the 1932 // animation right away. This avoids a flash when the animation starts 1933 if (waitingToStart() && m_animation->delay() > 0) 1934 return; 1935 1936 // FIXME: we need to be more efficient about determining which keyframes we are animating between. 1937 // We should cache the last pair or something 1938 1939 // find the first key 1940 double elapsedTime = (m_startTime > 0) ? ((!paused() ? currentTime() : m_pauseTime) - m_startTime) : 0.0; 1941 if (elapsedTime < 0.0) 1942 elapsedTime = 0.0; 1943 1944 double t = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1.0; 1945 int i = (int) t; 1946 t -= i; 1947 if (m_animation->direction() && (i & 1)) 1948 t = 1 - t; 1949 1950 RenderStyle* fromStyle = 0; 1951 RenderStyle* toStyle = 0; 1952 double scale = 1.0; 1953 double offset = 0.0; 1954 if (m_keyframes.get()) { 1955 Vector<KeyframeValue>::const_iterator end = m_keyframes->endKeyframes(); 1956 for (Vector<KeyframeValue>::const_iterator it = m_keyframes->beginKeyframes(); it != end; ++it) { 1957 if (t < it->key) { 1958 // The first key should always be 0, so we should never succeed on the first key 1959 if (!fromStyle) 1960 break; 1961 scale = 1.0 / (it->key - offset); 1962 toStyle = const_cast<RenderStyle*>(&(it->style)); 1963 break; 1964 } 1965 1966 offset = it->key; 1967 fromStyle = const_cast<RenderStyle*>(&(it->style)); 1968 } 1969 } 1970 1971 // if either style is 0 we have an invalid case, just stop the animation 1972 if (!fromStyle || !toStyle) { 1973 updateStateMachine(STATE_INPUT_END_ANIMATION, -1); 1974 return; 1975 } 1976 1977 // run a cycle of animation. 1978 // We know we will need a new render style, so make one if needed 1979 if (!animatedStyle) 1980 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); 1981 1982 double prog = progress(scale, offset); 1983 1984 HashSet<int>::const_iterator end = m_keyframes->endProperties(); 1985 for (HashSet<int>::const_iterator it = m_keyframes->beginProperties(); it != end; ++it) { 1986 if (AnimationControllerPrivate::blendProperties(*it, animatedStyle, fromStyle, toStyle, prog)) 1987 setAnimating(); 1988 } 1989 } 1990 1991 void KeyframeAnimation::endAnimation(bool reset) 1992 { 1993 if (m_object) { 1994 // restore the original (unanimated) style 1995 setChanged(m_object->element()); 1996 } 1997 } 1998 1999 void KeyframeAnimation::onAnimationStart(double inElapsedTime) 2000 { 2001 sendAnimationEvent(EventNames::webkitAnimationStartEvent, inElapsedTime); 2002 } 2003 2004 void KeyframeAnimation::onAnimationIteration(double inElapsedTime) 2005 { 2006 sendAnimationEvent(EventNames::webkitAnimationIterationEvent, inElapsedTime); 2007 } 2008 2009 void KeyframeAnimation::onAnimationEnd(double inElapsedTime) 2010 { 2011 // FIXME: set the unanimated style on the element 2012 if (!sendAnimationEvent(EventNames::webkitAnimationEndEvent, inElapsedTime)) { 2013 // we didn't dispatch an event, which would call endAnimation(), so we'll just end 2014 // it here. 2015 endAnimation(true); 2016 } 2017 } 2018 2019 bool KeyframeAnimation::sendAnimationEvent(const AtomicString& inEventType, double inElapsedTime) 2020 { 2021 // FIXME: Event dispatch goes here 2022 return false; // didn't dispatch an event 2023 } 2024 2025 void KeyframeAnimation::overrideAnimations() 2026 { 2027 // this will override implicit animations that match the properties in the keyframe animation 2028 HashSet<int>::const_iterator end = m_keyframes->endProperties(); 2029 for (HashSet<int>::const_iterator it = m_keyframes->beginProperties(); it != end; ++it) 2030 compositeAnimation()->overrideImplicitAnimations(*it); 2031 } 2032 2033 void KeyframeAnimation::resumeOverriddenAnimations() 2034 { 2035 // this will resume overridden implicit animations 2036 HashSet<int>::const_iterator end = m_keyframes->endProperties(); 2037 for (HashSet<int>::const_iterator it = m_keyframes->beginProperties(); it != end; ++it) 2038 compositeAnimation()->resumeOverriddenImplicitAnimations(*it); 2039 } 2040 2041 bool KeyframeAnimation::affectsProperty(int property) const 2042 { 2043 HashSet<int>::const_iterator end = m_keyframes->endProperties(); 2044 for (HashSet<int>::const_iterator it = m_keyframes->beginProperties(); it != end; ++it) { 2045 if ((*it) == property) 2046 return true; 2047 } 2048 return false; 2049 } 2050 1682 2051 AnimationController::AnimationController(Frame* frame) 1683 2052 : m_data(new AnimationControllerPrivate(frame)) … … 1708 2077 RenderStyle* oldStyle = renderer->style(); 1709 2078 1710 if ((!oldStyle || !oldStyle->transitions()) && !newStyle->transitions()) 2079 if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && 2080 (!newStyle->animations() && !newStyle->transitions())) 1711 2081 return newStyle; 1712 2082 … … 1734 2104 } 1735 2105 1736 bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const 1737 { 1738 return m_data->isAnimatingPropertyOnRenderer(obj, property); 2106 void AnimationController::setAnimationStartTime(RenderObject* obj, double t) 2107 { 2108 CompositeAnimation* rendererAnimations = m_data->accessCompositeAnimation(obj); 2109 rendererAnimations->setAnimationStartTime(t); 2110 } 2111 2112 void AnimationController::setTransitionStartTime(RenderObject* obj, int property, double t) 2113 { 2114 CompositeAnimation* rendererAnimations = m_data->accessCompositeAnimation(obj); 2115 rendererAnimations->setTransitionStartTime(property, t); 2116 } 2117 2118 bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const 2119 { 2120 return m_data->isAnimatingPropertyOnRenderer(obj, property, isRunningNow); 1739 2121 } 1740 2122 -
trunk/WebCore/page/AnimationController.h
r35545 r35646 49 49 RenderStyle* updateAnimations(RenderObject*, RenderStyle* newStyle); 50 50 51 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const; 51 void setAnimationStartTime(RenderObject* obj, double t); 52 void setTransitionStartTime(RenderObject* obj, int property, double t); 53 54 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const; 52 55 53 56 void suspendAnimations(Document* document); -
trunk/WebCore/rendering/RenderObject.cpp
r35551 r35646 2156 2156 void RenderObject::setAnimatableStyle(RenderStyle* style) 2157 2157 { 2158 if (!isText() && m_style &&style)2158 if (!isText() && style) 2159 2159 style = animation()->updateAnimations(this, style); 2160 2160 -
trunk/WebCore/rendering/style/RenderStyle.h
r35615 r35646 1914 1914 const NinePieceImage& borderImage() const { return surround->border.image; } 1915 1915 1916 IntSizeborderTopLeftRadius() const { return surround->border.topLeft; }1917 IntSizeborderTopRightRadius() const { return surround->border.topRight; }1918 IntSizeborderBottomLeftRadius() const { return surround->border.bottomLeft; }1919 IntSizeborderBottomRightRadius() const { return surround->border.bottomRight; }1916 const IntSize& borderTopLeftRadius() const { return surround->border.topLeft; } 1917 const IntSize& borderTopRightRadius() const { return surround->border.topRight; } 1918 const IntSize& borderBottomLeftRadius() const { return surround->border.bottomLeft; } 1919 const IntSize& borderBottomRightRadius() const { return surround->border.bottomRight; } 1920 1920 bool hasBorderRadius() const { return surround->border.hasBorderRadius(); } 1921 1921
Note: See TracChangeset
for help on using the changeset viewer.