Ignore:
Timestamp:
Jun 8, 2016, 11:46:43 AM (9 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.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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);
Note: See TracChangeset for help on using the changeset viewer.