AnimationCollection.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/AnimationCollection.h"
  6. #include "mozilla/RestyleManagerHandle.h"
  7. #include "mozilla/RestyleManagerHandleInlines.h"
  8. #include "nsAnimationManager.h" // For dom::CSSAnimation
  9. #include "nsPresContext.h"
  10. #include "nsTransitionManager.h" // For dom::CSSTransition
  11. namespace mozilla {
  12. template <class AnimationType>
  13. /* static */ void
  14. AnimationCollection<AnimationType>::PropertyDtor(void* aObject,
  15. nsIAtom* aPropertyName,
  16. void* aPropertyValue,
  17. void* aData)
  18. {
  19. AnimationCollection* collection =
  20. static_cast<AnimationCollection*>(aPropertyValue);
  21. #ifdef DEBUG
  22. MOZ_ASSERT(!collection->mCalledPropertyDtor, "can't call dtor twice");
  23. collection->mCalledPropertyDtor = true;
  24. #endif
  25. {
  26. nsAutoAnimationMutationBatch mb(collection->mElement->OwnerDoc());
  27. for (size_t animIdx = collection->mAnimations.Length(); animIdx-- != 0; ) {
  28. collection->mAnimations[animIdx]->CancelFromStyle();
  29. }
  30. }
  31. delete collection;
  32. }
  33. template <class AnimationType>
  34. /* static */ AnimationCollection<AnimationType>*
  35. AnimationCollection<AnimationType>::GetAnimationCollection(
  36. dom::Element *aElement,
  37. CSSPseudoElementType aPseudoType)
  38. {
  39. if (!aElement->MayHaveAnimations()) {
  40. // Early return for the most common case.
  41. return nullptr;
  42. }
  43. nsIAtom* propName = GetPropertyAtomForPseudoType(aPseudoType);
  44. if (!propName) {
  45. return nullptr;
  46. }
  47. return
  48. static_cast<AnimationCollection<AnimationType>*>(aElement->
  49. GetProperty(propName));
  50. }
  51. template <class AnimationType>
  52. /* static */ AnimationCollection<AnimationType>*
  53. AnimationCollection<AnimationType>::GetAnimationCollection(
  54. const nsIFrame* aFrame)
  55. {
  56. Maybe<NonOwningAnimationTarget> pseudoElement =
  57. EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
  58. if (!pseudoElement) {
  59. return nullptr;
  60. }
  61. if (!pseudoElement->mElement->MayHaveAnimations()) {
  62. return nullptr;
  63. }
  64. return GetAnimationCollection(pseudoElement->mElement,
  65. pseudoElement->mPseudoType);
  66. }
  67. template <class AnimationType>
  68. /* static */ AnimationCollection<AnimationType>*
  69. AnimationCollection<AnimationType>::GetOrCreateAnimationCollection(
  70. dom::Element* aElement,
  71. CSSPseudoElementType aPseudoType,
  72. bool* aCreatedCollection)
  73. {
  74. MOZ_ASSERT(aCreatedCollection);
  75. *aCreatedCollection = false;
  76. nsIAtom* propName = GetPropertyAtomForPseudoType(aPseudoType);
  77. MOZ_ASSERT(propName, "Should only try to create animations for one of the"
  78. " recognized pseudo types");
  79. auto collection = static_cast<AnimationCollection<AnimationType>*>(
  80. aElement->GetProperty(propName));
  81. if (!collection) {
  82. // FIXME: Consider arena-allocating?
  83. collection = new AnimationCollection<AnimationType>(aElement, propName);
  84. nsresult rv =
  85. aElement->SetProperty(propName, collection,
  86. &AnimationCollection<AnimationType>::PropertyDtor,
  87. false);
  88. if (NS_FAILED(rv)) {
  89. NS_WARNING("SetProperty failed");
  90. // The collection must be destroyed via PropertyDtor, otherwise
  91. // mCalledPropertyDtor assertion is triggered in destructor.
  92. AnimationCollection<AnimationType>::PropertyDtor(aElement, propName,
  93. collection, nullptr);
  94. return nullptr;
  95. }
  96. *aCreatedCollection = true;
  97. aElement->SetMayHaveAnimations();
  98. }
  99. return collection;
  100. }
  101. template <class AnimationType>
  102. /* static */ nsString
  103. AnimationCollection<AnimationType>::PseudoTypeAsString(
  104. CSSPseudoElementType aPseudoType)
  105. {
  106. switch (aPseudoType) {
  107. case CSSPseudoElementType::before:
  108. return NS_LITERAL_STRING("::before");
  109. case CSSPseudoElementType::after:
  110. return NS_LITERAL_STRING("::after");
  111. default:
  112. MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo,
  113. "Unexpected pseudo type");
  114. return EmptyString();
  115. }
  116. }
  117. template <class AnimationType>
  118. void
  119. AnimationCollection<AnimationType>::UpdateCheckGeneration(
  120. nsPresContext* aPresContext)
  121. {
  122. if (aPresContext->RestyleManager()->IsServo()) {
  123. // stylo: ServoRestyleManager does not support animations yet.
  124. return;
  125. }
  126. mCheckGeneration =
  127. aPresContext->RestyleManager()->AsGecko()->GetAnimationGeneration();
  128. }
  129. template<class AnimationType>
  130. /*static*/ nsIAtom*
  131. AnimationCollection<AnimationType>::GetPropertyAtomForPseudoType(
  132. CSSPseudoElementType aPseudoType)
  133. {
  134. nsIAtom* propName = nullptr;
  135. if (aPseudoType == CSSPseudoElementType::NotPseudo) {
  136. propName = TraitsType::ElementPropertyAtom();
  137. } else if (aPseudoType == CSSPseudoElementType::before) {
  138. propName = TraitsType::BeforePropertyAtom();
  139. } else if (aPseudoType == CSSPseudoElementType::after) {
  140. propName = TraitsType::AfterPropertyAtom();
  141. }
  142. return propName;
  143. }
  144. // Explicit class instantiations
  145. template class AnimationCollection<dom::CSSAnimation>;
  146. template class AnimationCollection<dom::CSSTransition>;
  147. } // namespace mozilla