Changeset 34382 in webkit


Ignore:
Timestamp:
Jun 5, 2008 1:51:32 PM (16 years ago)
Author:
hyatt@apple.com
Message:

2008-06-04 David Hyatt <hyatt@apple.com>

Fix for <rdar://problem/5957994> Height doesn't animate

Improve the behavior when transitions are dynamically changed. Make sure to leave older transitions
running and let them obsolete themselves when they finish.

Reviewed by Dan Bernstein

Added WebCore/manual-tests/transitions2.html (must be tested manually)

  • manual-tests/transitions.html:
  • manual-tests/transitions2.html: Added.
  • page/AnimationController.cpp: (WebCore::ImplicitAnimation::property): (WebCore::ImplicitAnimation::setFinished): (WebCore::ImplicitAnimation::markedForDeath): (WebCore::ImplicitAnimation::setMarkedForDeath): (WebCore::ImplicitAnimation::ImplicitAnimation): (WebCore::ImplicitAnimation::reset): (WebCore::ImplicitAnimation::animate): (WebCore::CompositeImplicitAnimation::animate):
Location:
trunk/WebCore
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r34381 r34382  
     12008-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
    1242008-06-05  Eric Seidel  <eric@webkit.org>
    225
  • trunk/WebCore/manual-tests/transitions.html

    r30319 r34382  
    3232        {className:"", description:"instantly change into a small green square then animate to yellow over 5 seconds"},
    3333        {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 rectange over 2 seconds"},
     34        {className:"green", description:"instantly change into a green square and then animate to a rectangle over 2 seconds"},
    3535        {className:"", description:"instantly change into a small green square then animate to yellow over 5 seconds"},
    3636        {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"},
    3838        {className:"", description:"instantly change into a rectangle then animate into a square over 2 seconds"}
    3939    ];
  • trunk/WebCore/page/AnimationController.cpp

    r32334 r34382  
    6969    double progress() const;
    7070
     71    int property() const { return m_property; }
     72   
    7173    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; }
    7278
    7379private:
     
    8793    bool m_paused;
    8894    double m_pauseTime;
     95   
     96    bool m_stale;
    8997};
    9098
     
    96104
    97105    bool animating() const;
    98 
    99     bool hasAnimationForProperty(int prop) const { return m_animations.contains(prop); }
    100106
    101107    void reset(RenderObject*);
     
    117123, m_paused(false)
    118124, m_pauseTime(m_startTime)
     125, m_stale(false)
    119126{
    120127}
     
    127134void ImplicitAnimation::reset(RenderObject* renderer, RenderStyle* from, RenderStyle* to)
    128135{
     136    setFinished(false);
     137
    129138    if (m_fromStyle)
    130139        m_fromStyle->deref(renderer->renderArena());
     
    137146    if (m_toStyle)
    138147        m_toStyle->ref();
    139     m_finished = false;
    140148    if (from || to)
    141149        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);
    142171}
    143172
     
    227256
    228257#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()) {\
    230259        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) { \
    233264        if (m_fromStyle->getter() != m_toStyle->getter()) {\
    234             m_finished = false; \
     265            setFinished(false); \
    235266            if (!animatedStyle) \
    236267                animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \
     
    242273
    243274#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()) { \
    245276        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) { \
    248281        Color fromColor = m_fromStyle->getter(); \
    249282        Color toColor = m_toStyle->getter(); \
     
    254287                toColor = m_toStyle->color(); \
    255288            if (fromColor != toColor) {\
    256                 m_finished = false; \
     289                setFinished(false); \
    257290                if (!animatedStyle) \
    258291                    animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \
     
    265298
    266299#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())) { \
    268301        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) { \
    271306        if (m_fromStyle->getter() && m_toStyle->getter() && *m_fromStyle->getter() != *m_toStyle->getter()) {\
    272             m_finished = false; \
     307            setFinished(false); \
    273308            if (!animatedStyle) \
    274309                animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \
     
    284319    // every single animatable property.  For now we'll just diff the styles to ask that question,
    285320    // 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))) {
    287322        reset(renderer, currentStyle, targetStyle);
     323        if (stale())
     324            return;
     325    }
    288326
    289327    // FIXME: Blow up shorthands so that they can be honored.
    290     m_finished = true;
     328    setFinished(true);
    291329    BLEND(CSSPropertyLeft, left, setLeft);
    292330    BLEND(CSSPropertyRight, right, setRight);
     
    347385    const Transition* currentTransitions = currentStyle->transitions();
    348386    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
    358389    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).
    359392        for (const Transition* transition = currentTransitions; transition; transition = transition->next()) {
    360393            int property = transition->property();
     
    367400        }
    368401    }
    369 
     402       
    370403    // Now that we have animation objects ready, let them know about the new goal state.  We want them
    371404    // to fill in a RenderStyle*& only if needed.
    372405    RenderStyle* result = 0;
    373406    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       
    375430        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    }
    376464
    377465    if (result)
Note: See TracChangeset for help on using the changeset viewer.