Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/animation/EffectSet.cpp
Line
Count
Source (jump to first uncovered line)
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 "nsCSSPseudoElements.h" // For CSSPseudoElementType
11
#include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
12
#include "nsPresContext.h"
13
#include "nsLayoutUtils.h"
14
15
namespace mozilla {
16
17
/* static */ void
18
EffectSet::PropertyDtor(void* aObject, nsAtom* aPropertyName,
19
                        void* aPropertyValue, void* aData)
20
0
{
21
0
  EffectSet* effectSet = static_cast<EffectSet*>(aPropertyValue);
22
0
23
#ifdef DEBUG
24
  MOZ_ASSERT(!effectSet->mCalledPropertyDtor, "Should not call dtor twice");
25
  effectSet->mCalledPropertyDtor = true;
26
#endif
27
28
0
  delete effectSet;
29
0
}
30
31
void
32
EffectSet::Traverse(nsCycleCollectionTraversalCallback& aCallback)
33
0
{
34
0
  for (auto iter = mEffects.Iter(); !iter.Done(); iter.Next()) {
35
0
    CycleCollectionNoteChild(aCallback, iter.Get()->GetKey(),
36
0
                             "EffectSet::mEffects[]", aCallback.Flags());
37
0
  }
38
0
}
39
40
/* static */ EffectSet*
41
EffectSet::GetEffectSet(const dom::Element* aElement,
42
                        CSSPseudoElementType aPseudoType)
43
0
{
44
0
  if (!aElement->MayHaveAnimations()) {
45
0
    return nullptr;
46
0
  }
47
0
48
0
  nsAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
49
0
  return static_cast<EffectSet*>(aElement->GetProperty(propName));
50
0
}
51
52
/* static */ EffectSet*
53
EffectSet::GetEffectSet(const nsIFrame* aFrame)
54
0
{
55
0
  Maybe<NonOwningAnimationTarget> target =
56
0
    EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
57
0
58
0
  if (!target) {
59
0
    return nullptr;
60
0
  }
61
0
62
0
  return GetEffectSet(target->mElement, target->mPseudoType);
63
0
}
64
65
/* static */ EffectSet*
66
EffectSet::GetOrCreateEffectSet(dom::Element* aElement,
67
                                CSSPseudoElementType aPseudoType)
68
0
{
69
0
  EffectSet* effectSet = GetEffectSet(aElement, aPseudoType);
70
0
  if (effectSet) {
71
0
    return effectSet;
72
0
  }
73
0
74
0
  nsAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
75
0
  effectSet = new EffectSet();
76
0
77
0
  nsresult rv = aElement->SetProperty(propName, effectSet,
78
0
                                      &EffectSet::PropertyDtor, true);
79
0
  if (NS_FAILED(rv)) {
80
0
    NS_WARNING("SetProperty failed");
81
0
    // The set must be destroyed via PropertyDtor, otherwise
82
0
    // mCalledPropertyDtor assertion is triggered in destructor.
83
0
    EffectSet::PropertyDtor(aElement, propName, effectSet, nullptr);
84
0
    return nullptr;
85
0
  }
86
0
87
0
  aElement->SetMayHaveAnimations();
88
0
89
0
  return effectSet;
90
0
}
91
92
/* static */ void
93
EffectSet::DestroyEffectSet(dom::Element* aElement,
94
                            CSSPseudoElementType aPseudoType)
95
0
{
96
0
  nsAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
97
0
  EffectSet* effectSet =
98
0
    static_cast<EffectSet*>(aElement->GetProperty(propName));
99
0
  if (!effectSet) {
100
0
    return;
101
0
  }
102
0
103
0
  MOZ_ASSERT(!effectSet->IsBeingEnumerated(),
104
0
             "Should not destroy an effect set while it is being enumerated");
105
0
  effectSet = nullptr;
106
0
107
0
  aElement->DeleteProperty(propName);
108
0
}
109
110
void
111
EffectSet::UpdateAnimationGeneration(nsPresContext* aPresContext)
112
0
{
113
0
  mAnimationGeneration =
114
0
    aPresContext->RestyleManager()->GetAnimationGeneration();
115
0
}
116
117
/* static */ nsAtom**
118
EffectSet::GetEffectSetPropertyAtoms()
119
0
{
120
0
  static nsAtom* effectSetPropertyAtoms[] =
121
0
    {
122
0
      nsGkAtoms::animationEffectsProperty,
123
0
      nsGkAtoms::animationEffectsForBeforeProperty,
124
0
      nsGkAtoms::animationEffectsForAfterProperty,
125
0
      nullptr
126
0
    };
127
0
128
0
  return effectSetPropertyAtoms;
129
0
}
130
131
/* static */ nsAtom*
132
EffectSet::GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType)
133
0
{
134
0
  switch (aPseudoType) {
135
0
    case CSSPseudoElementType::NotPseudo:
136
0
      return nsGkAtoms::animationEffectsProperty;
137
0
138
0
    case CSSPseudoElementType::before:
139
0
      return nsGkAtoms::animationEffectsForBeforeProperty;
140
0
141
0
    case CSSPseudoElementType::after:
142
0
      return nsGkAtoms::animationEffectsForAfterProperty;
143
0
144
0
    default:
145
0
      MOZ_ASSERT_UNREACHABLE("Should not try to get animation effects for "
146
0
                             "a pseudo other that :before or :after");
147
0
      return nullptr;
148
0
  }
149
0
}
150
151
void
152
EffectSet::AddEffect(dom::KeyframeEffect& aEffect)
153
0
{
154
0
  if (!mEffects.EnsureInserted(&aEffect)) {
155
0
    return;
156
0
  }
157
0
158
0
  MarkCascadeNeedsUpdate();
159
0
}
160
161
void
162
EffectSet::RemoveEffect(dom::KeyframeEffect& aEffect)
163
0
{
164
0
  if (!mEffects.EnsureRemoved(&aEffect)) {
165
0
    return;
166
0
  }
167
0
168
0
  MarkCascadeNeedsUpdate();
169
0
}
170
171
} // namespace mozilla