bool nsSMILTimeValueSpec::ApplyOffset(nsSMILTimeValue& aTime) const { // indefinite + offset = indefinite. Likewise for unresolved times. if (!aTime.IsDefinite()) { return true; } double resultAsDouble = (double)aTime.GetMillis() + mParams.mOffset.GetMillis(); if (resultAsDouble > std::numeric_limits<nsSMILTime>::max() || resultAsDouble < std::numeric_limits<nsSMILTime>::min()) { return false; } aTime.SetMillis(aTime.GetMillis() + mParams.mOffset.GetMillis()); return true; }
// // This method is based on the pseudocode given in the SMILANIM spec. // // See: // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start // nsresult nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval, nsSMILInterval& aResult) { static nsSMILTimeValue zeroTime; zeroTime.SetMillis(0L); if (mRestartMode == RESTART_NEVER && aPrevInterval) return NS_ERROR_FAILURE; // Calc starting point nsSMILTimeValue beginAfter; PRBool prevIntervalWasZeroDur = PR_FALSE; if (aPrevInterval) { beginAfter = aPrevInterval->mEnd; prevIntervalWasZeroDur = (aPrevInterval->mEnd.CompareTo(aPrevInterval->mBegin) == 0); } else { beginAfter.SetMillis(LL_MININT); } nsSMILTimeValue tempBegin; nsSMILTimeValue tempEnd; nsSMILInstanceTime::Comparator comparator; mBeginInstances.Sort(comparator); mEndInstances.Sort(comparator); while (PR_TRUE) { if (!mBeginSpecSet && beginAfter.CompareTo(zeroTime) <= 0) { tempBegin.SetMillis(0); } else { PRInt32 beginPos = 0; PRBool beginFound = GetNextGreaterOrEqual(mBeginInstances, beginAfter, beginPos, tempBegin); if (!beginFound) return NS_ERROR_FAILURE; } if (mEndInstances.Length() == 0) { nsSMILTimeValue indefiniteEnd; indefiniteEnd.SetIndefinite(); tempEnd = CalcActiveEnd(tempBegin, indefiniteEnd); } else { PRInt32 endPos = 0; PRBool endFound = GetNextGreaterOrEqual(mEndInstances, tempBegin, endPos, tempEnd); // If the last interval ended at the same point and was zero-duration and // this one is too, look for another end to use instead if (tempEnd.CompareTo(tempBegin) == 0 && prevIntervalWasZeroDur) { endFound = GetNextGreater(mEndInstances, tempBegin, endPos, tempEnd); } if (!endFound) { if (mEndHasEventConditions || mEndInstances.Length() == 0) { tempEnd.SetUnresolved(); } else { // // This is a little counter-intuitive but according to SMILANIM, if // all the ends are before the begin, we _don't_ just assume an // infinite end, it's actually a bad interval. ASV however will just // use an infinite end. // return NS_ERROR_FAILURE; } } tempEnd = CalcActiveEnd(tempBegin, tempEnd); } // If we get two zero-length intervals in a row we will potentially have an // infinite loop so we break it here by searching for the next begin time // greater than tempEnd on the next time around. if (tempEnd.IsResolved() && tempBegin.CompareTo(tempEnd) == 0) { if (prevIntervalWasZeroDur) { beginAfter.SetMillis(tempEnd.GetMillis()+1); prevIntervalWasZeroDur = PR_FALSE; continue; } prevIntervalWasZeroDur = PR_TRUE; } if (tempEnd.CompareTo(zeroTime) > 0 || (tempBegin.CompareTo(zeroTime) == 0 && tempEnd.CompareTo(zeroTime) == 0)) { aResult.mBegin = tempBegin; aResult.mEnd = tempEnd; return NS_OK; } else if (mRestartMode == RESTART_NEVER) { // tempEnd <= 0 so we're going to loop which effectively means restarting return NS_ERROR_FAILURE; } else { beginAfter = tempEnd; } } NS_NOTREACHED("Hmm... we really shouldn't be here"); return NS_ERROR_FAILURE; }