Changeset 201818 in webkit


Ignore:
Timestamp:
Jun 8, 2016 11:46:43 AM (8 years ago)
Author:
dino@apple.com
Message:

Multiple selectors break keyframes animation
https://bugs.webkit.org/show_bug.cgi?id=158199
<rdar://problem/26652591>

Reviewed by Simon Fraser.

Source/WebCore:

If we came across a duplicate key entry in a keyframe, we
were replacing the existing entry, instead of merging.

Test: animations/duplicate-keys.html

  • css/CSSKeyframeRule.h:

(WebCore::StyleKeyframe::setKey): Add a way to set the key of a rule
as a number, rather than going through a string and the CSS parser.

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::keyframeStylesForAnimation): Check if the rule
has duplicates, and if it does, merge all the common entries.

  • rendering/style/KeyframeList.cpp:

(WebCore::KeyframeList::insert): Now that we've removed duplicates at
the processing time, we should never come across a duplicate while
building this list.

LayoutTests:

  • animations/duplicate-keys-expected.html: Added.
  • animations/duplicate-keys.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r201817 r201818  
     12016-06-08  Dean Jackson  <dino@apple.com>
     2
     3        Multiple selectors break keyframes animation
     4        https://bugs.webkit.org/show_bug.cgi?id=158199
     5        <rdar://problem/26652591>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * animations/duplicate-keys-expected.html: Added.
     10        * animations/duplicate-keys.html: Added.
     11
    1122016-06-08  Per Arne Vollan  <pvollan@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r201816 r201818  
     12016-06-08  Dean Jackson  <dino@apple.com>
     2
     3        Multiple selectors break keyframes animation
     4        https://bugs.webkit.org/show_bug.cgi?id=158199
     5        <rdar://problem/26652591>
     6
     7        Reviewed by Simon Fraser.
     8
     9        If we came across a duplicate key entry in a keyframe, we
     10        were replacing the existing entry, instead of merging.
     11
     12        Test: animations/duplicate-keys.html
     13
     14        * css/CSSKeyframeRule.h:
     15        (WebCore::StyleKeyframe::setKey): Add a way to set the key of a rule
     16        as a number, rather than going through a string and the CSS parser.
     17        * css/StyleResolver.cpp:
     18        (WebCore::StyleResolver::keyframeStylesForAnimation): Check if the rule
     19        has duplicates, and if it does, merge all the common entries.
     20        * rendering/style/KeyframeList.cpp:
     21        (WebCore::KeyframeList::insert): Now that we've removed duplicates at
     22        the processing time, we should never come across a duplicate while
     23        building this list.
     24
    1252016-06-08  Ryan Haddad  <ryanhaddad@apple.com>
    226
  • trunk/Source/WebCore/css/CSSKeyframeRule.h

    r197563 r201818  
    4848    String keyText() const;
    4949    void setKeyText(const String& text) { m_keys = CSSParser::parseKeyframeSelector(text); }
     50    void setKey(double key)
     51    {
     52        ASSERT(m_keys.isEmpty());
     53        m_keys.clear();
     54        m_keys.append(key);
     55    }
    5056
    5157    const Vector<double>& keys() const { return m_keys; };
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r201799 r201818  
    514514    list.clear();
    515515
    516     // Get the keyframesRule for this name
     516    // Get the keyframesRule for this name.
    517517    if (list.animationName().isEmpty())
    518518        return;
     
    526526    const StyleRuleKeyframes* keyframesRule = it->value.get();
    527527
    528     // Construct and populate the style for each keyframe
    529     for (auto& keyframe : keyframesRule->keyframes()) {
    530         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
     528    auto* keyframes = &keyframesRule->keyframes();
     529    Vector<Ref<StyleKeyframe>> newKeyframesIfNecessary;
     530
     531    bool hasDuplicateKeys;
     532    HashSet<double> keyframeKeys;
     533    for (auto& keyframe : *keyframes) {
     534        for (auto key : keyframe->keys()) {
     535            if (!keyframeKeys.add(key)) {
     536                hasDuplicateKeys = true;
     537                break;
     538            }
     539        }
     540        if (hasDuplicateKeys)
     541            break;
     542    }
     543
     544    // FIXME: If HashMaps could have Ref<> as value types, we wouldn't need
     545    // to copy the HashMap into a Vector.
     546    if (hasDuplicateKeys) {
     547        // Merge duplicate key times.
     548        HashMap<double, RefPtr<StyleKeyframe>> keyframesMap;
     549
     550        for (auto& originalKeyframe : keyframesRule->keyframes()) {
     551            for (auto key : originalKeyframe->keys()) {
     552                if (auto keyframe = keyframesMap.get(key))
     553                    keyframe->mutableProperties().mergeAndOverrideOnConflict(originalKeyframe->properties());
     554                else {
     555                    auto styleKeyframe = StyleKeyframe::create(MutableStyleProperties::create());
     556                    styleKeyframe.ptr()->setKey(key);
     557                    styleKeyframe.ptr()->mutableProperties().mergeAndOverrideOnConflict(originalKeyframe->properties());
     558                    keyframesMap.set(key, styleKeyframe.ptr());
     559                }
     560            }
     561        }
     562
     563        for (auto& keyframe : keyframesMap.values())
     564            newKeyframesIfNecessary.append(*keyframe.get());
     565
     566        keyframes = &newKeyframesIfNecessary;
     567    }
     568
     569    // Construct and populate the style for each keyframe.
     570    for (auto& keyframe : *keyframes) {
     571        // Apply the declaration to the style. This is a simplified version of the logic in styleForElement.
    531572        m_state = State(element, nullptr);
    532573
    533574        // Add this keyframe style to all the indicated key times
    534         for (auto& key : keyframe->keys()) {
     575        for (auto key : keyframe->keys()) {
    535576            KeyframeValue keyframeValue(0, nullptr);
    536577            keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe.ptr(), keyframeValue));
     
    540581    }
    541582
    542     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
     583    // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe).
    543584    int initialListSize = list.size();
    544585    if (initialListSize > 0 && list[0].key()) {
     
    546587        if (!zeroPercentKeyframe) {
    547588            zeroPercentKeyframe = &StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
    548             zeroPercentKeyframe->setKeyText("0%");
     589            zeroPercentKeyframe->setKey(0);
    549590        }
    550591        KeyframeValue keyframeValue(0, nullptr);
     
    553594    }
    554595
    555     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
     596    // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe).
    556597    if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
    557598        static StyleKeyframe* hundredPercentKeyframe;
    558599        if (!hundredPercentKeyframe) {
    559600            hundredPercentKeyframe = &StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
    560             hundredPercentKeyframe->setKeyText("100%");
     601            hundredPercentKeyframe->setKey(1);
    561602        }
    562603        KeyframeValue keyframeValue(1, nullptr);
  • trunk/Source/WebCore/rendering/style/KeyframeList.cpp

    r199964 r201818  
    7979
    8080    bool inserted = false;
    81     bool replaced = false;
    8281    size_t i = 0;
    8382    for (; i < m_keyframes.size(); ++i) {
    8483        if (m_keyframes[i].key() == keyframe.key()) {
    85             m_keyframes[i] = WTFMove(keyframe);
    86             replaced = true;
     84            ASSERT_NOT_REACHED();
    8785            break;
    8886        }
     
    9694    }
    9795   
    98     if (!replaced && !inserted)
     96    if (!inserted)
    9997        m_keyframes.append(WTFMove(keyframe));
    100 
    101     if (replaced) {
    102         // We have to rebuild the properties list from scratch.
    103         m_properties.clear();
    104         for (auto& keyframeValue : m_keyframes) {
    105             for (auto& property : keyframeValue.properties())
    106                 m_properties.add(property);
    107         }
    108         return;
    109     }
    11098
    11199    for (auto& property : m_keyframes[i].properties())
Note: See TracChangeset for help on using the changeset viewer.