| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 } else { | 112 } else { |
| 113 DCHECK(value.isCSSWideKeyword()); | 113 DCHECK(value.isCSSWideKeyword()); |
| 114 timingFunction = CSSTimingData::initialTimingFunction(); | 114 timingFunction = CSSTimingData::initialTimingFunction(); |
| 115 } | 115 } |
| 116 keyframe->setEasing(timingFunction.release()); | 116 keyframe->setEasing(timingFunction.release()); |
| 117 } else if (!CSSAnimations::isAnimationAffectingProperty(property)) { | 117 } else if (!CSSAnimations::isAnimationAffectingProperty(property)) { |
| 118 keyframe->setCSSPropertyValue(property, | 118 keyframe->setCSSPropertyValue(property, |
| 119 properties.propertyAt(j).value()); | 119 properties.propertyAt(j).value()); |
| 120 } | 120 } |
| 121 } | 121 } |
| 122 keyframes.append(keyframe); | 122 keyframes.push_back(keyframe); |
| 123 // The last keyframe specified at a given offset is used. | 123 // The last keyframe specified at a given offset is used. |
| 124 for (size_t j = 1; j < offsets.size(); ++j) { | 124 for (size_t j = 1; j < offsets.size(); ++j) { |
| 125 keyframes.append( | 125 keyframes.push_back( |
| 126 toStringKeyframe(keyframe->cloneWithOffset(offsets[j]).get())); | 126 toStringKeyframe(keyframe->cloneWithOffset(offsets[j]).get())); |
| 127 } | 127 } |
| 128 } | 128 } |
| 129 | 129 |
| 130 DEFINE_STATIC_LOCAL(SparseHistogram, propertyHistogram, | 130 DEFINE_STATIC_LOCAL(SparseHistogram, propertyHistogram, |
| 131 ("WebCore.Animation.CSSProperties")); | 131 ("WebCore.Animation.CSSProperties")); |
| 132 for (CSSPropertyID property : specifiedPropertiesForUseCounter) { | 132 for (CSSPropertyID property : specifiedPropertiesForUseCounter) { |
| 133 DCHECK(isValidCSSPropertyID(property)); | 133 DCHECK(isValidCSSPropertyID(property)); |
| 134 propertyHistogram.sample( | 134 propertyHistogram.sample( |
| 135 UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(property)); | 135 UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(property)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 159 startKeyframe = StringKeyframe::create(); | 159 startKeyframe = StringKeyframe::create(); |
| 160 startKeyframe->setOffset(0); | 160 startKeyframe->setOffset(0); |
| 161 startKeyframe->setEasing(defaultTimingFunction); | 161 startKeyframe->setEasing(defaultTimingFunction); |
| 162 keyframes.prepend(startKeyframe); | 162 keyframes.prepend(startKeyframe); |
| 163 } | 163 } |
| 164 RefPtr<StringKeyframe> endKeyframe = keyframes[keyframes.size() - 1]; | 164 RefPtr<StringKeyframe> endKeyframe = keyframes[keyframes.size() - 1]; |
| 165 if (endKeyframe->offset() != 1) { | 165 if (endKeyframe->offset() != 1) { |
| 166 endKeyframe = StringKeyframe::create(); | 166 endKeyframe = StringKeyframe::create(); |
| 167 endKeyframe->setOffset(1); | 167 endKeyframe->setOffset(1); |
| 168 endKeyframe->setEasing(defaultTimingFunction); | 168 endKeyframe->setEasing(defaultTimingFunction); |
| 169 keyframes.append(endKeyframe); | 169 keyframes.push_back(endKeyframe); |
| 170 } | 170 } |
| 171 DCHECK_GE(keyframes.size(), 2U); | 171 DCHECK_GE(keyframes.size(), 2U); |
| 172 DCHECK(!keyframes.front()->offset()); | 172 DCHECK(!keyframes.front()->offset()); |
| 173 DCHECK_EQ(keyframes.back()->offset(), 1); | 173 DCHECK_EQ(keyframes.back()->offset(), 1); |
| 174 | 174 |
| 175 // This is used for use counting neutral keyframes running on the compositor. | 175 // This is used for use counting neutral keyframes running on the compositor. |
| 176 PropertySet allProperties; | 176 PropertySet allProperties; |
| 177 for (const auto& keyframe : keyframes) { | 177 for (const auto& keyframe : keyframes) { |
| 178 for (const auto& property : keyframe->properties()) | 178 for (const auto& property : keyframe->properties()) |
| 179 allProperties.add(property.cssProperty()); | 179 allProperties.add(property.cssProperty()); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 new AnimationEventDelegate(element, entry.name); | 514 new AnimationEventDelegate(element, entry.name); |
| 515 KeyframeEffect* effect = KeyframeEffect::create( | 515 KeyframeEffect* effect = KeyframeEffect::create( |
| 516 element, inertAnimation->model(), inertAnimation->specifiedTiming(), | 516 element, inertAnimation->model(), inertAnimation->specifiedTiming(), |
| 517 KeyframeEffectReadOnly::DefaultPriority, eventDelegate); | 517 KeyframeEffectReadOnly::DefaultPriority, eventDelegate); |
| 518 Animation* animation = element->document().timeline().play(effect); | 518 Animation* animation = element->document().timeline().play(effect); |
| 519 animation->setId(entry.name); | 519 animation->setId(entry.name); |
| 520 if (inertAnimation->paused()) | 520 if (inertAnimation->paused()) |
| 521 animation->pause(); | 521 animation->pause(); |
| 522 animation->update(TimingUpdateOnDemand); | 522 animation->update(TimingUpdateOnDemand); |
| 523 | 523 |
| 524 m_runningAnimations.append(new RunningAnimation(animation, entry)); | 524 m_runningAnimations.push_back(new RunningAnimation(animation, entry)); |
| 525 } | 525 } |
| 526 | 526 |
| 527 // Transitions that are run on the compositor only update main-thread state | 527 // Transitions that are run on the compositor only update main-thread state |
| 528 // lazily. However, we need the new state to know what the from state shoud | 528 // lazily. However, we need the new state to know what the from state shoud |
| 529 // be when transitions are retargeted. Instead of triggering complete style | 529 // be when transitions are retargeted. Instead of triggering complete style |
| 530 // recalculation, we find these cases by searching for new transitions that | 530 // recalculation, we find these cases by searching for new transitions that |
| 531 // have matching cancelled animation property IDs on the compositor. | 531 // have matching cancelled animation property IDs on the compositor. |
| 532 HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffectReadOnly>, double>> | 532 HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffectReadOnly>, double>> |
| 533 retargetedCompositorTransitions; | 533 retargetedCompositorTransitions; |
| 534 for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) { | 534 for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 isNull(oldStartTime) | 591 isNull(oldStartTime) |
| 592 ? 0 | 592 ? 0 |
| 593 : element->document().timeline().currentTimeInternal() - | 593 : element->document().timeline().currentTimeInternal() - |
| 594 oldStartTime; | 594 oldStartTime; |
| 595 | 595 |
| 596 AnimatableValueKeyframeEffectModel* oldEffect = | 596 AnimatableValueKeyframeEffectModel* oldEffect = |
| 597 toAnimatableValueKeyframeEffectModel(inertAnimation->model()); | 597 toAnimatableValueKeyframeEffectModel(inertAnimation->model()); |
| 598 const KeyframeVector& frames = oldEffect->getFrames(); | 598 const KeyframeVector& frames = oldEffect->getFrames(); |
| 599 | 599 |
| 600 AnimatableValueKeyframeVector newFrames; | 600 AnimatableValueKeyframeVector newFrames; |
| 601 newFrames.append(toAnimatableValueKeyframe(frames[0]->clone().get())); | 601 newFrames.push_back(toAnimatableValueKeyframe(frames[0]->clone().get())); |
| 602 newFrames.append(toAnimatableValueKeyframe(frames[1]->clone().get())); | 602 newFrames.push_back(toAnimatableValueKeyframe(frames[1]->clone().get())); |
| 603 newFrames.append(toAnimatableValueKeyframe(frames[2]->clone().get())); | 603 newFrames.push_back(toAnimatableValueKeyframe(frames[2]->clone().get())); |
| 604 newFrames[0]->clearPropertyValue(id); | 604 newFrames[0]->clearPropertyValue(id); |
| 605 newFrames[1]->clearPropertyValue(id); | 605 newFrames[1]->clearPropertyValue(id); |
| 606 | 606 |
| 607 InertEffect* inertAnimationForSampling = InertEffect::create( | 607 InertEffect* inertAnimationForSampling = InertEffect::create( |
| 608 oldAnimation->model(), oldAnimation->specifiedTiming(), false, | 608 oldAnimation->model(), oldAnimation->specifiedTiming(), false, |
| 609 inheritedTime); | 609 inheritedTime); |
| 610 Vector<RefPtr<Interpolation>> sample; | 610 Vector<RefPtr<Interpolation>> sample; |
| 611 inertAnimationForSampling->sample(sample); | 611 inertAnimationForSampling->sample(sample); |
| 612 if (sample.size() == 1) { | 612 if (sample.size() == 1) { |
| 613 newFrames[0]->setPropertyValue( | 613 newFrames[0]->setPropertyValue( |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 if (timing.startDelay > 0) { | 712 if (timing.startDelay > 0) { |
| 713 timing.iterationDuration += timing.startDelay; | 713 timing.iterationDuration += timing.startDelay; |
| 714 startKeyframeOffset = timing.startDelay / timing.iterationDuration; | 714 startKeyframeOffset = timing.startDelay / timing.iterationDuration; |
| 715 timing.startDelay = 0; | 715 timing.startDelay = 0; |
| 716 } | 716 } |
| 717 | 717 |
| 718 RefPtr<AnimatableValueKeyframe> delayKeyframe = | 718 RefPtr<AnimatableValueKeyframe> delayKeyframe = |
| 719 AnimatableValueKeyframe::create(); | 719 AnimatableValueKeyframe::create(); |
| 720 delayKeyframe->setPropertyValue(id, from.get()); | 720 delayKeyframe->setPropertyValue(id, from.get()); |
| 721 delayKeyframe->setOffset(0); | 721 delayKeyframe->setOffset(0); |
| 722 keyframes.append(delayKeyframe); | 722 keyframes.push_back(delayKeyframe); |
| 723 | 723 |
| 724 RefPtr<AnimatableValueKeyframe> startKeyframe = | 724 RefPtr<AnimatableValueKeyframe> startKeyframe = |
| 725 AnimatableValueKeyframe::create(); | 725 AnimatableValueKeyframe::create(); |
| 726 startKeyframe->setPropertyValue(id, from.get()); | 726 startKeyframe->setPropertyValue(id, from.get()); |
| 727 startKeyframe->setOffset(startKeyframeOffset); | 727 startKeyframe->setOffset(startKeyframeOffset); |
| 728 startKeyframe->setEasing(timing.timingFunction.release()); | 728 startKeyframe->setEasing(timing.timingFunction.release()); |
| 729 timing.timingFunction = LinearTimingFunction::shared(); | 729 timing.timingFunction = LinearTimingFunction::shared(); |
| 730 keyframes.append(startKeyframe); | 730 keyframes.push_back(startKeyframe); |
| 731 | 731 |
| 732 RefPtr<AnimatableValueKeyframe> endKeyframe = | 732 RefPtr<AnimatableValueKeyframe> endKeyframe = |
| 733 AnimatableValueKeyframe::create(); | 733 AnimatableValueKeyframe::create(); |
| 734 endKeyframe->setPropertyValue(id, to.get()); | 734 endKeyframe->setPropertyValue(id, to.get()); |
| 735 endKeyframe->setOffset(1); | 735 endKeyframe->setOffset(1); |
| 736 keyframes.append(endKeyframe); | 736 keyframes.push_back(endKeyframe); |
| 737 | 737 |
| 738 AnimatableValueKeyframeEffectModel* model = | 738 AnimatableValueKeyframeEffectModel* model = |
| 739 AnimatableValueKeyframeEffectModel::create(keyframes); | 739 AnimatableValueKeyframeEffectModel::create(keyframes); |
| 740 update.startTransition(id, from.get(), to.get(), reversingAdjustedStartValue, | 740 update.startTransition(id, from.get(), to.get(), reversingAdjustedStartValue, |
| 741 reversingShorteningFactor, | 741 reversingShorteningFactor, |
| 742 *InertEffect::create(model, timing, false, 0)); | 742 *InertEffect::create(model, timing, false, 0)); |
| 743 DCHECK(!element->elementAnimations() || | 743 DCHECK(!element->elementAnimations() || |
| 744 !element->elementAnimations()->isAnimationStyleChange()); | 744 !element->elementAnimations()->isAnimationStyleChange()); |
| 745 } | 745 } |
| 746 | 746 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 EffectStack::activeInterpolations( | 871 EffectStack::activeInterpolations( |
| 872 effectStack, nullptr, nullptr, | 872 effectStack, nullptr, nullptr, |
| 873 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle)); | 873 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle)); |
| 874 update.adoptActiveInterpolationsForAnimations( | 874 update.adoptActiveInterpolationsForAnimations( |
| 875 activeInterpolationsForAnimations); | 875 activeInterpolationsForAnimations); |
| 876 return; | 876 return; |
| 877 } | 877 } |
| 878 | 878 |
| 879 HeapVector<Member<const InertEffect>> newEffects; | 879 HeapVector<Member<const InertEffect>> newEffects; |
| 880 for (const auto& newAnimation : update.newAnimations()) | 880 for (const auto& newAnimation : update.newAnimations()) |
| 881 newEffects.append(newAnimation.effect); | 881 newEffects.push_back(newAnimation.effect); |
| 882 | 882 |
| 883 // Animations with updates use a temporary InertEffect for the current frame. | 883 // Animations with updates use a temporary InertEffect for the current frame. |
| 884 for (const auto& updatedAnimation : update.animationsWithUpdates()) | 884 for (const auto& updatedAnimation : update.animationsWithUpdates()) |
| 885 newEffects.append(updatedAnimation.effect); | 885 newEffects.push_back(updatedAnimation.effect); |
| 886 | 886 |
| 887 ActiveInterpolationsMap activeInterpolationsForAnimations( | 887 ActiveInterpolationsMap activeInterpolationsForAnimations( |
| 888 EffectStack::activeInterpolations( | 888 EffectStack::activeInterpolations( |
| 889 effectStack, &newEffects, &update.suppressedAnimations(), | 889 effectStack, &newEffects, &update.suppressedAnimations(), |
| 890 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle)); | 890 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle)); |
| 891 update.adoptActiveInterpolationsForAnimations( | 891 update.adoptActiveInterpolationsForAnimations( |
| 892 activeInterpolationsForAnimations); | 892 activeInterpolationsForAnimations); |
| 893 } | 893 } |
| 894 | 894 |
| 895 void CSSAnimations::calculateTransitionActiveInterpolations( | 895 void CSSAnimations::calculateTransitionActiveInterpolations( |
| 896 CSSAnimationUpdate& update, | 896 CSSAnimationUpdate& update, |
| 897 const Element* animatingElement) { | 897 const Element* animatingElement) { |
| 898 ElementAnimations* elementAnimations = | 898 ElementAnimations* elementAnimations = |
| 899 animatingElement ? animatingElement->elementAnimations() : nullptr; | 899 animatingElement ? animatingElement->elementAnimations() : nullptr; |
| 900 EffectStack* effectStack = | 900 EffectStack* effectStack = |
| 901 elementAnimations ? &elementAnimations->effectStack() : nullptr; | 901 elementAnimations ? &elementAnimations->effectStack() : nullptr; |
| 902 | 902 |
| 903 ActiveInterpolationsMap activeInterpolationsForTransitions; | 903 ActiveInterpolationsMap activeInterpolationsForTransitions; |
| 904 if (update.newTransitions().isEmpty() && | 904 if (update.newTransitions().isEmpty() && |
| 905 update.cancelledTransitions().isEmpty()) { | 905 update.cancelledTransitions().isEmpty()) { |
| 906 activeInterpolationsForTransitions = EffectStack::activeInterpolations( | 906 activeInterpolationsForTransitions = EffectStack::activeInterpolations( |
| 907 effectStack, nullptr, nullptr, | 907 effectStack, nullptr, nullptr, |
| 908 KeyframeEffectReadOnly::TransitionPriority, isStylePropertyHandle); | 908 KeyframeEffectReadOnly::TransitionPriority, isStylePropertyHandle); |
| 909 } else { | 909 } else { |
| 910 HeapVector<Member<const InertEffect>> newTransitions; | 910 HeapVector<Member<const InertEffect>> newTransitions; |
| 911 for (const auto& entry : update.newTransitions()) | 911 for (const auto& entry : update.newTransitions()) |
| 912 newTransitions.append(entry.value.effect.get()); | 912 newTransitions.push_back(entry.value.effect.get()); |
| 913 | 913 |
| 914 HeapHashSet<Member<const Animation>> cancelledAnimations; | 914 HeapHashSet<Member<const Animation>> cancelledAnimations; |
| 915 if (!update.cancelledTransitions().isEmpty()) { | 915 if (!update.cancelledTransitions().isEmpty()) { |
| 916 DCHECK(elementAnimations); | 916 DCHECK(elementAnimations); |
| 917 const TransitionMap& transitionMap = | 917 const TransitionMap& transitionMap = |
| 918 elementAnimations->cssAnimations().m_transitions; | 918 elementAnimations->cssAnimations().m_transitions; |
| 919 for (CSSPropertyID id : update.cancelledTransitions()) { | 919 for (CSSPropertyID id : update.cancelledTransitions()) { |
| 920 DCHECK(transitionMap.contains(id)); | 920 DCHECK(transitionMap.contains(id)); |
| 921 cancelledAnimations.add(transitionMap.get(id).animation.get()); | 921 cancelledAnimations.add(transitionMap.get(id).animation.get()); |
| 922 } | 922 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 CSSPropertyID id = convertToCSSPropertyID(i); | 1042 CSSPropertyID id = convertToCSSPropertyID(i); |
| 1043 // Avoid creating overlapping transitions with perspective-origin and | 1043 // Avoid creating overlapping transitions with perspective-origin and |
| 1044 // transition-origin. | 1044 // transition-origin. |
| 1045 if (id == CSSPropertyWebkitPerspectiveOriginX || | 1045 if (id == CSSPropertyWebkitPerspectiveOriginX || |
| 1046 id == CSSPropertyWebkitPerspectiveOriginY || | 1046 id == CSSPropertyWebkitPerspectiveOriginY || |
| 1047 id == CSSPropertyWebkitTransformOriginX || | 1047 id == CSSPropertyWebkitTransformOriginX || |
| 1048 id == CSSPropertyWebkitTransformOriginY || | 1048 id == CSSPropertyWebkitTransformOriginY || |
| 1049 id == CSSPropertyWebkitTransformOriginZ) | 1049 id == CSSPropertyWebkitTransformOriginZ) |
| 1050 continue; | 1050 continue; |
| 1051 if (CSSPropertyMetadata::isInterpolableProperty(id)) | 1051 if (CSSPropertyMetadata::isInterpolableProperty(id)) |
| 1052 properties.append(id); | 1052 properties.push_back(id); |
| 1053 } | 1053 } |
| 1054 propertyShorthand = StylePropertyShorthand( | 1054 propertyShorthand = StylePropertyShorthand( |
| 1055 CSSPropertyInvalid, properties.begin(), properties.size()); | 1055 CSSPropertyInvalid, properties.begin(), properties.size()); |
| 1056 } | 1056 } |
| 1057 return propertyShorthand; | 1057 return propertyShorthand; |
| 1058 } | 1058 } |
| 1059 | 1059 |
| 1060 // Properties that affect animations are not allowed to be affected by | 1060 // Properties that affect animations are not allowed to be affected by |
| 1061 // animations. http://w3c.github.io/web-animations/#not-animatable-section | 1061 // animations. http://w3c.github.io/web-animations/#not-animatable-section |
| 1062 bool CSSAnimations::isAnimationAffectingProperty(CSSPropertyID property) { | 1062 bool CSSAnimations::isAnimationAffectingProperty(CSSPropertyID property) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1107 isCustomPropertyHandle); | 1107 isCustomPropertyHandle); |
| 1108 } | 1108 } |
| 1109 | 1109 |
| 1110 DEFINE_TRACE(CSSAnimations) { | 1110 DEFINE_TRACE(CSSAnimations) { |
| 1111 visitor->trace(m_transitions); | 1111 visitor->trace(m_transitions); |
| 1112 visitor->trace(m_pendingUpdate); | 1112 visitor->trace(m_pendingUpdate); |
| 1113 visitor->trace(m_runningAnimations); | 1113 visitor->trace(m_runningAnimations); |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 } // namespace blink | 1116 } // namespace blink |
| OLD | NEW |