Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / smil / nsSMILInstanceTime.cpp
blob013ae4bd83401cca2cf245fc3fff79163d38f138
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 //----------------------------------------------------------------------
12 // Implementation
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
27 switch (aSource) {
28 case SOURCE_NONE:
29 // No special flags
30 break;
32 case SOURCE_DOM:
33 mFlags = kDynamic | kFromDOM;
34 break;
36 case SOURCE_SYNCBASE:
37 mFlags = kMayUpdate;
38 break;
40 case SOURCE_EVENT:
41 mFlags = kDynamic;
42 break;
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 "
54 "interval");
57 void
58 nsSMILInstanceTime::Unlink()
60 nsRefPtr<nsSMILInstanceTime> deathGrip(this);
61 if (mBaseInterval) {
62 mBaseInterval->RemoveDependentTime(*this);
63 mBaseInterval = nullptr;
65 mCreator = nullptr;
68 void
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.
78 if (!mBaseInterval)
79 return;
81 NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not.");
83 if (mVisited) {
84 // Break the cycle here
85 Unlink();
86 return;
89 bool objectChanged = mCreator->DependsOnBegin() ? aBeginObjectChanged :
90 aEndObjectChanged;
92 mozilla::AutoRestore<bool> setVisited(mVisited);
93 mVisited = true;
95 nsRefPtr<nsSMILInstanceTime> deathGrip(this);
96 mCreator->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer, *this,
97 objectChanged);
100 void
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);
112 mCreator = nullptr;
115 void
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
123 mCreator = nullptr;
126 bool
127 nsSMILInstanceTime::ShouldPreserve() const
129 return mFixedEndpointRefCnt > 0 || (mFlags & kWasDynamicEndpoint);
132 void
133 nsSMILInstanceTime::UnmarkShouldPreserve()
135 mFlags &= ~kWasDynamicEndpoint;
138 void
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
147 void
148 nsSMILInstanceTime::ReleaseFixedEndpoint()
150 NS_ABORT_IF_FALSE(mFixedEndpointRefCnt > 0, "Duplicate release");
151 --mFixedEndpointRefCnt;
152 if (mFixedEndpointRefCnt == 0 && IsDynamic()) {
153 mFlags |= kWasDynamicEndpoint;
157 bool
158 nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime& aOther) const
160 if (mVisited)
161 return false;
163 const nsSMILInstanceTime* myBaseTime = GetBaseTime();
164 if (!myBaseTime)
165 return false;
167 if (myBaseTime == &aOther)
168 return true;
170 mozilla::AutoRestore<bool> setVisited(mVisited);
171 mVisited = true;
172 return myBaseTime->IsDependentOn(aOther);
175 const nsSMILInstanceTime*
176 nsSMILInstanceTime::GetBaseTime() const
178 if (!mBaseInterval) {
179 return nullptr;
182 NS_ABORT_IF_FALSE(mCreator, "Base interval is set but there is no creator.");
183 if (!mCreator) {
184 return nullptr;
187 return mCreator->DependsOnBegin() ? mBaseInterval->Begin() :
188 mBaseInterval->End();
191 void
192 nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval)
194 NS_ABORT_IF_FALSE(!mBaseInterval,
195 "Attempting to reassociate an instance time with a different interval.");
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;
204 aBaseInterval->AddDependentTime(*this);
207 mBaseInterval = aBaseInterval;