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/. */
6 #include "nsSMILInstanceTime.h"
7 #include "nsSMILInterval.h"
8 #include "nsSMILTimeValueSpec.h"
9 #include "mozilla/AutoRestore.h"
11 //----------------------------------------------------------------------
14 nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue
& aTime
,
15 nsSMILInstanceTimeSource aSource
,
16 nsSMILTimeValueSpec
* aCreator
,
17 nsSMILInterval
* aBaseInterval
)
21 mFixedEndpointRefCnt(0),
24 mBaseInterval(nullptr) // This will get set to aBaseInterval in a call to
25 // SetBaseInterval() at end of constructor
33 mFlags
= kDynamic
| kFromDOM
;
45 SetBaseInterval(aBaseInterval
);
48 nsSMILInstanceTime::~nsSMILInstanceTime()
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 "
58 nsSMILInstanceTime::Unlink()
60 nsRefPtr
<nsSMILInstanceTime
> deathGrip(this);
62 mBaseInterval
->RemoveDependentTime(*this);
63 mBaseInterval
= nullptr;
69 nsSMILInstanceTime::HandleChangedInterval(
70 const nsSMILTimeContainer
* aSrcContainer
,
71 bool aBeginObjectChanged
,
72 bool aEndObjectChanged
)
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.
81 NS_ABORT_IF_FALSE(mCreator
, "Base interval is set but creator is not.");
84 // Break the cycle here
89 bool objectChanged
= mCreator
->DependsOnBegin() ? aBeginObjectChanged
:
92 mozilla::AutoRestore
<bool> setVisited(mVisited
);
95 nsRefPtr
<nsSMILInstanceTime
> deathGrip(this);
96 mCreator
->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer
, *this,
101 nsSMILInstanceTime::HandleDeletedInterval()
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");
107 mBaseInterval
= nullptr;
108 mFlags
&= ~kMayUpdate
; // Can't update without a base interval
110 nsRefPtr
<nsSMILInstanceTime
> deathGrip(this);
111 mCreator
->HandleDeletedInstanceTime(*this);
116 nsSMILInstanceTime::HandleFilteredInterval()
118 NS_ABORT_IF_FALSE(mBaseInterval
,
119 "Got call to HandleFilteredInterval on an independent instance time");
121 mBaseInterval
= nullptr;
122 mFlags
&= ~kMayUpdate
; // Can't update without a base interval
127 nsSMILInstanceTime::ShouldPreserve() const
129 return mFixedEndpointRefCnt
> 0 || (mFlags
& kWasDynamicEndpoint
);
133 nsSMILInstanceTime::UnmarkShouldPreserve()
135 mFlags
&= ~kWasDynamicEndpoint
;
139 nsSMILInstanceTime::AddRefFixedEndpoint()
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
148 nsSMILInstanceTime::ReleaseFixedEndpoint()
150 NS_ABORT_IF_FALSE(mFixedEndpointRefCnt
> 0, "Duplicate release");
151 --mFixedEndpointRefCnt
;
152 if (mFixedEndpointRefCnt
== 0 && IsDynamic()) {
153 mFlags
|= kWasDynamicEndpoint
;
158 nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime
& aOther
) const
163 const nsSMILInstanceTime
* myBaseTime
= GetBaseTime();
167 if (myBaseTime
== &aOther
)
170 mozilla::AutoRestore
<bool> setVisited(mVisited
);
172 return myBaseTime
->IsDependentOn(aOther
);
175 const nsSMILInstanceTime
*
176 nsSMILInstanceTime::GetBaseTime() const
178 if (!mBaseInterval
) {
182 NS_ABORT_IF_FALSE(mCreator
, "Base interval is set but there is no creator.");
187 return mCreator
->DependsOnBegin() ? mBaseInterval
->Begin() :
188 mBaseInterval
->End();
192 nsSMILInstanceTime::SetBaseInterval(nsSMILInterval
* aBaseInterval
)
194 NS_ABORT_IF_FALSE(!mBaseInterval
,
195 "Attempting to reassociate an instance time with a different interval.");
198 NS_ABORT_IF_FALSE(mCreator
,
199 "Attempting to create a dependent instance time without reference "
200 "to the creating nsSMILTimeValueSpec object.");
204 aBaseInterval
->AddDependentTime(*this);
207 mBaseInterval
= aBaseInterval
;