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 |