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