|
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 "nsSMILInterval.h" |
|
7 |
|
8 nsSMILInterval::nsSMILInterval() |
|
9 : |
|
10 mBeginFixed(false), |
|
11 mEndFixed(false) |
|
12 { |
|
13 } |
|
14 |
|
15 nsSMILInterval::nsSMILInterval(const nsSMILInterval& aOther) |
|
16 : |
|
17 mBegin(aOther.mBegin), |
|
18 mEnd(aOther.mEnd), |
|
19 mBeginFixed(false), |
|
20 mEndFixed(false) |
|
21 { |
|
22 NS_ABORT_IF_FALSE(aOther.mDependentTimes.IsEmpty(), |
|
23 "Attempting to copy-construct an interval with dependent times, " |
|
24 "this will lead to instance times being shared between intervals."); |
|
25 |
|
26 // For the time being we don't allow intervals with fixed endpoints to be |
|
27 // copied since we only ever copy-construct to establish a new current |
|
28 // interval. If we ever need to copy historical intervals we may need to move |
|
29 // the ReleaseFixedEndpoint calls from Unlink to the dtor. |
|
30 NS_ABORT_IF_FALSE(!aOther.mBeginFixed && !aOther.mEndFixed, |
|
31 "Attempting to copy-construct an interval with fixed endpoints"); |
|
32 } |
|
33 |
|
34 nsSMILInterval::~nsSMILInterval() |
|
35 { |
|
36 NS_ABORT_IF_FALSE(mDependentTimes.IsEmpty(), |
|
37 "Destroying interval without disassociating dependent instance times. " |
|
38 "Unlink was not called"); |
|
39 } |
|
40 |
|
41 void |
|
42 nsSMILInterval::Unlink(bool aFiltered) |
|
43 { |
|
44 for (int32_t i = mDependentTimes.Length() - 1; i >= 0; --i) { |
|
45 if (aFiltered) { |
|
46 mDependentTimes[i]->HandleFilteredInterval(); |
|
47 } else { |
|
48 mDependentTimes[i]->HandleDeletedInterval(); |
|
49 } |
|
50 } |
|
51 mDependentTimes.Clear(); |
|
52 if (mBegin && mBeginFixed) { |
|
53 mBegin->ReleaseFixedEndpoint(); |
|
54 } |
|
55 mBegin = nullptr; |
|
56 if (mEnd && mEndFixed) { |
|
57 mEnd->ReleaseFixedEndpoint(); |
|
58 } |
|
59 mEnd = nullptr; |
|
60 } |
|
61 |
|
62 nsSMILInstanceTime* |
|
63 nsSMILInterval::Begin() |
|
64 { |
|
65 NS_ABORT_IF_FALSE(mBegin && mEnd, |
|
66 "Requesting Begin() on un-initialized interval."); |
|
67 return mBegin; |
|
68 } |
|
69 |
|
70 nsSMILInstanceTime* |
|
71 nsSMILInterval::End() |
|
72 { |
|
73 NS_ABORT_IF_FALSE(mBegin && mEnd, |
|
74 "Requesting End() on un-initialized interval."); |
|
75 return mEnd; |
|
76 } |
|
77 |
|
78 void |
|
79 nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin) |
|
80 { |
|
81 NS_ABORT_IF_FALSE(aBegin.Time().IsDefinite(), |
|
82 "Attempting to set unresolved or indefinite begin time on interval"); |
|
83 NS_ABORT_IF_FALSE(!mBeginFixed, |
|
84 "Attempting to set begin time but the begin point is fixed"); |
|
85 // Check that we're not making an instance time dependent on itself. Such an |
|
86 // arrangement does not make intuitive sense and should be detected when |
|
87 // creating or updating intervals. |
|
88 NS_ABORT_IF_FALSE(!mBegin || aBegin.GetBaseTime() != mBegin, |
|
89 "Attempting to make self-dependent instance time"); |
|
90 |
|
91 mBegin = &aBegin; |
|
92 } |
|
93 |
|
94 void |
|
95 nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd) |
|
96 { |
|
97 NS_ABORT_IF_FALSE(!mEndFixed, |
|
98 "Attempting to set end time but the end point is fixed"); |
|
99 // As with SetBegin, check we're not making an instance time dependent on |
|
100 // itself. |
|
101 NS_ABORT_IF_FALSE(!mEnd || aEnd.GetBaseTime() != mEnd, |
|
102 "Attempting to make self-dependent instance time"); |
|
103 |
|
104 mEnd = &aEnd; |
|
105 } |
|
106 |
|
107 void |
|
108 nsSMILInterval::FixBegin() |
|
109 { |
|
110 NS_ABORT_IF_FALSE(mBegin && mEnd, |
|
111 "Fixing begin point on un-initialized interval"); |
|
112 NS_ABORT_IF_FALSE(!mBeginFixed, "Duplicate calls to FixBegin()"); |
|
113 mBeginFixed = true; |
|
114 mBegin->AddRefFixedEndpoint(); |
|
115 } |
|
116 |
|
117 void |
|
118 nsSMILInterval::FixEnd() |
|
119 { |
|
120 NS_ABORT_IF_FALSE(mBegin && mEnd, |
|
121 "Fixing end point on un-initialized interval"); |
|
122 NS_ABORT_IF_FALSE(mBeginFixed, |
|
123 "Fixing the end of an interval without a fixed begin"); |
|
124 NS_ABORT_IF_FALSE(!mEndFixed, "Duplicate calls to FixEnd()"); |
|
125 mEndFixed = true; |
|
126 mEnd->AddRefFixedEndpoint(); |
|
127 } |
|
128 |
|
129 void |
|
130 nsSMILInterval::AddDependentTime(nsSMILInstanceTime& aTime) |
|
131 { |
|
132 nsRefPtr<nsSMILInstanceTime>* inserted = |
|
133 mDependentTimes.InsertElementSorted(&aTime); |
|
134 if (!inserted) { |
|
135 NS_WARNING("Insufficient memory to insert instance time."); |
|
136 } |
|
137 } |
|
138 |
|
139 void |
|
140 nsSMILInterval::RemoveDependentTime(const nsSMILInstanceTime& aTime) |
|
141 { |
|
142 #ifdef DEBUG |
|
143 bool found = |
|
144 #endif |
|
145 mDependentTimes.RemoveElementSorted(&aTime); |
|
146 NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete."); |
|
147 } |
|
148 |
|
149 void |
|
150 nsSMILInterval::GetDependentTimes(InstanceTimeList& aTimes) |
|
151 { |
|
152 aTimes = mDependentTimes; |
|
153 } |
|
154 |
|
155 bool |
|
156 nsSMILInterval::IsDependencyChainLink() const |
|
157 { |
|
158 if (!mBegin || !mEnd) |
|
159 return false; // Not yet initialised so it can't be part of a chain |
|
160 |
|
161 if (mDependentTimes.IsEmpty()) |
|
162 return false; // No dependents, chain end |
|
163 |
|
164 // So we have dependents, but we're still only a link in the chain (as opposed |
|
165 // to the end of the chain) if one of our endpoints is dependent on an |
|
166 // interval other than ourselves. |
|
167 return (mBegin->IsDependent() && mBegin->GetBaseInterval() != this) || |
|
168 (mEnd->IsDependent() && mEnd->GetBaseInterval() != this); |
|
169 } |