Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp

Issue 2680923005: Refactor CSS Transitions to use CSSInterpolationTypes instead of AnimatableValues (Closed)
Patch Set: lint Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698