/* -*- 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 /* static */ void AnimationCollection::PropertyDtor( void* aObject, nsAtom* aPropertyName, void* aPropertyValue, void* aData) { AnimationCollection* collection = static_cast(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 /* static */ AnimationCollection* AnimationCollection::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*>( aElement->GetProperty(propName)); } template /* static */ AnimationCollection* AnimationCollection::GetAnimationCollection( const nsIFrame* aFrame) { Maybe pseudoElement = EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame); if (!pseudoElement) { return nullptr; } if (!pseudoElement->mElement->MayHaveAnimations()) { return nullptr; } return GetAnimationCollection(pseudoElement->mElement, pseudoElement->mPseudoType); } template /* static */ AnimationCollection* AnimationCollection::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*>( aElement->GetProperty(propName)); if (!collection) { // FIXME: Consider arena-allocating? collection = new AnimationCollection(aElement, propName); nsresult rv = aElement->SetProperty( propName, collection, &AnimationCollection::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::PropertyDtor(aElement, propName, collection, nullptr); return nullptr; } *aCreatedCollection = true; aElement->SetMayHaveAnimations(); } return collection; } template /*static*/ nsAtom* AnimationCollection::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 void AnimationCollection::Destroy() { mCalledDestroy = true; // This will call our destructor. mElement->RemoveProperty(mElementProperty); } // Explicit class instantiations template class AnimationCollection; template class AnimationCollection; } // namespace mozilla