diff options
Diffstat (limited to 'layout/style/AnimationCollection.cpp')
-rw-r--r-- | layout/style/AnimationCollection.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/layout/style/AnimationCollection.cpp b/layout/style/AnimationCollection.cpp new file mode 100644 index 0000000000..1226c74202 --- /dev/null +++ b/layout/style/AnimationCollection.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/AnimationCollection.h" + +#include "mozilla/RestyleManager.h" +#include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch +#include "mozilla/dom/CSSAnimation.h" // For dom::CSSAnimation +#include "mozilla/dom/CSSTransition.h" // For dom::CSSTransition + +namespace mozilla { + +template <class AnimationType> +/* static */ void AnimationCollection<AnimationType>::PropertyDtor( + void* aObject, nsAtom* aPropertyName, void* aPropertyValue, void* aData) { + AnimationCollection* collection = + static_cast<AnimationCollection*>(aPropertyValue); +#ifdef DEBUG + MOZ_ASSERT(!collection->mCalledPropertyDtor, "can't call dtor twice"); + collection->mCalledPropertyDtor = true; +#endif + + PostRestyleMode postRestyle = collection->mCalledDestroy + ? PostRestyleMode::IfNeeded + : PostRestyleMode::Never; + { + nsAutoAnimationMutationBatch mb(collection->mElement->OwnerDoc()); + + for (size_t animIdx = collection->mAnimations.Length(); animIdx-- != 0;) { + collection->mAnimations[animIdx]->CancelFromStyle(postRestyle); + } + } + delete collection; +} + +template <class AnimationType> +/* static */ AnimationCollection<AnimationType>* +AnimationCollection<AnimationType>::GetAnimationCollection( + const dom::Element* aElement, PseudoStyleType aPseudoType) { + if (!aElement->MayHaveAnimations()) { + // Early return for the most common case. + return nullptr; + } + + nsAtom* propName = GetPropertyAtomForPseudoType(aPseudoType); + if (!propName) { + return nullptr; + } + + return static_cast<AnimationCollection<AnimationType>*>( + aElement->GetProperty(propName)); +} + +template <class AnimationType> +/* static */ AnimationCollection<AnimationType>* +AnimationCollection<AnimationType>::GetAnimationCollection( + const nsIFrame* aFrame) { + Maybe<NonOwningAnimationTarget> pseudoElement = + EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame); + if (!pseudoElement) { + return nullptr; + } + + if (!pseudoElement->mElement->MayHaveAnimations()) { + return nullptr; + } + + return GetAnimationCollection(pseudoElement->mElement, + pseudoElement->mPseudoType); +} + +template <class AnimationType> +/* static */ AnimationCollection<AnimationType>* +AnimationCollection<AnimationType>::GetOrCreateAnimationCollection( + dom::Element* aElement, PseudoStyleType aPseudoType, + bool* aCreatedCollection) { + MOZ_ASSERT(aCreatedCollection); + *aCreatedCollection = false; + + nsAtom* propName = GetPropertyAtomForPseudoType(aPseudoType); + MOZ_ASSERT(propName, + "Should only try to create animations for one of the" + " recognized pseudo types"); + + auto collection = static_cast<AnimationCollection<AnimationType>*>( + aElement->GetProperty(propName)); + if (!collection) { + // FIXME: Consider arena-allocating? + collection = new AnimationCollection<AnimationType>(aElement, propName); + nsresult rv = aElement->SetProperty( + propName, collection, &AnimationCollection<AnimationType>::PropertyDtor, + false); + if (NS_FAILED(rv)) { + NS_WARNING("SetProperty failed"); + // The collection must be destroyed via PropertyDtor, otherwise + // mCalledPropertyDtor assertion is triggered in destructor. + AnimationCollection<AnimationType>::PropertyDtor(aElement, propName, + collection, nullptr); + return nullptr; + } + + *aCreatedCollection = true; + aElement->SetMayHaveAnimations(); + } + + return collection; +} + +template <class AnimationType> +/*static*/ nsAtom* +AnimationCollection<AnimationType>::GetPropertyAtomForPseudoType( + PseudoStyleType aPseudoType) { + nsAtom* propName = nullptr; + + if (aPseudoType == PseudoStyleType::NotPseudo) { + propName = TraitsType::ElementPropertyAtom(); + } else if (aPseudoType == PseudoStyleType::before) { + propName = TraitsType::BeforePropertyAtom(); + } else if (aPseudoType == PseudoStyleType::after) { + propName = TraitsType::AfterPropertyAtom(); + } else if (aPseudoType == PseudoStyleType::marker) { + propName = TraitsType::MarkerPropertyAtom(); + } + + return propName; +} + +template <class AnimationType> +void AnimationCollection<AnimationType>::Destroy() { + mCalledDestroy = true; + + // This will call our destructor. + mElement->RemoveProperty(mElementProperty); +} + +// Explicit class instantiations + +template class AnimationCollection<dom::CSSAnimation>; +template class AnimationCollection<dom::CSSTransition>; + +} // namespace mozilla |