diff options
Diffstat (limited to 'dom/animation/EffectSet.cpp')
-rw-r--r-- | dom/animation/EffectSet.cpp | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/dom/animation/EffectSet.cpp b/dom/animation/EffectSet.cpp new file mode 100644 index 000000000..ffd3bb523 --- /dev/null +++ b/dom/animation/EffectSet.cpp @@ -0,0 +1,177 @@ +/* -*- 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 "EffectSet.h" +#include "mozilla/dom/Element.h" // For Element +#include "mozilla/RestyleManagerHandle.h" +#include "mozilla/RestyleManagerHandleInlines.h" +#include "nsCSSPseudoElements.h" // For CSSPseudoElementType +#include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild +#include "nsPresContext.h" +#include "nsLayoutUtils.h" + +namespace mozilla { + +/* static */ void +EffectSet::PropertyDtor(void* aObject, nsIAtom* aPropertyName, + void* aPropertyValue, void* aData) +{ + EffectSet* effectSet = static_cast<EffectSet*>(aPropertyValue); + +#ifdef DEBUG + MOZ_ASSERT(!effectSet->mCalledPropertyDtor, "Should not call dtor twice"); + effectSet->mCalledPropertyDtor = true; +#endif + + delete effectSet; +} + +void +EffectSet::Traverse(nsCycleCollectionTraversalCallback& aCallback) +{ + for (auto iter = mEffects.Iter(); !iter.Done(); iter.Next()) { + CycleCollectionNoteChild(aCallback, iter.Get()->GetKey(), + "EffectSet::mEffects[]", aCallback.Flags()); + } +} + +/* static */ EffectSet* +EffectSet::GetEffectSet(dom::Element* aElement, + CSSPseudoElementType aPseudoType) +{ + nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType); + return static_cast<EffectSet*>(aElement->GetProperty(propName)); +} + +/* static */ EffectSet* +EffectSet::GetEffectSet(const nsIFrame* aFrame) +{ + Maybe<NonOwningAnimationTarget> target = + EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame); + + if (!target) { + return nullptr; + } + + if (!target->mElement->MayHaveAnimations()) { + return nullptr; + } + + return GetEffectSet(target->mElement, target->mPseudoType); +} + +/* static */ EffectSet* +EffectSet::GetOrCreateEffectSet(dom::Element* aElement, + CSSPseudoElementType aPseudoType) +{ + EffectSet* effectSet = GetEffectSet(aElement, aPseudoType); + if (effectSet) { + return effectSet; + } + + nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType); + effectSet = new EffectSet(); + + nsresult rv = aElement->SetProperty(propName, effectSet, + &EffectSet::PropertyDtor, true); + if (NS_FAILED(rv)) { + NS_WARNING("SetProperty failed"); + // The set must be destroyed via PropertyDtor, otherwise + // mCalledPropertyDtor assertion is triggered in destructor. + EffectSet::PropertyDtor(aElement, propName, effectSet, nullptr); + return nullptr; + } + + aElement->SetMayHaveAnimations(); + + return effectSet; +} + +/* static */ void +EffectSet::DestroyEffectSet(dom::Element* aElement, + CSSPseudoElementType aPseudoType) +{ + nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType); + EffectSet* effectSet = + static_cast<EffectSet*>(aElement->GetProperty(propName)); + if (!effectSet) { + return; + } + + MOZ_ASSERT(!effectSet->IsBeingEnumerated(), + "Should not destroy an effect set while it is being enumerated"); + effectSet = nullptr; + + aElement->DeleteProperty(propName); +} + +void +EffectSet::UpdateAnimationGeneration(nsPresContext* aPresContext) +{ + MOZ_ASSERT(aPresContext->RestyleManager()->IsGecko(), + "stylo: Servo-backed style system should not be using " + "EffectSet"); + mAnimationGeneration = + aPresContext->RestyleManager()->AsGecko()->GetAnimationGeneration(); +} + +/* static */ nsIAtom** +EffectSet::GetEffectSetPropertyAtoms() +{ + static nsIAtom* effectSetPropertyAtoms[] = + { + nsGkAtoms::animationEffectsProperty, + nsGkAtoms::animationEffectsForBeforeProperty, + nsGkAtoms::animationEffectsForAfterProperty, + nullptr + }; + + return effectSetPropertyAtoms; +} + +/* static */ nsIAtom* +EffectSet::GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType) +{ + switch (aPseudoType) { + case CSSPseudoElementType::NotPseudo: + return nsGkAtoms::animationEffectsProperty; + + case CSSPseudoElementType::before: + return nsGkAtoms::animationEffectsForBeforeProperty; + + case CSSPseudoElementType::after: + return nsGkAtoms::animationEffectsForAfterProperty; + + default: + NS_NOTREACHED("Should not try to get animation effects for a pseudo " + "other that :before or :after"); + return nullptr; + } +} + +void +EffectSet::AddEffect(dom::KeyframeEffectReadOnly& aEffect) +{ + if (mEffects.Contains(&aEffect)) { + return; + } + + mEffects.PutEntry(&aEffect); + MarkCascadeNeedsUpdate(); +} + +void +EffectSet::RemoveEffect(dom::KeyframeEffectReadOnly& aEffect) +{ + if (!mEffects.Contains(&aEffect)) { + return; + } + + mEffects.RemoveEntry(&aEffect); + MarkCascadeNeedsUpdate(); +} + +} // namespace mozilla |