Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/smil/nsSMILInstanceTime.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 "nsSMILInstanceTime.h"
8
#include "nsSMILInterval.h"
9
#include "nsSMILTimeValueSpec.h"
10
#include "mozilla/AutoRestore.h"
11
12
//----------------------------------------------------------------------
13
// Implementation
14
15
nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime,
16
                                       nsSMILInstanceTimeSource aSource,
17
                                       nsSMILTimeValueSpec* aCreator,
18
                                       nsSMILInterval* aBaseInterval)
19
  : mTime(aTime),
20
    mFlags(0),
21
    mVisited(false),
22
    mFixedEndpointRefCnt(0),
23
    mSerial(0),
24
    mCreator(aCreator),
25
    mBaseInterval(nullptr) // This will get set to aBaseInterval in a call to
26
                          // SetBaseInterval() at end of constructor
27
0
{
28
0
  switch (aSource) {
29
0
    case SOURCE_NONE:
30
0
      // No special flags
31
0
      break;
32
0
33
0
    case SOURCE_DOM:
34
0
      mFlags = kDynamic | kFromDOM;
35
0
      break;
36
0
37
0
    case SOURCE_SYNCBASE:
38
0
      mFlags = kMayUpdate;
39
0
      break;
40
0
41
0
    case SOURCE_EVENT:
42
0
      mFlags = kDynamic;
43
0
      break;
44
0
  }
45
0
46
0
  SetBaseInterval(aBaseInterval);
47
0
}
48
49
nsSMILInstanceTime::~nsSMILInstanceTime()
50
0
{
51
0
  MOZ_ASSERT(!mBaseInterval,
52
0
             "Destroying instance time without first calling Unlink()");
53
0
  MOZ_ASSERT(mFixedEndpointRefCnt == 0,
54
0
             "Destroying instance time that is still used as the fixed "
55
0
             "endpoint of an interval");
56
0
}
57
58
void
59
nsSMILInstanceTime::Unlink()
60
0
{
61
0
  RefPtr<nsSMILInstanceTime> deathGrip(this);
62
0
  if (mBaseInterval) {
63
0
    mBaseInterval->RemoveDependentTime(*this);
64
0
    mBaseInterval = nullptr;
65
0
  }
66
0
  mCreator = nullptr;
67
0
}
68
69
void
70
nsSMILInstanceTime::HandleChangedInterval(
71
    const nsSMILTimeContainer* aSrcContainer,
72
    bool aBeginObjectChanged,
73
    bool aEndObjectChanged)
74
0
{
75
0
  // It's possible a sequence of notifications might cause our base interval to
76
0
  // be updated and then deleted. Furthermore, the delete might happen whilst
77
0
  // we're still in the queue to be notified of the change. In any case, if we
78
0
  // don't have a base interval, just ignore the change.
79
0
  if (!mBaseInterval)
80
0
    return;
81
0
82
0
  MOZ_ASSERT(mCreator, "Base interval is set but creator is not.");
83
0
84
0
  if (mVisited) {
85
0
    // Break the cycle here
86
0
    Unlink();
87
0
    return;
88
0
  }
89
0
90
0
  bool objectChanged = mCreator->DependsOnBegin() ? aBeginObjectChanged :
91
0
                                                      aEndObjectChanged;
92
0
93
0
  RefPtr<nsSMILInstanceTime> deathGrip(this);
94
0
  mozilla::AutoRestore<bool> setVisited(mVisited);
95
0
  mVisited = true;
96
0
97
0
  mCreator->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer, *this,
98
0
                                      objectChanged);
