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 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 DEFINE_STATIC_LOCAL(SparseHistogram, propertyHistogram, | 606 DEFINE_STATIC_LOCAL(SparseHistogram, propertyHistogram, |
607 ("WebCore.Animation.CSSProperties")); | 607 ("WebCore.Animation.CSSProperties")); |
608 propertyHistogram.sample( | 608 propertyHistogram.sample( |
609 UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram( | 609 UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram( |
610 property.cssProperty())); | 610 property.cssProperty())); |
611 } | 611 } |
612 clearPendingUpdate(); | 612 clearPendingUpdate(); |
613 } | 613 } |
614 | 614 |
615 void CSSAnimations::calculateTransitionUpdateForProperty( | 615 void CSSAnimations::calculateTransitionUpdateForProperty( |
| 616 TransitionUpdateState& state, |
616 const PropertyHandle& property, | 617 const PropertyHandle& property, |
617 const CSSTransitionData& transitionData, | 618 size_t transitionIndex) { |
618 size_t transitionIndex, | 619 state.listedProperties.set(property.cssProperty() - firstCSSProperty); |
619 const ComputedStyle& oldStyle, | 620 |
620 const ComputedStyle& style, | 621 // FIXME: We should transition if an !important property changes even when an |
621 const TransitionMap* activeTransitions, | 622 // animation is running, but this is a bit hard to do with the current |
622 CSSAnimationUpdate& update, | 623 // applyMatchedProperties system. |
623 const Element* element) { | 624 if (state.update.activeInterpolationsForAnimations().contains(property) || |
| 625 (state.animatingElement->elementAnimations() && |
| 626 state.animatingElement->elementAnimations() |
| 627 ->cssAnimations() |
| 628 .m_previousActiveInterpolationsForAnimations.contains(property))) { |
| 629 return; |
| 630 } |
| 631 |
624 RefPtr<AnimatableValue> to = nullptr; | 632 RefPtr<AnimatableValue> to = nullptr; |
625 const RunningTransition* interruptedTransition = nullptr; | 633 const RunningTransition* interruptedTransition = nullptr; |
626 if (activeTransitions) { | 634 if (state.activeTransitions) { |
627 TransitionMap::const_iterator activeTransitionIter = | 635 TransitionMap::const_iterator activeTransitionIter = |
628 activeTransitions->find(property); | 636 state.activeTransitions->find(property); |
629 if (activeTransitionIter != activeTransitions->end()) { | 637 if (activeTransitionIter != state.activeTransitions->end()) { |
630 const RunningTransition* runningTransition = &activeTransitionIter->value; | 638 const RunningTransition* runningTransition = &activeTransitionIter->value; |
631 to = CSSAnimatableValueFactory::create(property.cssProperty(), style); | 639 to = CSSAnimatableValueFactory::create(property.cssProperty(), |
| 640 state.style); |
632 const AnimatableValue* activeTo = runningTransition->to.get(); | 641 const AnimatableValue* activeTo = runningTransition->to.get(); |
633 if (to->equals(activeTo)) | 642 if (to->equals(activeTo)) |
634 return; | 643 return; |
635 update.cancelTransition(property); | 644 state.update.cancelTransition(property); |
636 DCHECK(!element->elementAnimations() || | 645 DCHECK(!state.animatingElement->elementAnimations() || |
637 !element->elementAnimations()->isAnimationStyleChange()); | 646 !state.animatingElement->elementAnimations() |
| 647 ->isAnimationStyleChange()); |
638 | 648 |
639 if (to->equals(runningTransition->reversingAdjustedStartValue.get())) | 649 if (to->equals(runningTransition->reversingAdjustedStartValue.get())) { |
640 interruptedTransition = runningTransition; | 650 interruptedTransition = runningTransition; |
| 651 } |
641 } | 652 } |
642 } | 653 } |
643 | 654 |
644 if (CSSPropertyEquality::propertiesEqual(property.cssProperty(), oldStyle, | 655 if (CSSPropertyEquality::propertiesEqual(property.cssProperty(), |
645 style)) | 656 state.oldStyle, state.style)) { |
646 return; | 657 return; |
| 658 } |
647 | 659 |
648 if (!to) | 660 if (!to) |
649 to = CSSAnimatableValueFactory::create(property.cssProperty(), style); | 661 to = CSSAnimatableValueFactory::create(property.cssProperty(), state.style); |
650 RefPtr<AnimatableValue> from = | 662 RefPtr<AnimatableValue> from = |
651 CSSAnimatableValueFactory::create(property.cssProperty(), oldStyle); | 663 CSSAnimatableValueFactory::create(property.cssProperty(), state.oldStyle); |
652 | 664 |
653 // TODO(alancutter): Support transitions on registered custom properties and | 665 // TODO(alancutter): Support transitions on registered custom properties and |
654 // give the map a PropertyRegistry. | 666 // give the map a PropertyRegistry. |
655 CSSInterpolationTypesMap map(nullptr); | 667 CSSInterpolationTypesMap map(nullptr); |
656 InterpolationEnvironment oldEnvironment(map, oldStyle); | 668 InterpolationEnvironment oldEnvironment(map, state.oldStyle); |
657 InterpolationEnvironment newEnvironment(map, style); | 669 InterpolationEnvironment newEnvironment(map, state.style); |
658 InterpolationValue start = nullptr; | 670 InterpolationValue start = nullptr; |
659 InterpolationValue end = nullptr; | 671 InterpolationValue end = nullptr; |
660 const InterpolationType* transitionType = nullptr; | 672 const InterpolationType* transitionType = nullptr; |
661 for (const auto& interpolationType : map.get(property)) { | 673 for (const auto& interpolationType : map.get(property)) { |
662 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment); | 674 start = interpolationType->maybeConvertUnderlyingValue(oldEnvironment); |
663 if (!start) { | 675 if (!start) { |
664 continue; | 676 continue; |
665 } | 677 } |
666 end = interpolationType->maybeConvertUnderlyingValue(newEnvironment); | 678 end = interpolationType->maybeConvertUnderlyingValue(newEnvironment); |
667 if (!end) { | 679 if (!end) { |
668 continue; | 680 continue; |
669 } | 681 } |
670 // Merge will only succeed if the two values are considered interpolable. | 682 // Merge will only succeed if the two values are considered interpolable. |
671 if (interpolationType->maybeMergeSingles(start.clone(), end.clone())) { | 683 if (interpolationType->maybeMergeSingles(start.clone(), end.clone())) { |
672 transitionType = interpolationType.get(); | 684 transitionType = interpolationType.get(); |
673 break; | 685 break; |
674 } | 686 } |
675 } | 687 } |
676 | 688 |
677 // No smooth interpolation exists between these values so don't start a | 689 // No smooth interpolation exists between these values so don't start a |
678 // transition. | 690 // transition. |
679 if (!transitionType) { | 691 if (!transitionType) { |
680 return; | 692 return; |
681 } | 693 } |
682 | 694 |
683 // If we have multiple transitions on the same property, we will use the | 695 // If we have multiple transitions on the same property, we will use the |
684 // last one since we iterate over them in order. | 696 // last one since we iterate over them in order. |
685 | 697 |
686 Timing timing = transitionData.convertToTiming(transitionIndex); | 698 Timing timing = state.transitionData.convertToTiming(transitionIndex); |
687 if (timing.startDelay + timing.iterationDuration <= 0) { | 699 if (timing.startDelay + timing.iterationDuration <= 0) { |
688 // We may have started a transition in a prior CSSTransitionData update, | 700 // We may have started a transition in a prior CSSTransitionData update, |
689 // this CSSTransitionData update needs to override them. | 701 // this CSSTransitionData update needs to override them. |
690 // TODO(alancutter): Just iterate over the CSSTransitionDatas in reverse and | 702 // TODO(alancutter): Just iterate over the CSSTransitionDatas in reverse and |
691 // skip any properties that have already been visited so we don't need to | 703 // skip any properties that have already been visited so we don't need to |
692 // "undo" work like this. | 704 // "undo" work like this. |
693 update.unstartTransition(property); | 705 state.update.unstartTransition(property); |
694 return; | 706 return; |
695 } | 707 } |
696 | 708 |
697 AnimatableValue* reversingAdjustedStartValue = from.get(); | 709 AnimatableValue* reversingAdjustedStartValue = from.get(); |
698 double reversingShorteningFactor = 1; | 710 double reversingShorteningFactor = 1; |
699 if (interruptedTransition) { | 711 if (interruptedTransition) { |
700 const double interruptedProgress = | 712 const double interruptedProgress = |
701 interruptedTransition->animation->effect()->progress(); | 713 interruptedTransition->animation->effect()->progress(); |
702 if (!std::isnan(interruptedProgress)) { | 714 if (!std::isnan(interruptedProgress)) { |
703 reversingAdjustedStartValue = interruptedTransition->to.get(); | 715 reversingAdjustedStartValue = interruptedTransition->to.get(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 keyframes.push_back(endKeyframe); | 760 keyframes.push_back(endKeyframe); |
749 | 761 |
750 if (CompositorAnimations::isCompositableProperty(property.cssProperty())) { | 762 if (CompositorAnimations::isCompositableProperty(property.cssProperty())) { |
751 delayKeyframe->setCompositorValue(from); | 763 delayKeyframe->setCompositorValue(from); |
752 startKeyframe->setCompositorValue(from); | 764 startKeyframe->setCompositorValue(from); |
753 endKeyframe->setCompositorValue(to); | 765 endKeyframe->setCompositorValue(to); |
754 } | 766 } |
755 | 767 |
756 TransitionKeyframeEffectModel* model = | 768 TransitionKeyframeEffectModel* model = |
757 TransitionKeyframeEffectModel::create(keyframes); | 769 TransitionKeyframeEffectModel::create(keyframes); |
758 update.startTransition(property, from.get(), to.get(), | 770 state.update.startTransition( |
759 reversingAdjustedStartValue, reversingShorteningFactor, | 771 property, from.get(), to.get(), reversingAdjustedStartValue, |
760 *InertEffect::create(model, timing, false, 0)); | 772 reversingShorteningFactor, *InertEffect::create(model, timing, false, 0)); |
761 DCHECK(!element->elementAnimations() || | 773 DCHECK( |
762 !element->elementAnimations()->isAnimationStyleChange()); | 774 !state.animatingElement->elementAnimations() || |
| 775 !state.animatingElement->elementAnimations()->isAnimationStyleChange()); |
| 776 } |
| 777 |
| 778 void CSSAnimations::calculateTransitionUpdateForStandardProperty( |
| 779 TransitionUpdateState& state, |
| 780 const CSSTransitionData::TransitionProperty& transitionProperty, |
| 781 size_t transitionIndex) { |
| 782 if (transitionProperty.propertyType != |
| 783 CSSTransitionData::TransitionKnownProperty) { |
| 784 return; |
| 785 } |
| 786 |
| 787 CSSPropertyID resolvedID = |
| 788 resolveCSSPropertyID(transitionProperty.unresolvedProperty); |
| 789 bool animateAll = resolvedID == CSSPropertyAll; |
| 790 const StylePropertyShorthand& propertyList = |
| 791 animateAll ? propertiesForTransitionAll() |
| 792 : shorthandForProperty(resolvedID); |
| 793 // If not a shorthand we only execute one iteration of this loop, and |
| 794 // refer to the property directly. |
| 795 for (unsigned i = 0; !i || i < propertyList.length(); ++i) { |
| 796 CSSPropertyID longhandID = |
| 797 propertyList.length() ? propertyList.properties()[i] : resolvedID; |
| 798 PropertyHandle property = PropertyHandle(longhandID); |
| 799 DCHECK_GE(longhandID, firstCSSProperty); |
| 800 |
| 801 if (!animateAll && |
| 802 !CSSPropertyMetadata::isInterpolableProperty(longhandID)) { |
| 803 continue; |
| 804 } |
| 805 |
| 806 calculateTransitionUpdateForProperty(state, property, transitionIndex); |
| 807 } |
763 } | 808 } |
764 | 809 |
765 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, | 810 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, |
766 const Element* animatingElement, | 811 const Element* animatingElement, |
767 const ComputedStyle& style) { | 812 const ComputedStyle& style) { |
768 if (!animatingElement) | 813 if (!animatingElement) |
769 return; | 814 return; |
770 | 815 |
771 if (animatingElement->document().finishingOrIsPrinting()) | 816 if (animatingElement->document().finishingOrIsPrinting()) |
772 return; | 817 return; |
773 | 818 |
774 ElementAnimations* elementAnimations = animatingElement->elementAnimations(); | 819 ElementAnimations* elementAnimations = animatingElement->elementAnimations(); |
775 const TransitionMap* activeTransitions = | 820 const TransitionMap* activeTransitions = |
776 elementAnimations ? &elementAnimations->cssAnimations().m_transitions | 821 elementAnimations ? &elementAnimations->cssAnimations().m_transitions |
777 : nullptr; | 822 : nullptr; |
778 const CSSTransitionData* transitionData = style.transitions(); | 823 const CSSTransitionData* transitionData = style.transitions(); |
779 | 824 |
780 const bool animationStyleRecalc = | 825 const bool animationStyleRecalc = |
781 elementAnimations && elementAnimations->isAnimationStyleChange(); | 826 elementAnimations && elementAnimations->isAnimationStyleChange(); |
782 | 827 |
783 std::bitset<numCSSProperties> listedProperties; | 828 std::bitset<numCSSProperties> listedProperties; |
784 bool anyTransitionHadTransitionAll = false; | 829 bool anyTransitionHadTransitionAll = false; |
785 const LayoutObject* layoutObject = animatingElement->layoutObject(); | 830 const LayoutObject* layoutObject = animatingElement->layoutObject(); |
786 if (!animationStyleRecalc && style.display() != EDisplay::None && | 831 if (!animationStyleRecalc && style.display() != EDisplay::None && |
787 layoutObject && layoutObject->style() && transitionData) { | 832 layoutObject && layoutObject->style() && transitionData) { |
788 const ComputedStyle& oldStyle = *layoutObject->style(); | 833 TransitionUpdateState state = { |
| 834 update, animatingElement, *layoutObject->style(), |
| 835 style, activeTransitions, listedProperties, |
| 836 *transitionData}; |
789 | 837 |
790 for (size_t i = 0; i < transitionData->propertyList().size(); ++i) { | 838 for (size_t transitionIndex = 0; |
| 839 transitionIndex < transitionData->propertyList().size(); |
| 840 ++transitionIndex) { |
791 const CSSTransitionData::TransitionProperty& transitionProperty = | 841 const CSSTransitionData::TransitionProperty& transitionProperty = |
792 transitionData->propertyList()[i]; | 842 transitionData->propertyList()[transitionIndex]; |
793 if (transitionProperty.propertyType != | 843 if (transitionProperty.unresolvedProperty == CSSPropertyAll) { |
794 CSSTransitionData::TransitionKnownProperty) | |
795 continue; | |
796 | |
797 CSSPropertyID property = | |
798 resolveCSSPropertyID(transitionProperty.unresolvedProperty); | |
799 bool animateAll = property == CSSPropertyAll; | |
800 if (animateAll) | |
801 anyTransitionHadTransitionAll = true; | 844 anyTransitionHadTransitionAll = true; |
802 const StylePropertyShorthand& propertyList = | |
803 animateAll ? CSSAnimations::propertiesForTransitionAll() | |
804 : shorthandForProperty(property); | |
805 // If not a shorthand we only execute one iteration of this loop, and | |
806 // refer to the property directly. | |
807 for (unsigned j = 0; !j || j < propertyList.length(); ++j) { | |
808 CSSPropertyID id = | |
809 propertyList.length() ? propertyList.properties()[j] : property; | |
810 DCHECK_GE(id, firstCSSProperty); | |
811 | |
812 if (!animateAll) { | |
813 if (CSSPropertyMetadata::isInterpolableProperty(id)) | |
814 listedProperties.set(id - firstCSSProperty); | |
815 else | |
816 continue; | |
817 } | |
818 | |
819 // FIXME: We should transition if an !important property changes even | |
820 // when an animation is running, but this is a bit hard to do with the | |
821 // current applyMatchedProperties system. | |
822 PropertyHandle property = PropertyHandle(id); | |
823 if (!update.activeInterpolationsForAnimations().contains(property) && | |
824 (!elementAnimations || | |
825 !elementAnimations->cssAnimations() | |
826 .m_previousActiveInterpolationsForAnimations.contains( | |
827 property))) { | |
828 calculateTransitionUpdateForProperty( | |
829 property, *transitionData, i, oldStyle, style, activeTransitions, | |
830 update, animatingElement); | |
831 } | |
832 } | 845 } |
| 846 calculateTransitionUpdateForStandardProperty(state, transitionProperty, |
| 847 transitionIndex); |
833 } | 848 } |
834 } | 849 } |
835 | 850 |
836 if (activeTransitions) { | 851 if (activeTransitions) { |
837 for (const auto& entry : *activeTransitions) { | 852 for (const auto& entry : *activeTransitions) { |
838 const PropertyHandle& property = entry.key; | 853 const PropertyHandle& property = entry.key; |
839 // TODO(alancutter): Handle transitions on custom properties. | 854 // TODO(alancutter): Handle transitions on custom properties. |
840 DCHECK(!property.isCSSCustomProperty()); | 855 DCHECK(!property.isCSSCustomProperty()); |
841 CSSPropertyID id = property.cssProperty(); | 856 CSSPropertyID id = property.cssProperty(); |
842 if (!anyTransitionHadTransitionAll && !animationStyleRecalc && | 857 if (!anyTransitionHadTransitionAll && !animationStyleRecalc && |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 isCustomPropertyHandle); | 1145 isCustomPropertyHandle); |
1131 } | 1146 } |
1132 | 1147 |
1133 DEFINE_TRACE(CSSAnimations) { | 1148 DEFINE_TRACE(CSSAnimations) { |
1134 visitor->trace(m_transitions); | 1149 visitor->trace(m_transitions); |
1135 visitor->trace(m_pendingUpdate); | 1150 visitor->trace(m_pendingUpdate); |
1136 visitor->trace(m_runningAnimations); | 1151 visitor->trace(m_runningAnimations); |
1137 } | 1152 } |
1138 | 1153 |
1139 } // namespace blink | 1154 } // namespace blink |
OLD | NEW |