/* -*- 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 "mozilla/RestyleManagerInlines.h" #include "nsAnimationManager.h" // For dom::CSSAnimation #include "nsPresContext.h" #include "nsTransitionManager.h" // For dom::CSSTransition namespace mozilla { template /* static */ void AnimationCollection::PropertyDtor(void* aObject, nsIAtom* 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 { nsAutoAnimationMutationBatch mb(collection->mElement->OwnerDoc()); for (size_t animIdx = collection->mAnimations.Length(); animIdx-- != 0; ) { collection->mAnimations[animIdx]->CancelFromStyle(); } } delete collection; } template /* static */ AnimationCollection* AnimationCollection::GetAnimationCollection( const dom::Element *aElement, CSSPseudoElementType aPseudoType) { if (!aElement->MayHaveAnimations()) { // Early return for the most common case. return nullptr; } nsIAtom* 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, CSSPseudoElementType aPseudoType, bool* aCreatedCollection) { MOZ_ASSERT(aCreatedCollection); *aCreatedCollection = false; nsIAtom* 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 */ nsString AnimationCollection::PseudoTypeAsString( CSSPseudoElementType aPseudoType) { switch (aPseudoType) { case CSSPseudoElementType::before: return NS_LITERAL_STRING("::before"); case CSSPseudoElementType::after: return NS_LITERAL_STRING("::after"); default: MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo, "Unexpected pseudo type"); return EmptyString(); } } template void AnimationCollection::UpdateCheckGeneration( nsPresContext* aPresContext) { if (aPresContext->RestyleManager()->IsServo()) { // stylo: ServoRestyleManager does not support animations yet. return; } mCheckGeneration = aPresContext->RestyleManager()->AsGecko()->GetAnimationGeneration(); } template /*static*/ nsIAtom* AnimationCollection::GetPropertyAtomForPseudoType( CSSPseudoElementType aPseudoType) { nsIAtom* propName = nullptr; if (aPseudoType == CSSPseudoElementType::NotPseudo) { propName = TraitsType::ElementPropertyAtom(); } else if (aPseudoType == CSSPseudoElementType::before) { propName = TraitsType::BeforePropertyAtom(); } else if (aPseudoType == CSSPseudoElementType::after) { propName = TraitsType::AfterPropertyAtom(); } return propName; } // Explicit class instantiations template class AnimationCollection; template class AnimationCollection; } // namespace mozilla