summaryrefslogtreecommitdiffstats
path: root/dom/smil/nsSMILInterval.cpp
blob: b2476ff7c6caed17c7edd77aada4a4fde8a7751a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsSMILInterval.h"

nsSMILInterval::nsSMILInterval()
:
  mBeginFixed(false),
  mEndFixed(false)
{
}

nsSMILInterval::nsSMILInterval(const nsSMILInterval& aOther)
:
  mBegin(aOther.mBegin),
  mEnd(aOther.mEnd),
  mBeginFixed(false),
  mEndFixed(false)
{
  MOZ_ASSERT(aOther.mDependentTimes.IsEmpty(),
             "Attempt to copy-construct an interval with dependent times; this "
             "will lead to instance times being shared between intervals.");

  // For the time being we don't allow intervals with fixed endpoints to be
  // copied since we only ever copy-construct to establish a new current
  // interval. If we ever need to copy historical intervals we may need to move
  // the ReleaseFixedEndpoint calls from Unlink to the dtor.
  MOZ_ASSERT(!aOther.mBeginFixed && !aOther.mEndFixed,
             "Attempt to copy-construct an interval with fixed endpoints");
}

nsSMILInterval::~nsSMILInterval()
{
  MOZ_ASSERT(mDependentTimes.IsEmpty(),
             "Destroying interval without disassociating dependent instance "
             "times. Unlink was not called");
}

void
nsSMILInterval::Unlink(bool aFiltered)
{
  for (int32_t i = mDependentTimes.Length() - 1; i >= 0; --i) {
    if (aFiltered) {
      mDependentTimes[i]->HandleFilteredInterval();
    } else {
      mDependentTimes[i]->HandleDeletedInterval();
    }
  }
  mDependentTimes.Clear();
  if (mBegin && mBeginFixed) {
    mBegin->ReleaseFixedEndpoint();
  }
  mBegin = nullptr;
  if (mEnd && mEndFixed) {
    mEnd->ReleaseFixedEndpoint();
  }
  mEnd = nullptr;
}

nsSMILInstanceTime*
nsSMILInterval::Begin()
{
  MOZ_ASSERT(mBegin && mEnd,
             "Requesting Begin() on un-initialized interval.");
  return mBegin;
}

nsSMILInstanceTime*
nsSMILInterval::End()
{
  MOZ_ASSERT(mBegin && mEnd,
             "Requesting End() on un-initialized interval.");
  return mEnd;
}

void
nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
{
  MOZ_ASSERT(aBegin.Time().IsDefinite(),
             "Attempt to set unresolved or indefinite begin time on interval");
  MOZ_ASSERT(!mBeginFixed,
             "Attempt to set begin time but the begin point is fixed");
  // Check that we're not making an instance time dependent on itself. Such an
  // arrangement does not make intuitive sense and should be detected when
  // creating or updating intervals.
  MOZ_ASSERT(!mBegin || aBegin.GetBaseTime() != mBegin,
             "Attempt to make self-dependent instance time");

  mBegin = &aBegin;
}

void
nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd)
{
  MOZ_ASSERT(!mEndFixed,
             "Attempt to set end time but the end point is fixed");
  // As with SetBegin, check we're not making an instance time dependent on
  // itself.
  MOZ_ASSERT(!mEnd || aEnd.GetBaseTime() != mEnd,
             "Attempting to make self-dependent instance time");

  mEnd = &aEnd;
}

void
nsSMILInterval::FixBegin()
{
  MOZ_ASSERT(mBegin && mEnd,
             "Fixing begin point on un-initialized interval");
  MOZ_ASSERT(!mBeginFixed, "Duplicate calls to FixBegin()");
  mBeginFixed = true;
  mBegin->AddRefFixedEndpoint();
}

void
nsSMILInterval::FixEnd()
{
  MOZ_ASSERT(mBegin && mEnd,
             "Fixing end point on un-initialized interval");
  MOZ_ASSERT(mBeginFixed,
             "Fixing the end of an interval without a fixed begin");
  MOZ_ASSERT(!mEndFixed, "Duplicate calls to FixEnd()");
  mEndFixed = true;
  mEnd->AddRefFixedEndpoint();
}

void
nsSMILInterval::AddDependentTime(nsSMILInstanceTime& aTime)
{
  RefPtr<nsSMILInstanceTime>* inserted =
    mDependentTimes.InsertElementSorted(&aTime);
  if (!inserted) {
    NS_WARNING("Insufficient memory to insert instance time.");
  }
}

void
nsSMILInterval::RemoveDependentTime(const nsSMILInstanceTime& aTime)
{
#ifdef DEBUG
  bool found =
#endif
    mDependentTimes.RemoveElementSorted(&aTime);
  MOZ_ASSERT(found, "Couldn't find instance time to delete.");
}

void
nsSMILInterval::GetDependentTimes(InstanceTimeList& aTimes)
{
  aTimes = mDependentTimes;
}

bool
nsSMILInterval::IsDependencyChainLink() const
{
  if (!mBegin || !mEnd)
    return false; // Not yet initialised so it can't be part of a chain

  if (mDependentTimes.IsEmpty())
    return false; // No dependents, chain end

  // So we have dependents, but we're still only a link in the chain (as opposed
  // to the end of the chain) if one of our endpoints is dependent on an
  // interval other than ourselves.
  return (mBegin->IsDependent() && mBegin->GetBaseInterval() != this) ||
         (mEnd->IsDependent() && mEnd->GetBaseInterval() != this);
}