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

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

Issue 2730683002: Add CSS Transition support to registered custom properties (Closed)
Patch Set: Rebased Created 3 years, 9 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #include "core/animation/InterpolationEnvironment.h" 43 #include "core/animation/InterpolationEnvironment.h"
44 #include "core/animation/InterpolationType.h" 44 #include "core/animation/InterpolationType.h"
45 #include "core/animation/KeyframeEffectModel.h" 45 #include "core/animation/KeyframeEffectModel.h"
46 #include "core/animation/KeyframeEffectReadOnly.h" 46 #include "core/animation/KeyframeEffectReadOnly.h"
47 #include "core/animation/TransitionInterpolation.h" 47 #include "core/animation/TransitionInterpolation.h"
48 #include "core/animation/css/CSSAnimatableValueFactory.h" 48 #include "core/animation/css/CSSAnimatableValueFactory.h"
49 #include "core/css/CSSKeyframeRule.h" 49 #include "core/css/CSSKeyframeRule.h"
50 #include "core/css/CSSPropertyEquality.h" 50 #include "core/css/CSSPropertyEquality.h"
51 #include "core/css/CSSPropertyMetadata.h" 51 #include "core/css/CSSPropertyMetadata.h"
52 #include "core/css/CSSValueList.h" 52 #include "core/css/CSSValueList.h"
53 #include "core/css/PropertyRegistry.h"
54 #include "core/css/parser/CSSVariableParser.h"
53 #include "core/css/resolver/CSSToStyleMap.h" 55 #include "core/css/resolver/CSSToStyleMap.h"
54 #include "core/css/resolver/StyleResolver.h" 56 #include "core/css/resolver/StyleResolver.h"
55 #include "core/dom/Element.h" 57 #include "core/dom/Element.h"
56 #include "core/dom/PseudoElement.h" 58 #include "core/dom/PseudoElement.h"
57 #include "core/dom/StyleEngine.h" 59 #include "core/dom/StyleEngine.h"
58 #include "core/events/AnimationEvent.h" 60 #include "core/events/AnimationEvent.h"
59 #include "core/events/TransitionEvent.h" 61 #include "core/events/TransitionEvent.h"
60 #include "core/frame/UseCounter.h" 62 #include "core/frame/UseCounter.h"
61 #include "core/layout/LayoutObject.h" 63 #include "core/layout/LayoutObject.h"
62 #include "core/paint/PaintLayer.h" 64 #include "core/paint/PaintLayer.h"
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram( 611 UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(
610 property.cssProperty())); 612 property.cssProperty()));
611 } 613 }
612 clearPendingUpdate(); 614 clearPendingUpdate();
613 } 615 }
614 616
615 void CSSAnimations::calculateTransitionUpdateForProperty( 617 void CSSAnimations::calculateTransitionUpdateForProperty(
616 TransitionUpdateState& state, 618 TransitionUpdateState& state,
617 const PropertyHandle& property, 619 const PropertyHandle& property,
618 size_t transitionIndex) { 620 size_t transitionIndex) {
619 state.listedProperties.set(property.cssProperty() - firstCSSProperty); 621 state.listedProperties.insert(property);
620 622
621 // FIXME: We should transition if an !important property changes even when an 623 // FIXME: We should transition if an !important property changes even when an
622 // animation is running, but this is a bit hard to do with the current 624 // animation is running, but this is a bit hard to do with the current
623 // applyMatchedProperties system. 625 // applyMatchedProperties system.
624 if (state.update.activeInterpolationsForAnimations().contains(property) || 626 if (state.update.activeInterpolationsForAnimations().contains(property) ||
625 (state.animatingElement->elementAnimations() && 627 (state.animatingElement->elementAnimations() &&
626 state.animatingElement->elementAnimations() 628 state.animatingElement->elementAnimations()
627 ->cssAnimations() 629 ->cssAnimations()
628 .m_previousActiveInterpolationsForAnimations.contains(property))) { 630 .m_previousActiveInterpolationsForAnimations.contains(property))) {
629 return; 631 return;
(...skipping 14 matching lines...) Expand all
644 DCHECK(!state.animatingElement->elementAnimations() || 646 DCHECK(!state.animatingElement->elementAnimations() ||
645 !state.animatingElement->elementAnimations() 647 !state.animatingElement->elementAnimations()
646 ->isAnimationStyleChange()); 648 ->isAnimationStyleChange());
647 649
648 if (to->equals(runningTransition->reversingAdjustedStartValue.get())) { 650 if (to->equals(runningTransition->reversingAdjustedStartValue.get())) {
649 interruptedTransition = runningTransition; 651 interruptedTransition = runningTransition;
650 } 652 }
651 } 653 }
652 } 654 }
653 655
654 if (CSSPropertyEquality::propertiesEqual(property.cssProperty(), 656 const PropertyRegistry* registry =
655 state.oldStyle, state.style)) { 657 state.animatingElement->document().propertyRegistry();
658
659 if (property.isCSSCustomProperty()) {
660 if (!registry || !registry->registration(property.customPropertyName()) ||
661 CSSPropertyEquality::registeredCustomPropertiesEqual(
662 property.customPropertyName(), state.oldStyle, state.style)) {
663 return;
664 }
665 } else if (CSSPropertyEquality::propertiesEqual(
666 property.cssProperty(), state.oldStyle, state.style)) {
656 return; 667 return;
657 } 668 }
658 669
659 if (!to) 670 if (!to)
660 to = CSSAnimatableValueFactory::create(property, state.style); 671 to = CSSAnimatableValueFactory::create(property, state.style);
661 RefPtr<AnimatableValue> from = 672 RefPtr<AnimatableValue> from =
662 CSSAnimatableValueFactory::create(property, state.oldStyle); 673 CSSAnimatableValueFactory::create(property, state.oldStyle);
663 674
664 // TODO(alancutter): Support transitions on registered custom properties and 675 // TODO(alancutter): Support transitions on registered custom properties and
665 // give the map a PropertyRegistry. 676 // give the map a PropertyRegistry.
666 CSSInterpolationTypesMap map(nullptr); 677 CSSInterpolationTypesMap map(registry);
667 InterpolationEnvironment oldEnvironment(map, state.oldStyle); 678 InterpolationEnvironment oldEnvironment(map, state.oldStyle);
668 InterpolationEnvironment newEnvironment(map, state.style); 679 InterpolationEnvironment newEnvironment(map, state.style);
669 InterpolationValue start = nullptr; 680 InterpolationValue start = nullptr;
670 InterpolationValue end = nullptr; 681 InterpolationValue end = nullptr;
671 const InterpolationType* transitionType = nullptr; 682 const InterpolationType* transitionType = nullptr;
672 for (const auto& interpolationType : map.get(property)) { 683 for (const auto& interpolationType : map.get(property)) {
673 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment); 684 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment);
674 if (!start) { 685 if (!start) {
675 continue; 686 continue;
676 } 687 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 TransitionKeyframeEffectModel* model = 778 TransitionKeyframeEffectModel* model =
768 TransitionKeyframeEffectModel::create(keyframes); 779 TransitionKeyframeEffectModel::create(keyframes);
769 state.update.startTransition( 780 state.update.startTransition(
770 property, from.get(), to.get(), reversingAdjustedStartValue, 781 property, from.get(), to.get(), reversingAdjustedStartValue,
771 reversingShorteningFactor, *InertEffect::create(model, timing, false, 0)); 782 reversingShorteningFactor, *InertEffect::create(model, timing, false, 0));
772 DCHECK( 783 DCHECK(
773 !state.animatingElement->elementAnimations() || 784 !state.animatingElement->elementAnimations() ||
774 !state.animatingElement->elementAnimations()->isAnimationStyleChange()); 785 !state.animatingElement->elementAnimations()->isAnimationStyleChange());
775 } 786 }
776 787
788 void CSSAnimations::calculateTransitionUpdateForCustomProperty(
789 TransitionUpdateState& state,
790 const CSSTransitionData::TransitionProperty& transitionProperty,
791 size_t transitionIndex) {
792 if (transitionProperty.propertyType !=
793 CSSTransitionData::TransitionUnknownProperty) {
794 return;
795 }
796 if (!CSSVariableParser::isValidVariableName(
797 transitionProperty.propertyString)) {
798 return;
799 }
800 calculateTransitionUpdateForProperty(
801 state, PropertyHandle(transitionProperty.propertyString),
802 transitionIndex);
803 }
804
777 void CSSAnimations::calculateTransitionUpdateForStandardProperty( 805 void CSSAnimations::calculateTransitionUpdateForStandardProperty(
778 TransitionUpdateState& state, 806 TransitionUpdateState& state,
779 const CSSTransitionData::TransitionProperty& transitionProperty, 807 const CSSTransitionData::TransitionProperty& transitionProperty,
780 size_t transitionIndex) { 808 size_t transitionIndex) {
781 if (transitionProperty.propertyType != 809 if (transitionProperty.propertyType !=
782 CSSTransitionData::TransitionKnownProperty) { 810 CSSTransitionData::TransitionKnownProperty) {
783 return; 811 return;
784 } 812 }
785 813
786 CSSPropertyID resolvedID = 814 CSSPropertyID resolvedID =
(...skipping 13 matching lines...) Expand all
800 if (!animateAll && 828 if (!animateAll &&
801 !CSSPropertyMetadata::isInterpolableProperty(longhandID)) { 829 !CSSPropertyMetadata::isInterpolableProperty(longhandID)) {
802 continue; 830 continue;
803 } 831 }
804 832
805 calculateTransitionUpdateForProperty(state, property, transitionIndex); 833 calculateTransitionUpdateForProperty(state, property, transitionIndex);
806 } 834 }
807 } 835 }
808 836
809 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, 837 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update,
838 PropertyPass propertyPass,
810 const Element* animatingElement, 839 const Element* animatingElement,
811 const ComputedStyle& style) { 840 const ComputedStyle& style) {
812 if (!animatingElement) 841 if (!animatingElement)
813 return; 842 return;
814 843
815 if (animatingElement->document().finishingOrIsPrinting()) 844 if (animatingElement->document().finishingOrIsPrinting())
816 return; 845 return;
817 846
818 ElementAnimations* elementAnimations = animatingElement->elementAnimations(); 847 ElementAnimations* elementAnimations = animatingElement->elementAnimations();
819 const TransitionMap* activeTransitions = 848 const TransitionMap* activeTransitions =
820 elementAnimations ? &elementAnimations->cssAnimations().m_transitions 849 elementAnimations ? &elementAnimations->cssAnimations().m_transitions
821 : nullptr; 850 : nullptr;
822 const CSSTransitionData* transitionData = style.transitions(); 851 const CSSTransitionData* transitionData = style.transitions();
823 852
824 const bool animationStyleRecalc = 853 const bool animationStyleRecalc =
825 elementAnimations && elementAnimations->isAnimationStyleChange(); 854 elementAnimations && elementAnimations->isAnimationStyleChange();
826 855
827 std::bitset<numCSSProperties> listedProperties; 856 HashSet<PropertyHandle> listedProperties;
828 bool anyTransitionHadTransitionAll = false; 857 bool anyTransitionHadTransitionAll = false;
829 const LayoutObject* layoutObject = animatingElement->layoutObject(); 858 const LayoutObject* layoutObject = animatingElement->layoutObject();
830 if (!animationStyleRecalc && style.display() != EDisplay::None && 859 if (!animationStyleRecalc && style.display() != EDisplay::None &&
831 layoutObject && layoutObject->style() && transitionData) { 860 layoutObject && layoutObject->style() && transitionData) {
832 TransitionUpdateState state = { 861 TransitionUpdateState state = {
833 update, animatingElement, *layoutObject->style(), 862 update, animatingElement, *layoutObject->style(),
834 style, activeTransitions, listedProperties, 863 style, activeTransitions, listedProperties,
835 *transitionData}; 864 *transitionData};
836 865
837 for (size_t transitionIndex = 0; 866 for (size_t transitionIndex = 0;
838 transitionIndex < transitionData->propertyList().size(); 867 transitionIndex < transitionData->propertyList().size();
839 ++transitionIndex) { 868 ++transitionIndex) {
840 const CSSTransitionData::TransitionProperty& transitionProperty = 869 const CSSTransitionData::TransitionProperty& transitionProperty =
841 transitionData->propertyList()[transitionIndex]; 870 transitionData->propertyList()[transitionIndex];
842 if (transitionProperty.unresolvedProperty == CSSPropertyAll) { 871 if (transitionProperty.unresolvedProperty == CSSPropertyAll) {
843 anyTransitionHadTransitionAll = true; 872 anyTransitionHadTransitionAll = true;
844 } 873 }
845 calculateTransitionUpdateForStandardProperty(state, transitionProperty, 874 if (propertyPass == PropertyPass::Custom) {
875 calculateTransitionUpdateForCustomProperty(state, transitionProperty,
846 transitionIndex); 876 transitionIndex);
877 } else {
878 DCHECK_EQ(propertyPass, PropertyPass::Standard);
879 calculateTransitionUpdateForStandardProperty(state, transitionProperty,
880 transitionIndex);
881 }
847 } 882 }
848 } 883 }
849 884
850 if (activeTransitions) { 885 if (activeTransitions) {
851 for (const auto& entry : *activeTransitions) { 886 for (const auto& entry : *activeTransitions) {
852 const PropertyHandle& property = entry.key; 887 const PropertyHandle& property = entry.key;
853 // TODO(alancutter): Handle transitions on custom properties.
854 DCHECK(!property.isCSSCustomProperty());
855 CSSPropertyID id = property.cssProperty();
856 if (!anyTransitionHadTransitionAll && !animationStyleRecalc && 888 if (!anyTransitionHadTransitionAll && !animationStyleRecalc &&
857 !listedProperties.test(id - firstCSSProperty)) { 889 !listedProperties.contains(property)) {
858 update.cancelTransition(property); 890 update.cancelTransition(property);
859 } else if (entry.value.animation->finishedInternal()) { 891 } else if (entry.value.animation->finishedInternal()) {
860 update.finishTransition(property); 892 update.finishTransition(property);
861 } 893 }
862 } 894 }
863 } 895 }
864 calculateTransitionActiveInterpolations(update, animatingElement); 896
897 calculateTransitionActiveInterpolations(update, propertyPass,
898 animatingElement);
865 } 899 }
866 900
867 void CSSAnimations::cancel() { 901 void CSSAnimations::cancel() {
868 for (const auto& runningAnimation : m_runningAnimations) { 902 for (const auto& runningAnimation : m_runningAnimations) {
869 runningAnimation->animation->cancel(); 903 runningAnimation->animation->cancel();
870 runningAnimation->animation->update(TimingUpdateOnDemand); 904 runningAnimation->animation->update(TimingUpdateOnDemand);
871 } 905 }
872 906
873 for (const auto& entry : m_transitions) { 907 for (const auto& entry : m_transitions) {
874 entry.value.animation->cancel(); 908 entry.value.animation->cancel();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 newEffects.push_back(updatedAnimation.effect); 954 newEffects.push_back(updatedAnimation.effect);
921 955
922 ActiveInterpolationsMap activeInterpolationsForAnimations( 956 ActiveInterpolationsMap activeInterpolationsForAnimations(
923 EffectStack::activeInterpolations( 957 EffectStack::activeInterpolations(
924 effectStack, &newEffects, &update.suppressedAnimations(), 958 effectStack, &newEffects, &update.suppressedAnimations(),
925 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle)); 959 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle));
926 update.adoptActiveInterpolationsForAnimations( 960 update.adoptActiveInterpolationsForAnimations(
927 activeInterpolationsForAnimations); 961 activeInterpolationsForAnimations);
928 } 962 }
929 963
964 static bool isCustomStylePropertyHandle(const PropertyHandle& property) {
965 return property.isCSSCustomProperty();
966 }
967
968 static bool isStandardStylePropertyHandle(const PropertyHandle& property) {
969 return isStylePropertyHandle(property) && !property.isCSSCustomProperty();
970 }
971
972 static EffectStack::PropertyHandleFilter stylePropertyFilter(
973 CSSAnimations::PropertyPass propertyPass) {
974 if (propertyPass == CSSAnimations::PropertyPass::Custom) {
975 return isCustomStylePropertyHandle;
976 }
977 DCHECK_EQ(propertyPass, CSSAnimations::PropertyPass::Standard);
978 return isStandardStylePropertyHandle;
979 }
980
930 void CSSAnimations::calculateTransitionActiveInterpolations( 981 void CSSAnimations::calculateTransitionActiveInterpolations(
931 CSSAnimationUpdate& update, 982 CSSAnimationUpdate& update,
983 PropertyPass propertyPass,
932 const Element* animatingElement) { 984 const Element* animatingElement) {
933 ElementAnimations* elementAnimations = 985 ElementAnimations* elementAnimations =
934 animatingElement ? animatingElement->elementAnimations() : nullptr; 986 animatingElement ? animatingElement->elementAnimations() : nullptr;
935 EffectStack* effectStack = 987 EffectStack* effectStack =
936 elementAnimations ? &elementAnimations->effectStack() : nullptr; 988 elementAnimations ? &elementAnimations->effectStack() : nullptr;
937 989
938 ActiveInterpolationsMap activeInterpolationsForTransitions; 990 ActiveInterpolationsMap activeInterpolationsForTransitions;
939 if (update.newTransitions().isEmpty() && 991 if (update.newTransitions().isEmpty() &&
940 update.cancelledTransitions().isEmpty()) { 992 update.cancelledTransitions().isEmpty()) {
941 activeInterpolationsForTransitions = EffectStack::activeInterpolations( 993 activeInterpolationsForTransitions = EffectStack::activeInterpolations(
942 effectStack, nullptr, nullptr, 994 effectStack, nullptr, nullptr,
943 KeyframeEffectReadOnly::TransitionPriority, isStylePropertyHandle); 995 KeyframeEffectReadOnly::TransitionPriority,
996 stylePropertyFilter(propertyPass));
944 } else { 997 } else {
945 HeapVector<Member<const InertEffect>> newTransitions; 998 HeapVector<Member<const InertEffect>> newTransitions;
946 for (const auto& entry : update.newTransitions()) 999 for (const auto& entry : update.newTransitions())
947 newTransitions.push_back(entry.value.effect.get()); 1000 newTransitions.push_back(entry.value.effect.get());
948 1001
949 HeapHashSet<Member<const Animation>> cancelledAnimations; 1002 HeapHashSet<Member<const Animation>> cancelledAnimations;
950 if (!update.cancelledTransitions().isEmpty()) { 1003 if (!update.cancelledTransitions().isEmpty()) {
951 DCHECK(elementAnimations); 1004 DCHECK(elementAnimations);
952 const TransitionMap& transitionMap = 1005 const TransitionMap& transitionMap =
953 elementAnimations->cssAnimations().m_transitions; 1006 elementAnimations->cssAnimations().m_transitions;
954 for (const PropertyHandle& property : update.cancelledTransitions()) { 1007 for (const PropertyHandle& property : update.cancelledTransitions()) {
955 DCHECK(transitionMap.contains(property)); 1008 DCHECK(transitionMap.contains(property));
956 cancelledAnimations.insert(transitionMap.at(property).animation.get()); 1009 cancelledAnimations.insert(transitionMap.at(property).animation.get());
957 } 1010 }
958 } 1011 }
959 1012
960 activeInterpolationsForTransitions = EffectStack::activeInterpolations( 1013 activeInterpolationsForTransitions = EffectStack::activeInterpolations(
961 effectStack, &newTransitions, &cancelledAnimations, 1014 effectStack, &newTransitions, &cancelledAnimations,
962 KeyframeEffectReadOnly::TransitionPriority, isStylePropertyHandle); 1015 KeyframeEffectReadOnly::TransitionPriority,
1016 stylePropertyFilter(propertyPass));
963 } 1017 }
964 1018
965 // Properties being animated by animations don't get values from transitions 1019 // Properties being animated by animations don't get values from transitions
966 // applied. 1020 // applied.
967 if (!update.activeInterpolationsForAnimations().isEmpty() && 1021 if (!update.activeInterpolationsForAnimations().isEmpty() &&
968 !activeInterpolationsForTransitions.isEmpty()) { 1022 !activeInterpolationsForTransitions.isEmpty()) {
969 for (const auto& entry : update.activeInterpolationsForAnimations()) 1023 for (const auto& entry : update.activeInterpolationsForAnimations())
970 activeInterpolationsForTransitions.erase(entry.key); 1024 activeInterpolationsForTransitions.erase(entry.key);
971 } 1025 }
972 update.adoptActiveInterpolationsForStandardTransitions( 1026
973 activeInterpolationsForTransitions); 1027 if (propertyPass == PropertyPass::Custom) {
1028 update.adoptActiveInterpolationsForCustomTransitions(
1029 activeInterpolationsForTransitions);
1030 } else {
1031 DCHECK_EQ(propertyPass, PropertyPass::Standard);
1032 update.adoptActiveInterpolationsForStandardTransitions(
1033 activeInterpolationsForTransitions);
1034 }
974 } 1035 }
975 1036
976 EventTarget* CSSAnimations::AnimationEventDelegate::eventTarget() const { 1037 EventTarget* CSSAnimations::AnimationEventDelegate::eventTarget() const {
977 return EventPath::eventTargetRespectingTargetRules(*m_animationTarget); 1038 return EventPath::eventTargetRespectingTargetRules(*m_animationTarget);
978 } 1039 }
979 1040
980 void CSSAnimations::AnimationEventDelegate::maybeDispatch( 1041 void CSSAnimations::AnimationEventDelegate::maybeDispatch(
981 Document::ListenerType listenerType, 1042 Document::ListenerType listenerType,
982 const AtomicString& eventName, 1043 const AtomicString& eventName,
983 double elapsedTime) { 1044 double elapsedTime) {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 isCustomPropertyHandle); 1205 isCustomPropertyHandle);
1145 } 1206 }
1146 1207
1147 DEFINE_TRACE(CSSAnimations) { 1208 DEFINE_TRACE(CSSAnimations) {
1148 visitor->trace(m_transitions); 1209 visitor->trace(m_transitions);
1149 visitor->trace(m_pendingUpdate); 1210 visitor->trace(m_pendingUpdate);
1150 visitor->trace(m_runningAnimations); 1211 visitor->trace(m_runningAnimations);
1151 } 1212 }
1152 1213
1153 } // namespace blink 1214 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698