dom/smil/nsSMILInstanceTime.cpp

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

mercurial