99
0
}
100
101
void
102
nsSMILInstanceTime::HandleDeletedInterval()
103
0
{
104
0
  MOZ_ASSERT(mBaseInterval,
105
0
             "Got call to HandleDeletedInterval on an independent instance "
106
0
             "time");
107
0
  MOZ_ASSERT(mCreator, "Base interval is set but creator is not");
108
0
109
0
  mBaseInterval = nullptr;
110
0
  mFlags &= ~kMayUpdate; // Can't update without a base interval
111
0
112
0
  RefPtr<nsSMILInstanceTime> deathGrip(this);
113
0
  mCreator->HandleDeletedInstanceTime(*this);
114
0
  mCreator = nullptr;
115
0
}
116
117
void
118
nsSMILInstanceTime::HandleFilteredInterval()
119
0
{
120
0
  MOZ_ASSERT(mBaseInterval,
121
0
             "Got call to HandleFilteredInterval on an independent instance "
122
0
             "time");
123
0
124
0
  mBaseInterval = nullptr;
125
0
  mFlags &= ~kMayUpdate; // Can't update without a base interval
126
0
  mCreator = nullptr;
127
0
}
128
129
bool
130
nsSMILInstanceTime::ShouldPreserve() const
131
0
{
132
0
  return mFixedEndpointRefCnt > 0 || (mFlags & kWasDynamicEndpoint);
133
0
}
134
135
void
136
nsSMILInstanceTime::UnmarkShouldPreserve()
137
0
{
138
0
  mFlags &= ~kWasDynamicEndpoint;
139
0
}
140
141
void
142
nsSMILInstanceTime::AddRefFixedEndpoint()
143
0
{
144
0
  MOZ_ASSERT(mFixedEndpointRefCnt < UINT16_MAX,
145
0
             "Fixed endpoint reference count upper limit reached");
146
0
  ++mFixedEndpointRefCnt;
147
0
  mFlags &= ~kMayUpdate; // Once fixed, always fixed
148
0
}
149
150
void
151
nsSMILInstanceTime::ReleaseFixedEndpoint()
152
0
{
153
0
  MOZ_ASSERT(mFixedEndpointRefCnt > 0, "Duplicate release");
154
0
  --mFixedEndpointRefCnt;
155
0
  if (mFixedEndpointRefCnt == 0 && IsDynamic()) {
156
0
    mFlags |= kWasDynamicEndpoint;
157
0
  }
158
0
}
159
160
bool
161
nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime& aOther) const
162
0
{
163
0
  if (mVisited)
164
0
    return false;
165
0
166
0
  const nsSMILInstanceTime* myBaseTime = GetBaseTime();
167
0
  if (!myBaseTime)
168
0
    return false;
169
0
170
0
  if (myBaseTime == &aOther)
171
0
    return true;
172
0
173
0
  mozilla::AutoRestore<bool> setVisited(mVisited);
174
0
  mVisited = true;
175
0
  return myBaseTime->IsDependentOn(aOther);
176
0
}
177
178
const nsSMILInstanceTime*
179
nsSMILInstanceTime::GetBaseTime() const
180
0
{
181
0
  if (!mBaseInterval) {
182
0
    return nullptr;
183
0
  }
184
0
185
0
  MOZ_ASSERT(mCreator, "Base interval is set but there is no creator.");
186
0
  if (!mCreator) {
187
0
    return nullptr;
188
0
  }
189
0
190
0
  return mCreator->DependsOnBegin() ? mBaseInterval->Begin() :
191
0
                                      mBaseInterval->End();
192
0
}
193
194
void
195
nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval)
196
0
{
197
0
  MOZ_ASSERT(!mBaseInterval,
198
0
             "Attempting to reassociate an instance time with a different "
199
0
             "interval.");
200
0
201
0
  if (aBaseInterval) {
202
0
    MOZ_ASSERT(mCreator,
203
0
               "Attempting to create a dependent instance time without "
204
0
               "reference to the creating nsSMILTimeValueSpec object.");
205
0
    if (!mCreator)
206
0
      return;
207
0
208
0
    aBaseInterval->AddDependentTime(*this);
209
0
  }
210
0
211
0
  mBaseInterval = aBaseInterval;
212
0
}