michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsSMILInterval.h" michael@0: michael@0: nsSMILInterval::nsSMILInterval() michael@0: : michael@0: mBeginFixed(false), michael@0: mEndFixed(false) michael@0: { michael@0: } michael@0: michael@0: nsSMILInterval::nsSMILInterval(const nsSMILInterval& aOther) michael@0: : michael@0: mBegin(aOther.mBegin), michael@0: mEnd(aOther.mEnd), michael@0: mBeginFixed(false), michael@0: mEndFixed(false) michael@0: { michael@0: NS_ABORT_IF_FALSE(aOther.mDependentTimes.IsEmpty(), michael@0: "Attempting to copy-construct an interval with dependent times, " michael@0: "this will lead to instance times being shared between intervals."); michael@0: michael@0: // For the time being we don't allow intervals with fixed endpoints to be michael@0: // copied since we only ever copy-construct to establish a new current michael@0: // interval. If we ever need to copy historical intervals we may need to move michael@0: // the ReleaseFixedEndpoint calls from Unlink to the dtor. michael@0: NS_ABORT_IF_FALSE(!aOther.mBeginFixed && !aOther.mEndFixed, michael@0: "Attempting to copy-construct an interval with fixed endpoints"); michael@0: } michael@0: michael@0: nsSMILInterval::~nsSMILInterval() michael@0: { michael@0: NS_ABORT_IF_FALSE(mDependentTimes.IsEmpty(), michael@0: "Destroying interval without disassociating dependent instance times. " michael@0: "Unlink was not called"); michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::Unlink(bool aFiltered) michael@0: { michael@0: for (int32_t i = mDependentTimes.Length() - 1; i >= 0; --i) { michael@0: if (aFiltered) { michael@0: mDependentTimes[i]->HandleFilteredInterval(); michael@0: } else { michael@0: mDependentTimes[i]->HandleDeletedInterval(); michael@0: } michael@0: } michael@0: mDependentTimes.Clear(); michael@0: if (mBegin && mBeginFixed) { michael@0: mBegin->ReleaseFixedEndpoint(); michael@0: } michael@0: mBegin = nullptr; michael@0: if (mEnd && mEndFixed) { michael@0: mEnd->ReleaseFixedEndpoint(); michael@0: } michael@0: mEnd = nullptr; michael@0: } michael@0: michael@0: nsSMILInstanceTime* michael@0: nsSMILInterval::Begin() michael@0: { michael@0: NS_ABORT_IF_FALSE(mBegin && mEnd, michael@0: "Requesting Begin() on un-initialized interval."); michael@0: return mBegin; michael@0: } michael@0: michael@0: nsSMILInstanceTime* michael@0: nsSMILInterval::End() michael@0: { michael@0: NS_ABORT_IF_FALSE(mBegin && mEnd, michael@0: "Requesting End() on un-initialized interval."); michael@0: return mEnd; michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin) michael@0: { michael@0: NS_ABORT_IF_FALSE(aBegin.Time().IsDefinite(), michael@0: "Attempting to set unresolved or indefinite begin time on interval"); michael@0: NS_ABORT_IF_FALSE(!mBeginFixed, michael@0: "Attempting to set begin time but the begin point is fixed"); michael@0: // Check that we're not making an instance time dependent on itself. Such an michael@0: // arrangement does not make intuitive sense and should be detected when michael@0: // creating or updating intervals. michael@0: NS_ABORT_IF_FALSE(!mBegin || aBegin.GetBaseTime() != mBegin, michael@0: "Attempting to make self-dependent instance time"); michael@0: michael@0: mBegin = &aBegin; michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd) michael@0: { michael@0: NS_ABORT_IF_FALSE(!mEndFixed, michael@0: "Attempting to set end time but the end point is fixed"); michael@0: // As with SetBegin, check we're not making an instance time dependent on michael@0: // itself. michael@0: NS_ABORT_IF_FALSE(!mEnd || aEnd.GetBaseTime() != mEnd, michael@0: "Attempting to make self-dependent instance time"); michael@0: michael@0: mEnd = &aEnd; michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::FixBegin() michael@0: { michael@0: NS_ABORT_IF_FALSE(mBegin && mEnd, michael@0: "Fixing begin point on un-initialized interval"); michael@0: NS_ABORT_IF_FALSE(!mBeginFixed, "Duplicate calls to FixBegin()"); michael@0: mBeginFixed = true; michael@0: mBegin->AddRefFixedEndpoint(); michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::FixEnd() michael@0: { michael@0: NS_ABORT_IF_FALSE(mBegin && mEnd, michael@0: "Fixing end point on un-initialized interval"); michael@0: NS_ABORT_IF_FALSE(mBeginFixed, michael@0: "Fixing the end of an interval without a fixed begin"); michael@0: NS_ABORT_IF_FALSE(!mEndFixed, "Duplicate calls to FixEnd()"); michael@0: mEndFixed = true; michael@0: mEnd->AddRefFixedEndpoint(); michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::AddDependentTime(nsSMILInstanceTime& aTime) michael@0: { michael@0: nsRefPtr* inserted = michael@0: mDependentTimes.InsertElementSorted(&aTime); michael@0: if (!inserted) { michael@0: NS_WARNING("Insufficient memory to insert instance time."); michael@0: } michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::RemoveDependentTime(const nsSMILInstanceTime& aTime) michael@0: { michael@0: #ifdef DEBUG michael@0: bool found = michael@0: #endif michael@0: mDependentTimes.RemoveElementSorted(&aTime); michael@0: NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete."); michael@0: } michael@0: michael@0: void michael@0: nsSMILInterval::GetDependentTimes(InstanceTimeList& aTimes) michael@0: { michael@0: aTimes = mDependentTimes; michael@0: } michael@0: michael@0: bool michael@0: nsSMILInterval::IsDependencyChainLink() const michael@0: { michael@0: if (!mBegin || !mEnd) michael@0: return false; // Not yet initialised so it can't be part of a chain michael@0: michael@0: if (mDependentTimes.IsEmpty()) michael@0: return false; // No dependents, chain end michael@0: michael@0: // So we have dependents, but we're still only a link in the chain (as opposed michael@0: // to the end of the chain) if one of our endpoints is dependent on an michael@0: // interval other than ourselves. michael@0: return (mBegin->IsDependent() && mBegin->GetBaseInterval() != this) || michael@0: (mEnd->IsDependent() && mEnd->GetBaseInterval() != this); michael@0: }