Chromium Code Reviews| 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 12 matching lines...) Expand all Loading... | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "core/animation/css/CSSAnimations.h" | 31 #include "core/animation/css/CSSAnimations.h" |
| 32 | 32 |
| 33 #include <algorithm> | |
| 34 #include <bitset> | |
| 33 #include "core/StylePropertyShorthand.h" | 35 #include "core/StylePropertyShorthand.h" |
| 34 #include "core/animation/Animation.h" | 36 #include "core/animation/Animation.h" |
| 37 #include "core/animation/CSSInterpolationTypesMap.h" | |
| 35 #include "core/animation/CompositorAnimations.h" | 38 #include "core/animation/CompositorAnimations.h" |
| 36 #include "core/animation/DocumentTimeline.h" | 39 #include "core/animation/DocumentTimeline.h" |
| 37 #include "core/animation/ElementAnimations.h" | 40 #include "core/animation/ElementAnimations.h" |
| 38 #include "core/animation/InertEffect.h" | 41 #include "core/animation/InertEffect.h" |
| 39 #include "core/animation/Interpolation.h" | 42 #include "core/animation/Interpolation.h" |
| 43 #include "core/animation/InterpolationEnvironment.h" | |
| 44 #include "core/animation/InterpolationType.h" | |
| 40 #include "core/animation/KeyframeEffectModel.h" | 45 #include "core/animation/KeyframeEffectModel.h" |
| 41 #include "core/animation/KeyframeEffectReadOnly.h" | 46 #include "core/animation/KeyframeEffectReadOnly.h" |
| 42 #include "core/animation/LegacyStyleInterpolation.h" | 47 #include "core/animation/TransitionInterpolation.h" |
| 43 #include "core/animation/css/CSSAnimatableValueFactory.h" | 48 #include "core/animation/css/CSSAnimatableValueFactory.h" |
| 44 #include "core/css/CSSKeyframeRule.h" | 49 #include "core/css/CSSKeyframeRule.h" |
| 45 #include "core/css/CSSPropertyEquality.h" | 50 #include "core/css/CSSPropertyEquality.h" |
| 46 #include "core/css/CSSPropertyMetadata.h" | 51 #include "core/css/CSSPropertyMetadata.h" |
| 47 #include "core/css/CSSValueList.h" | 52 #include "core/css/CSSValueList.h" |
| 48 #include "core/css/resolver/CSSToStyleMap.h" | 53 #include "core/css/resolver/CSSToStyleMap.h" |
| 49 #include "core/css/resolver/StyleResolver.h" | 54 #include "core/css/resolver/StyleResolver.h" |
| 50 #include "core/dom/Element.h" | 55 #include "core/dom/Element.h" |
| 51 #include "core/dom/PseudoElement.h" | 56 #include "core/dom/PseudoElement.h" |
| 52 #include "core/dom/StyleEngine.h" | 57 #include "core/dom/StyleEngine.h" |
| 53 #include "core/events/AnimationEvent.h" | 58 #include "core/events/AnimationEvent.h" |
| 54 #include "core/events/TransitionEvent.h" | 59 #include "core/events/TransitionEvent.h" |
| 55 #include "core/frame/UseCounter.h" | 60 #include "core/frame/UseCounter.h" |
| 56 #include "core/layout/LayoutObject.h" | 61 #include "core/layout/LayoutObject.h" |
| 57 #include "core/paint/PaintLayer.h" | 62 #include "core/paint/PaintLayer.h" |
| 58 #include "platform/Histogram.h" | 63 #include "platform/Histogram.h" |
| 59 #include "platform/animation/TimingFunction.h" | 64 #include "platform/animation/TimingFunction.h" |
| 60 #include "public/platform/Platform.h" | 65 #include "public/platform/Platform.h" |
| 61 #include "wtf/HashSet.h" | 66 #include "wtf/HashSet.h" |
| 62 #include <algorithm> | |
| 63 #include <bitset> | |
| 64 | 67 |
| 65 namespace blink { | 68 namespace blink { |
| 66 | 69 |
| 67 using PropertySet = HashSet<CSSPropertyID>; | 70 using PropertySet = HashSet<CSSPropertyID>; |
| 68 | 71 |
| 69 namespace { | 72 namespace { |
| 70 | 73 |
| 71 static StringKeyframeEffectModel* createKeyframeEffectModel( | 74 static StringKeyframeEffectModel* createKeyframeEffectModel( |
| 72 StyleResolver* resolver, | 75 StyleResolver* resolver, |
| 73 const Element* animatingElement, | 76 const Element* animatingElement, |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 547 const std::pair<Member<KeyframeEffectReadOnly>, double>& oldTransition = | 550 const std::pair<Member<KeyframeEffectReadOnly>, double>& oldTransition = |
| 548 retargetedCompositorTransitions.get(id); | 551 retargetedCompositorTransitions.get(id); |
| 549 KeyframeEffectReadOnly* oldAnimation = oldTransition.first; | 552 KeyframeEffectReadOnly* oldAnimation = oldTransition.first; |
| 550 double oldStartTime = oldTransition.second; | 553 double oldStartTime = oldTransition.second; |
| 551 double inheritedTime = | 554 double inheritedTime = |
| 552 isNull(oldStartTime) | 555 isNull(oldStartTime) |
| 553 ? 0 | 556 ? 0 |
| 554 : element->document().timeline().currentTimeInternal() - | 557 : element->document().timeline().currentTimeInternal() - |
| 555 oldStartTime; | 558 oldStartTime; |
| 556 | 559 |
| 557 AnimatableValueKeyframeEffectModel* oldEffect = | 560 TransitionKeyframeEffectModel* oldEffect = |
| 558 toAnimatableValueKeyframeEffectModel(inertAnimation->model()); | 561 toTransitionKeyframeEffectModel(inertAnimation->model()); |
| 559 const KeyframeVector& frames = oldEffect->getFrames(); | 562 const KeyframeVector& frames = oldEffect->getFrames(); |
| 560 | 563 |
| 561 AnimatableValueKeyframeVector newFrames; | 564 TransitionKeyframeVector newFrames; |
| 562 newFrames.push_back(toAnimatableValueKeyframe(frames[0]->clone().get())); | 565 newFrames.push_back(toTransitionKeyframe(frames[0]->clone().get())); |
| 563 newFrames.push_back(toAnimatableValueKeyframe(frames[1]->clone().get())); | 566 newFrames.push_back(toTransitionKeyframe(frames[1]->clone().get())); |
| 564 newFrames.push_back(toAnimatableValueKeyframe(frames[2]->clone().get())); | 567 newFrames.push_back(toTransitionKeyframe(frames[2]->clone().get())); |
| 565 newFrames[0]->clearPropertyValue(id); | |
| 566 newFrames[1]->clearPropertyValue(id); | |
| 567 | 568 |
| 568 InertEffect* inertAnimationForSampling = InertEffect::create( | 569 InertEffect* inertAnimationForSampling = InertEffect::create( |
| 569 oldAnimation->model(), oldAnimation->specifiedTiming(), false, | 570 oldAnimation->model(), oldAnimation->specifiedTiming(), false, |
| 570 inheritedTime); | 571 inheritedTime); |
| 571 Vector<RefPtr<Interpolation>> sample; | 572 Vector<RefPtr<Interpolation>> sample; |
| 572 inertAnimationForSampling->sample(sample); | 573 inertAnimationForSampling->sample(sample); |
| 573 if (sample.size() == 1) { | 574 if (sample.size() == 1) { |
| 574 newFrames[0]->setPropertyValue( | 575 const auto& transitionInterpolation = |
| 575 id, toLegacyStyleInterpolation(sample.at(0).get())->currentValue()); | 576 toTransitionInterpolation(*sample.at(0)); |
| 576 newFrames[1]->setPropertyValue( | 577 newFrames[0]->setValue(transitionInterpolation.getInterpolatedValue()); |
| 577 id, toLegacyStyleInterpolation(sample.at(0).get())->currentValue()); | 578 newFrames[0]->setCompositorValue( |
| 578 model = AnimatableValueKeyframeEffectModel::create(newFrames); | 579 transitionInterpolation.getInterpolatedCompositorValue()); |
| 580 newFrames[1]->setValue(transitionInterpolation.getInterpolatedValue()); | |
| 581 newFrames[1]->setCompositorValue( | |
| 582 transitionInterpolation.getInterpolatedCompositorValue()); | |
| 583 model = TransitionKeyframeEffectModel::create(newFrames); | |
| 579 } | 584 } |
| 580 } | 585 } |
| 581 | 586 |
| 582 KeyframeEffect* transition = KeyframeEffect::create( | 587 KeyframeEffect* transition = KeyframeEffect::create( |
| 583 element, model, inertAnimation->specifiedTiming(), | 588 element, model, inertAnimation->specifiedTiming(), |
| 584 KeyframeEffectReadOnly::TransitionPriority, eventDelegate); | 589 KeyframeEffectReadOnly::TransitionPriority, eventDelegate); |
| 585 Animation* animation = element->document().timeline().play(transition); | 590 Animation* animation = element->document().timeline().play(transition); |
| 586 animation->setId(getPropertyName(newTransition.id)); | 591 animation->setId(getPropertyName(newTransition.id)); |
| 587 // Set the current time as the start time for retargeted transitions | 592 // Set the current time as the start time for retargeted transitions |
| 588 if (retargetedCompositorTransitions.contains(id)) | 593 if (retargetedCompositorTransitions.contains(id)) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 610 CSSAnimationUpdate& update, | 615 CSSAnimationUpdate& update, |
| 611 const Element* element) { | 616 const Element* element) { |
| 612 RefPtr<AnimatableValue> to = nullptr; | 617 RefPtr<AnimatableValue> to = nullptr; |
| 613 const RunningTransition* interruptedTransition = nullptr; | 618 const RunningTransition* interruptedTransition = nullptr; |
| 614 if (activeTransitions) { | 619 if (activeTransitions) { |
| 615 TransitionMap::const_iterator activeTransitionIter = | 620 TransitionMap::const_iterator activeTransitionIter = |
| 616 activeTransitions->find(id); | 621 activeTransitions->find(id); |
| 617 if (activeTransitionIter != activeTransitions->end()) { | 622 if (activeTransitionIter != activeTransitions->end()) { |
| 618 const RunningTransition* runningTransition = &activeTransitionIter->value; | 623 const RunningTransition* runningTransition = &activeTransitionIter->value; |
| 619 to = CSSAnimatableValueFactory::create(id, style); | 624 to = CSSAnimatableValueFactory::create(id, style); |
| 620 const AnimatableValue* activeTo = runningTransition->to; | 625 const AnimatableValue* activeTo = runningTransition->to.get(); |
| 621 if (to->equals(activeTo)) | 626 if (to->equals(activeTo)) |
| 622 return; | 627 return; |
| 623 update.cancelTransition(id); | 628 update.cancelTransition(id); |
| 624 DCHECK(!element->elementAnimations() || | 629 DCHECK(!element->elementAnimations() || |
| 625 !element->elementAnimations()->isAnimationStyleChange()); | 630 !element->elementAnimations()->isAnimationStyleChange()); |
| 626 | 631 |
| 627 if (to->equals(runningTransition->reversingAdjustedStartValue.get())) | 632 if (to->equals(runningTransition->reversingAdjustedStartValue.get())) |
| 628 interruptedTransition = runningTransition; | 633 interruptedTransition = runningTransition; |
| 629 } | 634 } |
| 630 } | 635 } |
| 631 | 636 |
| 632 if (CSSPropertyEquality::propertiesEqual(id, oldStyle, style)) | 637 if (CSSPropertyEquality::propertiesEqual(id, oldStyle, style)) |
| 633 return; | 638 return; |
| 639 | |
| 634 if (!to) | 640 if (!to) |
| 635 to = CSSAnimatableValueFactory::create(id, style); | 641 to = CSSAnimatableValueFactory::create(id, style); |
| 636 | |
| 637 RefPtr<AnimatableValue> from = | 642 RefPtr<AnimatableValue> from = |
| 638 CSSAnimatableValueFactory::create(id, oldStyle); | 643 CSSAnimatableValueFactory::create(id, oldStyle); |
| 644 | |
| 645 // TODO(alancutter): Support transitions on registered custom properties and | |
| 646 // give the map a PropertyRegistry. | |
| 647 CSSInterpolationTypesMap map(nullptr); | |
| 648 InterpolationEnvironment oldEnvironment(map, oldStyle); | |
| 649 InterpolationEnvironment newEnvironment(map, style); | |
| 650 InterpolationValue start = nullptr; | |
| 651 InterpolationValue end = nullptr; | |
| 652 const InterpolationType* transitionType = nullptr; | |
| 653 PropertyHandle property(id); | |
| 654 for (const auto& interpolationType : map.get(property)) { | |
| 655 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment); | |
| 656 if (!start) { | |
| 657 continue; | |
| 658 } | |
| 659 end = interpolationType->maybeConvertUnderlyingValue(newEnvironment); | |
| 660 if (!end) { | |
| 661 continue; | |
| 662 } | |
| 663 // Merge will only succeed if the two values are considered interpolable. | |
| 664 if (interpolationType->maybeMergeSingles(start.clone(), end.clone())) { | |
| 665 transitionType = interpolationType.get(); | |
| 666 break; | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 // No smooth interpolation exists between these values so don't start a | |
| 671 // transition. | |
| 672 if (!transitionType) { | |
| 673 return; | |
| 674 } | |
| 675 | |
| 639 // If we have multiple transitions on the same property, we will use the | 676 // If we have multiple transitions on the same property, we will use the |
| 640 // last one since we iterate over them in order. | 677 // last one since we iterate over them in order. |
| 641 if (AnimatableValue::usesDefaultInterpolation(to.get(), from.get())) | |
| 642 return; | |
| 643 | 678 |
| 644 Timing timing = transitionData.convertToTiming(transitionIndex); | 679 Timing timing = transitionData.convertToTiming(transitionIndex); |
| 645 if (timing.startDelay + timing.iterationDuration <= 0) | 680 if (timing.startDelay + timing.iterationDuration <= 0) |
| 646 return; | 681 return; |
| 647 | 682 |
| 648 AnimatableValue* reversingAdjustedStartValue = from.get(); | 683 AnimatableValue* reversingAdjustedStartValue = from.get(); |
| 649 double reversingShorteningFactor = 1; | 684 double reversingShorteningFactor = 1; |
| 650 if (interruptedTransition) { | 685 if (interruptedTransition) { |
| 651 const double interruptedProgress = | 686 const double interruptedProgress = |
| 652 interruptedTransition->animation->effect()->progress(); | 687 interruptedTransition->animation->effect()->progress(); |
| 653 if (!std::isnan(interruptedProgress)) { | 688 if (!std::isnan(interruptedProgress)) { |
| 654 // const_cast because we need to take a ref later when passing to | 689 // const_cast because we need to take a ref later when passing to |
|
suzyh_UTC10 (ex-contributor)
2017/02/17 00:34:19
Comment obsolete?
alancutter (OOO until 2018)
2017/02/17 00:54:57
Removed, thanks for catch.
| |
| 655 // startTransition. | 690 // startTransition. |
| 656 reversingAdjustedStartValue = | 691 reversingAdjustedStartValue = interruptedTransition->to.get(); |
| 657 const_cast<AnimatableValue*>(interruptedTransition->to); | |
| 658 reversingShorteningFactor = | 692 reversingShorteningFactor = |
| 659 clampTo((interruptedProgress * | 693 clampTo((interruptedProgress * |
| 660 interruptedTransition->reversingShorteningFactor) + | 694 interruptedTransition->reversingShorteningFactor) + |
| 661 (1 - interruptedTransition->reversingShorteningFactor), | 695 (1 - interruptedTransition->reversingShorteningFactor), |
| 662 0.0, 1.0); | 696 0.0, 1.0); |
| 663 timing.iterationDuration *= reversingShorteningFactor; | 697 timing.iterationDuration *= reversingShorteningFactor; |
| 664 if (timing.startDelay < 0) { | 698 if (timing.startDelay < 0) { |
| 665 timing.startDelay *= reversingShorteningFactor; | 699 timing.startDelay *= reversingShorteningFactor; |
| 666 } | 700 } |
| 667 } | 701 } |
| 668 } | 702 } |
| 669 | 703 |
| 670 AnimatableValueKeyframeVector keyframes; | 704 TransitionKeyframeVector keyframes; |
| 671 double startKeyframeOffset = 0; | 705 double startKeyframeOffset = 0; |
| 672 | 706 |
| 673 if (timing.startDelay > 0) { | 707 if (timing.startDelay > 0) { |
| 674 timing.iterationDuration += timing.startDelay; | 708 timing.iterationDuration += timing.startDelay; |
| 675 startKeyframeOffset = timing.startDelay / timing.iterationDuration; | 709 startKeyframeOffset = timing.startDelay / timing.iterationDuration; |
| 676 timing.startDelay = 0; | 710 timing.startDelay = 0; |
| 677 } | 711 } |
| 678 | 712 |
| 679 RefPtr<AnimatableValueKeyframe> delayKeyframe = | 713 RefPtr<TransitionKeyframe> delayKeyframe = |
| 680 AnimatableValueKeyframe::create(); | 714 TransitionKeyframe::create(property); |
| 681 delayKeyframe->setPropertyValue(id, from.get()); | 715 delayKeyframe->setValue(TypedInterpolationValue::create( |
| 716 *transitionType, start.interpolableValue->clone(), | |
| 717 start.nonInterpolableValue)); | |
| 682 delayKeyframe->setOffset(0); | 718 delayKeyframe->setOffset(0); |
| 683 keyframes.push_back(delayKeyframe); | 719 keyframes.push_back(delayKeyframe); |
| 684 | 720 |
| 685 RefPtr<AnimatableValueKeyframe> startKeyframe = | 721 RefPtr<TransitionKeyframe> startKeyframe = |
| 686 AnimatableValueKeyframe::create(); | 722 TransitionKeyframe::create(property); |
| 687 startKeyframe->setPropertyValue(id, from.get()); | 723 startKeyframe->setValue(TypedInterpolationValue::create( |
| 724 *transitionType, start.interpolableValue->clone(), | |
| 725 start.nonInterpolableValue)); | |
| 688 startKeyframe->setOffset(startKeyframeOffset); | 726 startKeyframe->setOffset(startKeyframeOffset); |
| 689 startKeyframe->setEasing(std::move(timing.timingFunction)); | 727 startKeyframe->setEasing(std::move(timing.timingFunction)); |
| 690 timing.timingFunction = LinearTimingFunction::shared(); | 728 timing.timingFunction = LinearTimingFunction::shared(); |
| 691 keyframes.push_back(startKeyframe); | 729 keyframes.push_back(startKeyframe); |
| 692 | 730 |
| 693 RefPtr<AnimatableValueKeyframe> endKeyframe = | 731 RefPtr<TransitionKeyframe> endKeyframe = TransitionKeyframe::create(property); |
| 694 AnimatableValueKeyframe::create(); | 732 endKeyframe->setValue(TypedInterpolationValue::create( |
| 695 endKeyframe->setPropertyValue(id, to.get()); | 733 *transitionType, end.interpolableValue->clone(), |
| 734 end.nonInterpolableValue)); | |
| 696 endKeyframe->setOffset(1); | 735 endKeyframe->setOffset(1); |
| 697 keyframes.push_back(endKeyframe); | 736 keyframes.push_back(endKeyframe); |
| 698 | 737 |
| 699 AnimatableValueKeyframeEffectModel* model = | 738 if (CompositorAnimations::isCompositableProperty(id)) { |
| 700 AnimatableValueKeyframeEffectModel::create(keyframes); | 739 delayKeyframe->setCompositorValue(from); |
| 740 startKeyframe->setCompositorValue(from); | |
| 741 endKeyframe->setCompositorValue(to); | |
| 742 } | |
| 743 | |
| 744 TransitionKeyframeEffectModel* model = | |
| 745 TransitionKeyframeEffectModel::create(keyframes); | |
| 701 update.startTransition(id, from.get(), to.get(), reversingAdjustedStartValue, | 746 update.startTransition(id, from.get(), to.get(), reversingAdjustedStartValue, |
| 702 reversingShorteningFactor, | 747 reversingShorteningFactor, |
| 703 *InertEffect::create(model, timing, false, 0)); | 748 *InertEffect::create(model, timing, false, 0)); |
| 704 DCHECK(!element->elementAnimations() || | 749 DCHECK(!element->elementAnimations() || |
| 705 !element->elementAnimations()->isAnimationStyleChange()); | 750 !element->elementAnimations()->isAnimationStyleChange()); |
| 706 } | 751 } |
| 707 | 752 |
| 708 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, | 753 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, |
| 709 const Element* animatingElement, | 754 const Element* animatingElement, |
| 710 const ComputedStyle& style) { | 755 const ComputedStyle& style) { |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1068 isCustomPropertyHandle); | 1113 isCustomPropertyHandle); |
| 1069 } | 1114 } |
| 1070 | 1115 |
| 1071 DEFINE_TRACE(CSSAnimations) { | 1116 DEFINE_TRACE(CSSAnimations) { |
| 1072 visitor->trace(m_transitions); | 1117 visitor->trace(m_transitions); |
| 1073 visitor->trace(m_pendingUpdate); | 1118 visitor->trace(m_pendingUpdate); |
| 1074 visitor->trace(m_runningAnimations); | 1119 visitor->trace(m_runningAnimations); |
| 1075 } | 1120 } |
| 1076 | 1121 |
| 1077 } // namespace blink | 1122 } // namespace blink |
| OLD | NEW |