1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/smil/nsSMILInstanceTime.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,208 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsSMILInstanceTime.h" 1.10 +#include "nsSMILInterval.h" 1.11 +#include "nsSMILTimeValueSpec.h" 1.12 +#include "mozilla/AutoRestore.h" 1.13 + 1.14 +//---------------------------------------------------------------------- 1.15 +// Implementation 1.16 + 1.17 +nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime, 1.18 + nsSMILInstanceTimeSource aSource, 1.19 + nsSMILTimeValueSpec* aCreator, 1.20 + nsSMILInterval* aBaseInterval) 1.21 + : mTime(aTime), 1.22 + mFlags(0), 1.23 + mVisited(false), 1.24 + mFixedEndpointRefCnt(0), 1.25 + mSerial(0), 1.26 + mCreator(aCreator), 1.27 + mBaseInterval(nullptr) // This will get set to aBaseInterval in a call to 1.28 + // SetBaseInterval() at end of constructor 1.29 +{ 1.30 + switch (aSource) { 1.31 + case SOURCE_NONE: 1.32 + // No special flags 1.33 + break; 1.34 + 1.35 + case SOURCE_DOM: 1.36 + mFlags = kDynamic | kFromDOM; 1.37 + break; 1.38 + 1.39 + case SOURCE_SYNCBASE: 1.40 + mFlags = kMayUpdate; 1.41 + break; 1.42 + 1.43 + case SOURCE_EVENT: 1.44 + mFlags = kDynamic; 1.45 + break; 1.46 + } 1.47 + 1.48 + SetBaseInterval(aBaseInterval); 1.49 +} 1.50 + 1.51 +nsSMILInstanceTime::~nsSMILInstanceTime() 1.52 +{ 1.53 + NS_ABORT_IF_FALSE(!mBaseInterval, 1.54 + "Destroying instance time without first calling Unlink()"); 1.55 + NS_ABORT_IF_FALSE(mFixedEndpointRefCnt == 0, 1.56 + "Destroying instance time that is still used as the fixed endpoint of an " 1.57 + "interval"); 1.58 +} 1.59 + 1.60 +void 1.61 +nsSMILInstanceTime::Unlink() 1.62 +{ 1.63 + nsRefPtr<nsSMILInstanceTime> deathGrip(this); 1.64 + if (mBaseInterval) { 1.65 + mBaseInterval->RemoveDependentTime(*this); 1.66 + mBaseInterval = nullptr; 1.67 + } 1.68 + mCreator = nullptr; 1.69 +} 1.70 + 1.71 +void 1.72 +nsSMILInstanceTime::HandleChangedInterval( 1.73 + const nsSMILTimeContainer* aSrcContainer, 1.74 + bool aBeginObjectChanged, 1.75 + bool aEndObjectChanged) 1.76 +{ 1.77 + // It's possible a sequence of notifications might cause our base interval to 1.78 + // be updated and then deleted. Furthermore, the delete might happen whilst 1.79 + // we're still in the queue to be notified of the change. In any case, if we 1.80 + // don't have a base interval, just ignore the change. 1.81 + if (!mBaseInterval) 1.82 + return; 1.83 + 1.84 + NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not."); 1.85 + 1.86 + if (mVisited) { 1.87 + // Break the cycle here 1.88 + Unlink(); 1.89 + return; 1.90 + } 1.91 + 1.92 + bool objectChanged = mCreator->DependsOnBegin() ? aBeginObjectChanged : 1.93 + aEndObjectChanged; 1.94 + 1.95 + mozilla::AutoRestore<bool> setVisited(mVisited); 1.96 + mVisited = true; 1.97 + 1.98 + nsRefPtr<nsSMILInstanceTime> deathGrip(this); 1.99 + mCreator->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer, *this, 1.100 + objectChanged); 1.101 +} 1.102 + 1.103 +void 1.104 +nsSMILInstanceTime::HandleDeletedInterval() 1.105 +{ 1.106 + NS_ABORT_IF_FALSE(mBaseInterval, 1.107 + "Got call to HandleDeletedInterval on an independent instance time"); 1.108 + NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not"); 1.109 + 1.110 + mBaseInterval = nullptr; 1.111 + mFlags &= ~kMayUpdate; // Can't update without a base interval 1.112 + 1.113 + nsRefPtr<nsSMILInstanceTime> deathGrip(this); 1.114 + mCreator->HandleDeletedInstanceTime(*this); 1.115 + mCreator = nullptr; 1.116 +} 1.117 + 1.118 +void 1.119 +nsSMILInstanceTime::HandleFilteredInterval() 1.120 +{ 1.121 + NS_ABORT_IF_FALSE(mBaseInterval, 1.122 + "Got call to HandleFilteredInterval on an independent instance time"); 1.123 + 1.124 + mBaseInterval = nullptr; 1.125 + mFlags &= ~kMayUpdate; // Can't update without a base interval 1.126 + mCreator = nullptr; 1.127 +} 1.128 + 1.129 +bool 1.130 +nsSMILInstanceTime::ShouldPreserve() const 1.131 +{ 1.132 + return mFixedEndpointRefCnt > 0 || (mFlags & kWasDynamicEndpoint); 1.133 +} 1.134 + 1.135 +void 1.136 +nsSMILInstanceTime::UnmarkShouldPreserve() 1.137 +{ 1.138 + mFlags &= ~kWasDynamicEndpoint; 1.139 +} 1.140 + 1.141 +void 1.142 +nsSMILInstanceTime::AddRefFixedEndpoint() 1.143 +{ 1.144 + NS_ABORT_IF_FALSE(mFixedEndpointRefCnt < UINT16_MAX, 1.145 + "Fixed endpoint reference count upper limit reached"); 1.146 + ++mFixedEndpointRefCnt; 1.147 + mFlags &= ~kMayUpdate; // Once fixed, always fixed 1.148 +} 1.149 + 1.150 +void 1.151 +nsSMILInstanceTime::ReleaseFixedEndpoint() 1.152 +{ 1.153 + NS_ABORT_IF_FALSE(mFixedEndpointRefCnt > 0, "Duplicate release"); 1.154 + --mFixedEndpointRefCnt; 1.155 + if (mFixedEndpointRefCnt == 0 && IsDynamic()) { 1.156 + mFlags |= kWasDynamicEndpoint; 1.157 + } 1.158 +} 1.159 + 1.160 +bool 1.161 +nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime& aOther) const 1.162 +{ 1.163 + if (mVisited) 1.164 + return false; 1.165 + 1.166 + const nsSMILInstanceTime* myBaseTime = GetBaseTime(); 1.167 + if (!myBaseTime) 1.168 + return false; 1.169 + 1.170 + if (myBaseTime == &aOther) 1.171 + return true; 1.172 + 1.173 + mozilla::AutoRestore<bool> setVisited(mVisited); 1.174 + mVisited = true; 1.175 + return myBaseTime->IsDependentOn(aOther); 1.176 +} 1.177 + 1.178 +const nsSMILInstanceTime* 1.179 +nsSMILInstanceTime::GetBaseTime() const 1.180 +{ 1.181 + if (!mBaseInterval) { 1.182 + return nullptr; 1.183 + } 1.184 + 1.185 + NS_ABORT_IF_FALSE(mCreator, "Base interval is set but there is no creator."); 1.186 + if (!mCreator) { 1.187 + return nullptr; 1.188 + } 1.189 + 1.190 + return mCreator->DependsOnBegin() ? mBaseInterval->Begin() : 1.191 + mBaseInterval->End(); 1.192 +} 1.193 + 1.194 +void 1.195 +nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval) 1.196 +{ 1.197 + NS_ABORT_IF_FALSE(!mBaseInterval, 1.198 + "Attempting to reassociate an instance time with a different interval."); 1.199 + 1.200 + if (aBaseInterval) { 1.201 + NS_ABORT_IF_FALSE(mCreator, 1.202 + "Attempting to create a dependent instance time without reference " 1.203 + "to the creating nsSMILTimeValueSpec object."); 1.204 + if (!mCreator) 1.205 + return; 1.206 + 1.207 + aBaseInterval->AddDependentTime(*this); 1.208 + } 1.209 + 1.210 + mBaseInterval = aBaseInterval; 1.211 +}