summaryrefslogtreecommitdiffstats
path: root/dom/animation/EffectSet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/animation/EffectSet.cpp')
-rw-r--r--dom/animation/EffectSet.cpp177
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