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

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: comments 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 CSSInterpolationTypesMap map(registry);
665 // give the map a PropertyRegistry.
666 CSSInterpolationTypesMap map(nullptr);
667 InterpolationEnvironment oldEnvironment(map, state.oldStyle); 676 InterpolationEnvironment oldEnvironment(map, state.oldStyle);
668 InterpolationEnvironment newEnvironment(map, state.style); 677 InterpolationEnvironment newEnvironment(map, state.style);
669 InterpolationValue start = nullptr; 678 InterpolationValue start = nullptr;
670 InterpolationValue end = nullptr; 679 InterpolationValue end = nullptr;
671 const InterpolationType* transitionType = nullptr; 680 const InterpolationType* transitionType = nullptr;
672 for (const auto& interpolationType : map.get(property)) { 681 for (const auto& interpolationType : map.get(property)) {
673 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment); 682 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment);
674 if (!start) { 683 if (!start) {
675 continue; 684 continue;
676 } 685 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 TransitionKeyframeEffectModel* model = 776 TransitionKeyframeEffectModel* model =
768 TransitionKeyframeEffectModel::create(keyframes); 777 TransitionKeyframeEffectModel::create(keyframes);
769 state.update.startTransition( 778 state.update.startTransition(
770 property, from.get(), to.get(), reversingAdjustedStartValue, 779 property, from.get(), to.get(), reversingAdjustedStartValue,
771 reversingShorteningFactor, *InertEffect::create(model, timing, false, 0)); 780 reversingShorteningFactor, *InertEffect::create(model, timing, false, 0));
772 DCHECK( 781 DCHECK(
773 !state.animatingElement->elementAnimations() || 782 !state.animatingElement->elementAnimations() ||
774 !state.animatingElement->elementAnimations()->isAnimationStyleChange()); 783 !state.animatingElement->elementAnimations()->isAnimationStyleChange());
775 } 784 }
776 785
786 void CSSAnimations::calculateTransitionUpdateForCustomProperty(
787 TransitionUpdateState& state,
788 const CSSTransitionData::TransitionProperty& transitionProperty,
789 size_t transitionIndex) {
790 if (transitionProperty.propertyType !=
791 CSSTransitionData::TransitionUnknownProperty) {
792 return;
793 }
794 if (!CSSVariableParser::isValidVariableName(
795 transitionProperty.propertyString)) {
796 return;
797 }
798 calculateTransitionUpdateForProperty(
799 state, PropertyHandle(transitionProperty.propertyString),
800 transitionIndex);
801 }
802
777 void CSSAnimations::calculateTransitionUpdateForStandardProperty( 803 void CSSAnimations::calculateTransitionUpdateForStandardProperty(
778 TransitionUpdateState& state, 804 TransitionUpdateState& state,
779 const CSSTransitionData::TransitionProperty& transitionProperty, 805 const CSSTransitionData::TransitionProperty& transitionProperty,
780 size_t transitionIndex) { 806 size_t transitionIndex) {
781 if (transitionProperty.propertyType != 807 if (transitionProperty.propertyType !=
782 CSSTransitionData::TransitionKnownProperty) { 808 CSSTransitionData::TransitionKnownProperty) {
783 return; 809 return;
784 } 810 }
785 811
786 CSSPropertyID resolvedID = 812 CSSPropertyID resolvedID =
(...skipping 13 matching lines...) Expand all
800 if (!animateAll && 826 if (!animateAll &&
801 !CSSPropertyMetadata::isInterpolableProperty(longhandID)) { 827 !CSSPropertyMetadata::isInterpolableProperty(longhandID)) {
802 continue; 828 continue;
803 } 829 }
804 830
805 calculateTransitionUpdateForProperty(state, property, transitionIndex); 831 calculateTransitionUpdateForProperty(state, property, transitionIndex);
806 } 832 }
807 } 833 }
808 834
809 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, 835 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update,
836 PropertyPass propertyPass,
810 const Element* animatingElement, 837 const Element* animatingElement,
811 const ComputedStyle& style) { 838 const ComputedStyle& style) {
812 if (!animatingElement) 839 if (!animatingElement)
813 return; 840 return;
814 841
815 if (animatingElement->document().finishingOrIsPrinting()) 842 if (animatingElement->document().finishingOrIsPrinting())
816 return; 843 return;
817 844
818 ElementAnimations* elementAnimations = animatingElement->elementAnimations(); 845 ElementAnimations* elementAnimations = animatingElement->elementAnimations();
819 const TransitionMap* activeTransitions = 846 const TransitionMap* activeTransitions =
820 elementAnimations ? &elementAnimations->cssAnimations().m_transitions 847 elementAnimations ? &elementAnimations->cssAnimations().m_transitions
821 : nullptr; 848 : nullptr;
822 const CSSTransitionData* transitionData = style.transitions(); 849 const CSSTransitionData* transitionData = style.transitions();
823 850
824 const bool animationStyleRecalc = 851 const bool animationStyleRecalc =
825 elementAnimations && elementAnimations->isAnimationStyleChange(); 852 elementAnimations && elementAnimations->isAnimationStyleChange();
826 853
827 std::bitset<numCSSProperties> listedProperties; 854 HashSet<PropertyHandle> listedProperties;
828 bool anyTransitionHadTransitionAll = false; 855 bool anyTransitionHadTransitionAll = false;
829 const LayoutObject* layoutObject = animatingElement->layoutObject(); 856 const LayoutObject* layoutObject = animatingElement->layoutObject();
830 if (!animationStyleRecalc && style.display() != EDisplay::None && 857 if (!animationStyleRecalc && style.display() != EDisplay::None &&
831 layoutObject && layoutObject->style() && transitionData) { 858 layoutObject && layoutObject->style() && transitionData) {
832 TransitionUpdateState state = { 859 TransitionUpdateState state = {
833 update, animatingElement, *layoutObject->style(), 860 update, animatingElement, *layoutObject->style(),
834 style, activeTransitions, listedProperties, 861 style, activeTransitions, listedProperties,
835 *transitionData}; 862 *transitionData};
836 863
837 for (size_t transitionIndex = 0; 864 for (size_t transitionIndex = 0;
838 transitionIndex < transitionData->propertyList().size(); 865 transitionIndex < transitionData->propertyList().size();
839 ++transitionIndex) { 866 ++transitionIndex) {
840 const CSSTransitionData::TransitionProperty& transitionProperty = 867 const CSSTransitionData::TransitionProperty& transitionProperty =
841 transitionData->propertyList()[transitionIndex]; 868 transitionData->propertyList()[transitionIndex];
842 if (transitionProperty.unresolvedProperty == CSSPropertyAll) { 869 if (transitionProperty.unresolvedProperty == CSSPropertyAll) {
843 anyTransitionHadTransitionAll = true; 870 anyTransitionHadTransitionAll = true;
844 } 871 }
845 calculateTransitionUpdateForStandardProperty(state, transitionProperty, 872 if (propertyPass == PropertyPass::Custom) {
873 calculateTransitionUpdateForCustomProperty(state, transitionProperty,
846 transitionIndex); 874 transitionIndex);
875 } else {
876 DCHECK_EQ(propertyPass, PropertyPass::Standard);
877 calculateTransitionUpdateForStandardProperty(state, transitionProperty,
878 transitionIndex);
879 }
847 } 880 }
848 } 881 }
849 882
850 if (activeTransitions) { 883 if (activeTransitions) {
851 for (const auto& entry : *activeTransitions) { 884 for (const auto& entry : *activeTransitions) {
852 const PropertyHandle& property = entry.key; 885 const PropertyHandle& property = entry.key;
853 // TODO(alancutter): Handle transitions on custom properties. 886 if (property.isCSSCustomProperty() !=
854 DCHECK(!property.isCSSCustomProperty()); 887 (propertyPass == PropertyPass::Custom)) {
855 CSSPropertyID id = property.cssProperty(); 888 continue;
889 }
856 if (!anyTransitionHadTransitionAll && !animationStyleRecalc && 890 if (!anyTransitionHadTransitionAll && !animationStyleRecalc &&
857 !listedProperties.test(id - firstCSSProperty)) { 891 !listedProperties.contains(property)) {
858 update.cancelTransition(property); 892 update.cancelTransition(property);
859 } else if (entry.value.animation->finishedInternal()) { 893 } else if (entry.value.animation->finishedInternal()) {
860 update.finishTransition(property); 894 update.finishTransition(property);
861 } 895 }
862 } 896 }
863 } 897 }
864 calculateTransitionActiveInterpolations(update, animatingElement); 898
899 calculateTransitionActiveInterpolations(update, propertyPass,
900 animatingElement);
865 } 901 }
866 902
867 void CSSAnimations::cancel() { 903 void CSSAnimations::cancel() {
868 for (const auto& runningAnimation : m_runningAnimations) { 904 for (const auto& runningAnimation : m_runningAnimations) {
869 runningAnimation->animation->cancel(); 905 runningAnimation->animation->cancel();
870 runningAnimation->animation->update(TimingUpdateOnDemand); 906 runningAnimation->animation->update(TimingUpdateOnDemand);
871 } 907 }
872 908
873 for (const auto& entry : m_transitions) { 909 for (const auto& entry : m_transitions) {
874 entry.value.animation->cancel(); 910 entry.value.animation->cancel();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 newEffects.push_back(updatedAnimation.effect); 956 newEffects.push_back(updatedAnimation.effect);
921 957
922 ActiveInterpolationsMap activeInterpolationsForAnimations( 958 ActiveInterpolationsMap activeInterpolationsForAnimations(
923 EffectStack::activeInterpolations( 959 EffectStack::activeInterpolations(
924 effectStack, &newEffects, &update.suppressedAnimations(), 960 effectStack, &newEffects, &update.suppressedAnimations(),
925 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle)); 961 KeyframeEffectReadOnly::DefaultPriority, isStylePropertyHandle));
926 update.adoptActiveInterpolationsForAnimations( 962 update.adoptActiveInterpolationsForAnimations(
927 activeInterpolationsForAnimations); 963 activeInterpolationsForAnimations);
928 } 964 }
929 965
966 static bool isCustomStylePropertyHandle(const PropertyHandle& property) {
967 return property.isCSSCustomProperty();
968 }
969
970 static bool isStandardStylePropertyHandle(const PropertyHandle& property) {
971 return isStylePropertyHandle(property) && !property.isCSSCustomProperty();
972 }
973
974 static EffectStack::PropertyHandleFilter stylePropertyFilter(
975 CSSAnimations::PropertyPass propertyPass) {
976 if (propertyPass == CSSAnimations::PropertyPass::Custom) {
977 return isCustomStylePropertyHandle;
978 }
979 DCHECK_EQ(propertyPass, CSSAnimations::PropertyPass::Standard);
980 return isStandardStylePropertyHandle;
981 }
982
930 void CSSAnimations::calculateTransitionActiveInterpolations( 983 void CSSAnimations::calculateTransitionActiveInterpolations(
931 CSSAnimationUpdate& update, 984 CSSAnimationUpdate& update,
985 PropertyPass propertyPass,
932 const Element* animatingElement) { 986 const Element* animatingElement) {
933 ElementAnimations* elementAnimations = 987 ElementAnimations* elementAnimations =
934 animatingElement ? animatingElement->elementAnimations() : nullptr; 988 animatingElement ? animatingElement->elementAnimations() : nullptr;
935 EffectStack* effectStack = 989 EffectStack* effectStack =
936 elementAnimations ? &elementAnimations->effectStack() : nullptr; 990 elementAnimations ? &elementAnimations->effectStack() : nullptr;
937 991
938 ActiveInterpolationsMap activeInterpolationsForTransitions; 992 ActiveInterpolationsMap activeInterpolationsForTransitions;
939 if (update.newTransitions().isEmpty() && 993 if (update.newTransitions().isEmpty() &&
940 update.cancelledTransitions().isEmpty()) { 994 update.cancelledTransitions().isEmpty()) {
941 activeInterpolationsForTransitions = EffectStack::activeInterpolations( 995 activeInterpolationsForTransitions = EffectStack::activeInterpolations(
942 effectStack, nullptr, nullptr, 996 effectStack, nullptr, nullptr,
943 KeyframeEffectReadOnly::TransitionPriority, isStylePropertyHandle); 997 KeyframeEffectReadOnly::TransitionPriority,
998 stylePropertyFilter(propertyPass));
944 } else { 999 } else {
945 HeapVector<Member<const InertEffect>> newTransitions; 1000 HeapVector<Member<const InertEffect>> newTransitions;
946 for (const auto& entry : update.newTransitions()) 1001 for (const auto& entry : update.newTransitions())
947 newTransitions.push_back(entry.value.effect.get()); 1002 newTransitions.push_back(entry.value.effect.get());
948 1003
949 HeapHashSet<Member<const Animation>> cancelledAnimations; 1004 HeapHashSet<Member<const Animation>> cancelledAnimations;
950 if (!update.cancelledTransitions().isEmpty()) { 1005 if (!update.cancelledTransitions().isEmpty()) {
951 DCHECK(elementAnimations); 1006 DCHECK(elementAnimations);
952 const TransitionMap& transitionMap = 1007 const TransitionMap& transitionMap =
953 elementAnimations->cssAnimations().m_transitions; 1008 elementAnimations->cssAnimations().m_transitions;
954 for (const PropertyHandle& property : update.cancelledTransitions()) { 1009 for (const PropertyHandle& property : update.cancelledTransitions()) {
955 DCHECK(transitionMap.contains(property)); 1010 DCHECK(transitionMap.contains(property));
956 cancelledAnimations.insert(transitionMap.at(property).animation.get()); 1011 cancelledAnimations.insert(transitionMap.at(property).animation.get());
957 } 1012 }
958 } 1013 }
959 1014
960 activeInterpolationsForTransitions = EffectStack::activeInterpolations( 1015 activeInterpolationsForTransitions = EffectStack::activeInterpolations(
961 effectStack, &newTransitions, &cancelledAnimations, 1016 effectStack, &newTransitions, &cancelledAnimations,
962 KeyframeEffectReadOnly::TransitionPriority, isStylePropertyHandle); 1017 KeyframeEffectReadOnly::TransitionPriority,
1018 stylePropertyFilter(propertyPass));
963 } 1019 }
964 1020
965 // Properties being animated by animations don't get values from transitions 1021 // Properties being animated by animations don't get values from transitions
966 // applied. 1022 // applied.
967 if (!update.activeInterpolationsForAnimations().isEmpty() && 1023 if (!update.activeInterpolationsForAnimations().isEmpty() &&
968 !activeInterpolationsForTransitions.isEmpty()) { 1024 !activeInterpolationsForTransitions.isEmpty()) {
969 for (const auto& entry : update.activeInterpolationsForAnimations()) 1025 for (const auto& entry : update.activeInterpolationsForAnimations())
970 activeInterpolationsForTransitions.erase(entry.key); 1026 activeInterpolationsForTransitions.erase(entry.key);
971 } 1027 }
972 update.adoptActiveInterpolationsForStandardTransitions( 1028
973 activeInterpolationsForTransitions); 1029 if (propertyPass == PropertyPass::Custom) {
1030 update.adoptActiveInterpolationsForCustomTransitions(
1031 activeInterpolationsForTransitions);
1032 } else {
1033 DCHECK_EQ(propertyPass, PropertyPass::Standard);
1034 update.adoptActiveInterpolationsForStandardTransitions(
1035 activeInterpolationsForTransitions);
1036 }
974 } 1037 }
975 1038
976 EventTarget* CSSAnimations::AnimationEventDelegate::eventTarget() const { 1039 EventTarget* CSSAnimations::AnimationEventDelegate::eventTarget() const {
977 return EventPath::eventTargetRespectingTargetRules(*m_animationTarget); 1040 return EventPath::eventTargetRespectingTargetRules(*m_animationTarget);
978 } 1041 }
979 1042
980 void CSSAnimations::AnimationEventDelegate::maybeDispatch( 1043 void CSSAnimations::AnimationEventDelegate::maybeDispatch(
981 Document::ListenerType listenerType, 1044 Document::ListenerType listenerType,
982 const AtomicString& eventName, 1045 const AtomicString& eventName,
983 double elapsedTime) { 1046 double elapsedTime) {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1144 isCustomPropertyHandle); 1207 isCustomPropertyHandle);
1145 } 1208 }
1146 1209
1147 DEFINE_TRACE(CSSAnimations) { 1210 DEFINE_TRACE(CSSAnimations) {
1148 visitor->trace(m_transitions); 1211 visitor->trace(m_transitions);
1149 visitor->trace(m_pendingUpdate); 1212 visitor->trace(m_pendingUpdate);
1150 visitor->trace(m_runningAnimations); 1213 visitor->trace(m_runningAnimations);
1151 } 1214 }
1152 1215
1153 } // namespace blink 1216 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/animation/css/CSSAnimations.h ('k') | third_party/WebKit/Source/core/css/CSSPropertyEquality.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698