Changeset 35646 in webkit


Ignore:
Timestamp:
Aug 8, 2008 1:44:14 PM (16 years ago)
Author:
dino@apple.com
Message:

Execute CSS Animations using new AnimationController
https://bugs.webkit.org/show_bug.cgi?id=20119

I still need to file some follow-on bugs that EricS noticed.

Reviewed by Dave Hyatt

Some new tests:

  • manual-tests/animate-duration.html: Added.
  • manual-tests/animate-left.html: Added.
  • manual-tests/animate-none.html: Added.
  • css/CSSStyleSelector.cpp:
  • dom/Document.cpp:
    • don't redo style when page is place into cache
  • page/AnimationController.cpp:
  • page/AnimationController.h:
    • execute the animations
  • rendering/RenderObject.cpp:
  • rendering/style/RenderStyle.h:
    • make border radii const (for blending)
Location:
trunk/WebCore
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r35645 r35646  
     12008-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
    1252008-08-08  Kevin McCullough  <kmccullough@apple.com>
    226
  • trunk/WebCore/css/CSSStyleSelector.cpp

    r35580 r35646  
    196196    } \
    197197    \
    198     /* Reset any remaining layers to not have the property set. */ \
     198    /* Reset any remaining animations to not have the property set. */ \
    199199    for ( ; i < list->size(); ++i) \
    200200        (*list)[i]->clear##Prop(); \
     
    214214size_t childIndex = 0; \
    215215if (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. */ \
    217217    CSSValueList* valueList = static_cast<CSSValueList*>(value); \
    218218    for (unsigned int i = 0; i < valueList->length(); i++) { \
     
    229229} \
    230230for ( ; 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. */ \
    232232    (*list)[childIndex]->clear##Prop(); \
    233233} \
     
    245245    } \
    246246    \
    247     /* Reset any remaining layers to not have the property set. */ \
     247    /* Reset any remaining transitions to not have the property set. */ \
    248248    for ( ; i < list->size(); ++i) \
    249249        (*list)[i]->clear##Prop(); \
     
    263263size_t childIndex = 0; \
    264264if (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. */ \
    266266    CSSValueList* valueList = static_cast<CSSValueList*>(value); \
    267267    for (unsigned int i = 0; i < valueList->length(); i++) { \
     
    278278} \
    279279for ( ; 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. */ \
    281281    (*list)[childIndex]->clear##Prop(); \
    282282} \
  • trunk/WebCore/dom/Document.cpp

    r35545 r35646  
    11621162void Document::updateRendering()
    11631163{
    1164     if (hasChangedChild())
     1164    if (hasChangedChild() && !inPageCache())
    11651165        recalcStyle(NoChange);
    11661166   
    1167     // tell the animation controller that the style is available and it can start animations
     1167    // Tell the animation controller that the style is available and it can start animations
    11681168    if (m_frame)
    11691169        m_frame->animation()->styleAvailable();
     
    15481548    if (f)
    15491549        f->loader()->startIconLoader();
     1550
     1551    // Resume the animations (or start them)
     1552    if (f)
     1553        f->animation()->resumeAnimations(this);
    15501554
    15511555    dispatchImageLoadEventsNow();
  • trunk/WebCore/page/AnimationController.cpp

    r35568 r35646  
    158158
    159159class ImplicitAnimation;
     160class KeyframeAnimation;
    160161class AnimationControllerPrivate;
    161162
     
    174175    {
    175176        deleteAllValues(m_transitions);
     177        deleteAllValues(m_keyframeAnimations);
    176178    }
    177179   
     
    183185    bool hasAnimationForProperty(int prop) const { return m_transitions.contains(prop); }
    184186   
    185     void setTransitionStartTime(int property, double t);
    186    
    187187    void resetTransitions(RenderObject*);
    188188    void resetAnimations(RenderObject*);
    189189   
    190190    void cleanupFinishedAnimations(RenderObject*);
     191
     192    void setAnimationStartTime(double t);
     193    void setTransitionStartTime(int property, double t);
    191194   
    192195    void suspendAnimations();
     
    199202    void styleAvailable();
    200203   
    201     bool isAnimatingProperty(int property) const;
     204    bool isAnimatingProperty(int property, bool isRunningNow) const;
    202205   
    203206    void setWaitingForStyleAvailable(bool waiting);
     207
    204208protected:
    205209    void updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle);
     210    void updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle);
     211
     212    KeyframeAnimation* findKeyframeAnimation(const AtomicString& name);
    206213   
    207214private:
    208215    typedef HashMap<int, ImplicitAnimation*> CSSPropertyTransitionsMap;
     216    typedef HashMap<AtomicStringImpl*, KeyframeAnimation*>  AnimationNameMap;
    209217   
    210218    CSSPropertyTransitionsMap   m_transitions;
     219    AnimationNameMap            m_keyframeAnimations;
    211220    bool                        m_suspended;
    212221    AnimationControllerPrivate* m_animationController;
     
    271280   
    272281    // 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::
    275282    void onAnimationStartResponse(double startTime);
    276283   
    277284    // Called to change to or from paused state
    278285    void updatePlayState(bool running);
    279     bool playStatePlaying() const { return m_animation; }
     286    bool playStatePlaying() const { return m_animation && m_animation->playState() == AnimPlayStatePlaying; }
    280287   
    281288    bool waitingToStart() const { return m_animState == STATE_NEW || m_animState == STATE_START_WAIT_TIMER; }
     
    303310   
    304311    virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle,
    305                          const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle) { }
     312                         const RenderStyle* targetStyle, RenderStyle*& animatedStyle) { }
    306313    virtual void reset(RenderObject* renderer, const RenderStyle* from = 0, const RenderStyle* to = 0) { }
    307314   
     
    324331    // Does this animation/transition involve the given property?
    325332    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);
    329339    }
    330340       
     
    359369    double m_startTime;
    360370    double m_pauseTime;
    361     RenderObject*   m_object;
     371    RenderObject* m_object;
    362372   
    363373    AnimationTimerCallback m_animationTimerCallback;
     
    396406   
    397407    virtual void onAnimationEnd(double inElapsedTime);
    398     virtual bool startAnimation(double beginTime);
    399     virtual void endAnimation(bool reset);
    400408   
    401409    virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle,
    402                          const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle);
     410                         const RenderStyle* targetStyle, RenderStyle*& animatedStyle);
    403411    virtual void reset(RenderObject* renderer, const RenderStyle* from = 0, const RenderStyle* to = 0);
    404412   
     
    442450    m_anim->animationEventDispatcherFired(m_element.get(), m_name, m_property, m_reset, m_eventType, m_elapsedTime);
    443451}
    444    
     452
     453class KeyframeAnimation : public AnimationBase {
     454public:
     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
     479protected:
     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
     497private:
     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
    445505AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim)
    446506: m_animState(STATE_NEW)
     
    461521void AnimationBase::updateStateMachine(AnimStateInput input, double param)
    462522{
    463     // if we get a RESTART then we force a new animation, regardless of state
     523    // If we get a RESTART then we force a new animation, regardless of state
    464524    if (input == STATE_INPUT_MAKE_NEW) {
    465525        if (m_animState == STATE_START_WAIT_STYLE_AVAILABLE)
     
    510570    }
    511571   
    512     // execute state machine
     572    // Execute state machine
    513573    switch(m_animState) {
    514574        case STATE_NEW:
     
    554614               
    555615                // Send start event, if needed
    556                 onAnimationStart(0.0f); // the elapsedTime is always 0 here
     616                onAnimationStart(0.0f); // The elapsedTime is always 0 here
    557617               
    558618                // Start the animation
     
    715775    if (!element)
    716776        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    }
    717786}
    718787
     
    733802   
    734803    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))
    737808        return 1.0;
    738809   
    739810    // 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
    741812    // 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;
    745819   
    746820    if (scale != 1 || offset != 0)
    747         t = (t - offset) * scale;
     821        fractionalTime = (fractionalTime - offset) * scale;
    748822   
    749823    if (m_animation->timingFunction().type() == LinearTimingFunction)
    750         return t;
     824        return fractionalTime;
    751825   
    752826    // 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;
    759833}
    760834
     
    766840    ASSERT(elapsedDuration >= 0);
    767841   
    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
    769846    double durationLeft = 0;
    770847    double nextIterationTime = totalDuration;
     
    840917    TransformOperations result;
    841918    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);
    845922        if (blendedOp)
    846923            result.append(blendedOp);
     
    9471024};
    9481025
    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) const
    957     {
    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) const
    965     {
    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 
    9761026class PropertyWrapperMaybeInvalidColor : public PropertyWrapperBase {
    9771027public:
     
    10311081    void styleAvailable();
    10321082   
    1033     bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const;
     1083    bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const;
    10341084   
    10351085    static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b);
     
    11181168        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX));
    11191169        gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY));
    1120         gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
    1121         gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
    1122         gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
    1123         gPropertyWrappers->append(new PropertyWrapperIntSize(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));
    11241174        gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility));
    11251175        gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom));
     
    13031353}
    13041354
    1305 bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const
     1355bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const
    13061356{
    13071357    CompositeAnimation* animation = m_compositeAnimations.get(obj);
    13081358    if (!animation) return false;
    1309    
    1310     return animation->isAnimatingProperty(property);
     1359
     1360    return animation->isAnimatingProperty(property, isRunningNow);
    13111361}
    13121362
     
    14071457}
    14081458
     1459void 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
     1526KeyframeAnimation* CompositeAnimation::findKeyframeAnimation(const AtomicString& name)
     1527{
     1528    return m_keyframeAnimations.get(name.impl());
     1529}
     1530
    14091531RenderStyle* CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
    14101532{
     
    14251547        }
    14261548    }
     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    }
    14271566   
    14281567    cleanupFinishedAnimations(renderer);
    1429    
     1568
    14301569    return resultStyle ? resultStyle : targetStyle;
    14311570}
     
    14391578        ImplicitAnimation*  transition = it->second;
    14401579        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);
    14411586    }
    14421587}
     
    14501595            return true;
    14511596    }
     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
    14521605    return false;
    14531606}
     
    14621615    }
    14631616    m_transitions.clear();
     1617}
     1618
     1619void 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();
    14641627}
    14651628
     
    14901653        m_transitions.remove(*it);
    14911654    }
     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
     1679void 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    }
    14921688}
    14931689
     
    15111707    m_suspended = true;
    15121708
     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
    15131716    CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
    15141717    for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
    15151718        ImplicitAnimation* anim = it->second;
    1516         if (anim && anim->hasStyle()) {
     1719        if (anim && anim->hasStyle())
    15171720            anim->updatePlayState(false);
    1518         }
    15191721    }
    15201722}
     
    15261728   
    15271729    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   
    15291738    CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
    15301739    for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
    15311740        ImplicitAnimation* anim = it->second;
    1532         if (anim && anim->hasStyle()) {
     1741        if (anim && anim->hasStyle())
    15331742            anim->updatePlayState(true);
    1534         }
    15351743    }
    15361744}
     
    15561764}
    15571765
     1766static inline bool compareAnimationIndices(const KeyframeAnimation* a, const KeyframeAnimation* b)
     1767{
     1768    return a->index() < b->index();
     1769}
     1770
    15581771void CompositeAnimation::styleAvailable()
    15591772{
    15601773    if (m_numStyleAvailableWaiters == 0)
    15611774        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    }
    15621796   
    15631797    CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
     
    15691803}
    15701804
    1571 bool CompositeAnimation::isAnimatingProperty(int property) const
    1572 {
     1805bool 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   
    15731814    CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
    15741815    for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
    15751816        ImplicitAnimation* anim = it->second;
    1576         if (anim && anim->isAnimatingProperty(property))
     1817        if (anim && anim->isAnimatingProperty(property, isRunningNow))
    15771818            return true;
    15781819    }
     
    15811822
    15821823void ImplicitAnimation::animate(CompositeAnimation* animation, RenderObject* renderer, const RenderStyle* currentStyle,
    1583                                 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle)
     1824                                const RenderStyle* targetStyle, RenderStyle*& animatedStyle)
    15841825{
    15851826    if (paused())
     
    15891830    // If so, send back the targetStyle (it will get tossed later)
    15901831    if (postactive()) {
    1591         if (!ioAnimatedStyle)
    1592             ioAnimatedStyle = const_cast<RenderStyle*>(targetStyle);
     1832        if (!animatedStyle)
     1833            animatedStyle = const_cast<RenderStyle*>(targetStyle);
    15931834        return;
    15941835    }
     
    16001841    // Run a cycle of animation.
    16011842    // 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);
    16041845   
    16051846    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);
    16071848    if (needsAnim)
    16081849        setAnimating();
    1609 }
    1610 
    1611 bool ImplicitAnimation::startAnimation(double beginTime)
    1612 {
    1613     return false;
    1614 }
    1615 
    1616 void ImplicitAnimation::endAnimation(bool reset)
    1617 {
    16181850}
    16191851
     
    16301862bool ImplicitAnimation::sendTransitionEvent(const AtomicString& inEventType, double inElapsedTime)
    16311863{
    1632     return false; // didn't dispatch an event
     1864    // FIXME: event dispatching code will go here
     1865    return false; // Didn't dispatch an event
    16331866}
    16341867
     
    16801913}   
    16811914
     1915void 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
     1991void KeyframeAnimation::endAnimation(bool reset)
     1992{
     1993    if (m_object) {
     1994        // restore the original (unanimated) style
     1995        setChanged(m_object->element());
     1996    }
     1997}
     1998
     1999void KeyframeAnimation::onAnimationStart(double inElapsedTime)
     2000{
     2001    sendAnimationEvent(EventNames::webkitAnimationStartEvent, inElapsedTime);
     2002}
     2003
     2004void KeyframeAnimation::onAnimationIteration(double inElapsedTime)
     2005{
     2006    sendAnimationEvent(EventNames::webkitAnimationIterationEvent, inElapsedTime);
     2007}
     2008
     2009void 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
     2019bool KeyframeAnimation::sendAnimationEvent(const AtomicString& inEventType, double inElapsedTime)
     2020{
     2021    // FIXME: Event dispatch goes here
     2022    return false; // didn't dispatch an event
     2023}
     2024
     2025void 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
     2033void 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
     2041bool 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
    16822051AnimationController::AnimationController(Frame* frame)
    16832052: m_data(new AnimationControllerPrivate(frame))
     
    17082077    RenderStyle* oldStyle = renderer->style();
    17092078   
    1710     if ((!oldStyle || !oldStyle->transitions()) && !newStyle->transitions())
     2079    if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) &&
     2080                        (!newStyle->animations() && !newStyle->transitions()))
    17112081        return newStyle;
    17122082   
     
    17342104}
    17352105
    1736 bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const
    1737 {
    1738     return m_data->isAnimatingPropertyOnRenderer(obj, property);
     2106void AnimationController::setAnimationStartTime(RenderObject* obj, double t)
     2107{
     2108    CompositeAnimation* rendererAnimations = m_data->accessCompositeAnimation(obj);
     2109    rendererAnimations->setAnimationStartTime(t);
     2110}
     2111
     2112void AnimationController::setTransitionStartTime(RenderObject* obj, int property, double t)
     2113{
     2114    CompositeAnimation* rendererAnimations = m_data->accessCompositeAnimation(obj);
     2115    rendererAnimations->setTransitionStartTime(property, t);
     2116}
     2117
     2118bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* obj, int property, bool isRunningNow) const
     2119{
     2120    return m_data->isAnimatingPropertyOnRenderer(obj, property, isRunningNow);
    17392121}
    17402122
  • trunk/WebCore/page/AnimationController.h

    r35545 r35646  
    4949    RenderStyle* updateAnimations(RenderObject*, RenderStyle* newStyle);
    5050   
    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;
    5255   
    5356    void suspendAnimations(Document* document);
  • trunk/WebCore/rendering/RenderObject.cpp

    r35551 r35646  
    21562156void RenderObject::setAnimatableStyle(RenderStyle* style)
    21572157{
    2158     if (!isText() && m_style && style)
     2158    if (!isText() && style)
    21592159        style = animation()->updateAnimations(this, style);
    21602160
  • trunk/WebCore/rendering/style/RenderStyle.h

    r35615 r35646  
    19141914    const NinePieceImage& borderImage() const { return surround->border.image; }
    19151915
    1916     IntSize borderTopLeftRadius() const { return surround->border.topLeft; }
    1917     IntSize borderTopRightRadius() const { return surround->border.topRight; }
    1918     IntSize borderBottomLeftRadius() const { return surround->border.bottomLeft; }
    1919     IntSize borderBottomRightRadius() 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; }
    19201920    bool hasBorderRadius() const { return surround->border.hasBorderRadius(); }
    19211921
Note: See TracChangeset for help on using the changeset viewer.