Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "EffectSet.h"
8 : #include "mozilla/dom/Element.h" // For Element
9 : #include "mozilla/RestyleManager.h"
10 : #include "mozilla/RestyleManagerInlines.h"
11 : #include "nsCSSPseudoElements.h" // For CSSPseudoElementType
12 : #include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
13 : #include "nsPresContext.h"
14 : #include "nsLayoutUtils.h"
15 :
16 : namespace mozilla {
17 :
18 : /* static */ void
19 2 : EffectSet::PropertyDtor(void* aObject, nsIAtom* aPropertyName,
20 : void* aPropertyValue, void* aData)
21 : {
22 2 : EffectSet* effectSet = static_cast<EffectSet*>(aPropertyValue);
23 :
24 : #ifdef DEBUG
25 2 : MOZ_ASSERT(!effectSet->mCalledPropertyDtor, "Should not call dtor twice");
26 2 : effectSet->mCalledPropertyDtor = true;
27 : #endif
28 :
29 2 : delete effectSet;
30 2 : }
31 :
32 : void
33 0 : EffectSet::Traverse(nsCycleCollectionTraversalCallback& aCallback)
34 : {
35 0 : for (auto iter = mEffects.Iter(); !iter.Done(); iter.Next()) {
36 0 : CycleCollectionNoteChild(aCallback, iter.Get()->GetKey(),
37 0 : "EffectSet::mEffects[]", aCallback.Flags());
38 : }
39 0 : }
40 :
41 : /* static */ EffectSet*
42 32533 : EffectSet::GetEffectSet(const dom::Element* aElement,
43 : CSSPseudoElementType aPseudoType)
44 : {
45 32533 : if (!aElement->MayHaveAnimations()) {
46 32282 : return nullptr;
47 : }
48 :
49 251 : nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
50 251 : return static_cast<EffectSet*>(aElement->GetProperty(propName));
51 : }
52 :
53 : /* static */ EffectSet*
54 11847 : EffectSet::GetEffectSet(const nsIFrame* aFrame)
55 : {
56 : Maybe<NonOwningAnimationTarget> target =
57 23694 : EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
58 :
59 11847 : if (!target) {
60 2728 : return nullptr;
61 : }
62 :
63 9119 : return GetEffectSet(target->mElement, target->mPseudoType);
64 : }
65 :
66 : /* static */ EffectSet*
67 2 : EffectSet::GetOrCreateEffectSet(dom::Element* aElement,
68 : CSSPseudoElementType aPseudoType)
69 : {
70 2 : EffectSet* effectSet = GetEffectSet(aElement, aPseudoType);
71 2 : if (effectSet) {
72 0 : return effectSet;
73 : }
74 :
75 2 : nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
76 2 : effectSet = new EffectSet();
77 :
78 2 : nsresult rv = aElement->SetProperty(propName, effectSet,
79 2 : &EffectSet::PropertyDtor, true);
80 2 : if (NS_FAILED(rv)) {
81 0 : NS_WARNING("SetProperty failed");
82 : // The set must be destroyed via PropertyDtor, otherwise
83 : // mCalledPropertyDtor assertion is triggered in destructor.
84 0 : EffectSet::PropertyDtor(aElement, propName, effectSet, nullptr);
85 0 : return nullptr;
86 : }
87 :
88 2 : aElement->SetMayHaveAnimations();
89 :
90 2 : return effectSet;
91 : }
92 :
93 : /* static */ void
94 2 : EffectSet::DestroyEffectSet(dom::Element* aElement,
95 : CSSPseudoElementType aPseudoType)
96 : {
97 2 : nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
98 : EffectSet* effectSet =
99 2 : static_cast<EffectSet*>(aElement->GetProperty(propName));
100 2 : if (!effectSet) {
101 0 : return;
102 : }
103 :
104 2 : MOZ_ASSERT(!effectSet->IsBeingEnumerated(),
105 : "Should not destroy an effect set while it is being enumerated");
106 2 : effectSet = nullptr;
107 :
108 2 : aElement->DeleteProperty(propName);
109 : }
110 :
111 : void
112 2 : EffectSet::UpdateAnimationGeneration(nsPresContext* aPresContext)
113 : {
114 2 : mAnimationGeneration =
115 2 : aPresContext->RestyleManager()->GetAnimationGeneration();
116 2 : }
117 :
118 : /* static */ nsIAtom**
119 432 : EffectSet::GetEffectSetPropertyAtoms()
120 : {
121 : static nsIAtom* effectSetPropertyAtoms[] =
122 : {
123 : nsGkAtoms::animationEffectsProperty,
124 : nsGkAtoms::animationEffectsForBeforeProperty,
125 : nsGkAtoms::animationEffectsForAfterProperty,
126 : nullptr
127 432 : };
128 :
129 432 : return effectSetPropertyAtoms;
130 : }
131 :
132 : /* static */ nsIAtom*
133 255 : EffectSet::GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType)
134 : {
135 255 : switch (aPseudoType) {
136 : case CSSPseudoElementType::NotPseudo:
137 255 : return nsGkAtoms::animationEffectsProperty;
138 :
139 : case CSSPseudoElementType::before:
140 0 : return nsGkAtoms::animationEffectsForBeforeProperty;
141 :
142 : case CSSPseudoElementType::after:
143 0 : return nsGkAtoms::animationEffectsForAfterProperty;
144 :
145 : default:
146 0 : NS_NOTREACHED("Should not try to get animation effects for a pseudo "
147 : "other that :before or :after");
148 0 : return nullptr;
149 : }
150 : }
151 :
152 : void
153 2 : EffectSet::AddEffect(dom::KeyframeEffectReadOnly& aEffect)
154 : {
155 2 : if (mEffects.Contains(&aEffect)) {
156 0 : return;
157 : }
158 :
159 2 : mEffects.PutEntry(&aEffect);
160 2 : MarkCascadeNeedsUpdate();
161 : }
162 :
163 : void
164 2 : EffectSet::RemoveEffect(dom::KeyframeEffectReadOnly& aEffect)
165 : {
166 2 : if (!mEffects.Contains(&aEffect)) {
167 0 : return;
168 : }
169 :
170 2 : mEffects.RemoveEntry(&aEffect);
171 2 : MarkCascadeNeedsUpdate();
172 : }
173 :
174 : } // namespace mozilla
|