mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 474739. Handle zero-duration intervals properly in SMIL. r=roc
--HG-- extra : rebase_source : 8ad07bedbb6b808dd36ce8949dcb186ba1fd7ca1
This commit is contained in:
parent
1e621e52ea
commit
43ff7295f1
@ -234,11 +234,8 @@ nsSMILTimedElement::SampleAt(nsSMILTime aDocumentTime)
|
||||
{
|
||||
case STATE_STARTUP:
|
||||
{
|
||||
nsSMILTimeValue beginAfter;
|
||||
beginAfter.SetMillis(LL_MININT);
|
||||
|
||||
mElementState =
|
||||
(NS_SUCCEEDED(GetNextInterval(beginAfter, PR_TRUE, mCurrentInterval)))
|
||||
(NS_SUCCEEDED(GetNextInterval(nsnull, mCurrentInterval)))
|
||||
? STATE_WAITING
|
||||
: STATE_POSTACTIVE;
|
||||
stateChanged = PR_TRUE;
|
||||
@ -263,9 +260,7 @@ nsSMILTimedElement::SampleAt(nsSMILTime aDocumentTime)
|
||||
if (mCurrentInterval.mEnd.CompareTo(docTime) <= 0) {
|
||||
nsSMILInterval newInterval;
|
||||
mElementState =
|
||||
(NS_SUCCEEDED(GetNextInterval(mCurrentInterval.mEnd,
|
||||
PR_FALSE,
|
||||
newInterval)))
|
||||
(NS_SUCCEEDED(GetNextInterval(&mCurrentInterval, newInterval)))
|
||||
? STATE_WAITING
|
||||
: STATE_POSTACTIVE;
|
||||
if (mClient) {
|
||||
@ -706,30 +701,28 @@ nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
|
||||
// http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start
|
||||
//
|
||||
nsresult
|
||||
nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
PRBool aFirstInterval,
|
||||
nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
nsSMILInterval& aResult)
|
||||
{
|
||||
static nsSMILTimeValue zeroTime;
|
||||
zeroTime.SetMillis(0L);
|
||||
|
||||
nsSMILTimeValue beginAfter = aBeginAfter;
|
||||
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;
|
||||
PRInt32 beginPos = 0;
|
||||
PRInt32 endPos = 0;
|
||||
|
||||
//
|
||||
// This is to handle the special case when a we are calculating the first
|
||||
// interval and we have a non-0-duration interval immediately after
|
||||
// a 0-duration in which case but we have to be careful not to re-use an end
|
||||
// that has already been used in another interval. See the pseudocode in
|
||||
// SMILANIM 3.6.8 for getFirstInterval.
|
||||
//
|
||||
PRInt32 endMaxPos = 0;
|
||||
|
||||
if (mRestartMode == RESTART_NEVER && !aFirstInterval)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsSMILInstanceTime::Comparator comparator;
|
||||
mBeginInstances.Sort(comparator);
|
||||
@ -739,6 +732,7 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
if (!mBeginSpecSet && beginAfter.CompareTo(zeroTime) <= 0) {
|
||||
tempBegin.SetMillis(0);
|
||||
} else {
|
||||
PRInt32 beginPos = 0;
|
||||
PRBool beginFound = GetNextGreaterOrEqual(mBeginInstances, beginAfter,
|
||||
beginPos, tempBegin);
|
||||
if (!beginFound)
|
||||
@ -751,23 +745,16 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
|
||||
tempEnd = CalcActiveEnd(tempBegin, indefiniteEnd);
|
||||
} else {
|
||||
//
|
||||
// Start searching from the beginning again.
|
||||
//
|
||||
endPos = 0;
|
||||
|
||||
PRInt32 endPos = 0;
|
||||
PRBool endFound = GetNextGreaterOrEqual(mEndInstances, tempBegin,
|
||||
endPos, tempEnd);
|
||||
|
||||
if ((!aFirstInterval && tempEnd.CompareTo(aBeginAfter) == 0) ||
|
||||
(aFirstInterval && tempEnd.CompareTo(tempBegin) == 0 &&
|
||||
endPos <= endMaxPos)) {
|
||||
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);
|
||||
}
|
||||
|
||||
endMaxPos = endPos;
|
||||
|
||||
if (!endFound) {
|
||||
if (mEndHasEventConditions || mEndInstances.Length() == 0) {
|
||||
tempEnd.SetUnresolved();
|
||||
@ -785,11 +772,25 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
tempEnd = CalcActiveEnd(tempBegin, tempEnd);
|
||||
}
|
||||
|
||||
if (tempEnd.CompareTo(zeroTime) > 0) {
|
||||
// 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;
|
||||
@ -800,6 +801,19 @@ nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILTimedElement::GetNextGreater(
|
||||
const nsTArray<nsSMILInstanceTime>& aList,
|
||||
const nsSMILTimeValue& aBase,
|
||||
PRInt32 &aPosition,
|
||||
nsSMILTimeValue& aResult)
|
||||
{
|
||||
PRBool found;
|
||||
while ((found = GetNextGreaterOrEqual(aList, aBase, aPosition, aResult))
|
||||
&& aResult.CompareTo(aBase) == 0);
|
||||
return found;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSMILTimedElement::GetNextGreaterOrEqual(
|
||||
const nsTArray<nsSMILInstanceTime>& aList,
|
||||
@ -957,9 +971,7 @@ nsSMILTimedElement::CheckForEarlyEnd(const nsSMILTimeValue& aDocumentTime)
|
||||
nsSMILTimeValue nextBegin;
|
||||
PRInt32 position = 0;
|
||||
|
||||
while (GetNextGreaterOrEqual(mBeginInstances, mCurrentInterval.mBegin,
|
||||
position, nextBegin)
|
||||
&& nextBegin.CompareTo(mCurrentInterval.mBegin) == 0);
|
||||
GetNextGreater(mBeginInstances, mCurrentInterval.mBegin, position, nextBegin);
|
||||
|
||||
if (nextBegin.IsResolved() &&
|
||||
nextBegin.CompareTo(mCurrentInterval.mBegin) > 0 &&
|
||||
@ -973,16 +985,10 @@ void
|
||||
nsSMILTimedElement::UpdateCurrentInterval()
|
||||
{
|
||||
nsSMILInterval updatedInterval;
|
||||
PRBool isFirstInterval = mOldIntervals.IsEmpty();
|
||||
|
||||
nsSMILTimeValue beginAfter;
|
||||
if (!isFirstInterval) {
|
||||
beginAfter = mOldIntervals[mOldIntervals.Length() - 1].mEnd;
|
||||
} else {
|
||||
beginAfter.SetMillis(LL_MININT);
|
||||
}
|
||||
|
||||
nsresult rv = GetNextInterval(beginAfter, isFirstInterval, updatedInterval);
|
||||
nsSMILInterval* prevInterval = mOldIntervals.IsEmpty()
|
||||
? nsnull
|
||||
: &mOldIntervals[mOldIntervals.Length() - 1];
|
||||
nsresult rv = GetNextInterval(prevInterval, updatedInterval);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
||||
@ -1049,7 +1055,7 @@ nsSMILTimedElement::SampleFillValue()
|
||||
nsSMILTime simpleTime =
|
||||
ActiveTimeToSimpleTime(activeTime, repeatIteration);
|
||||
|
||||
if (simpleTime == 0L) {
|
||||
if (simpleTime == 0L && repeatIteration) {
|
||||
mClient->SampleLastValue(--repeatIteration);
|
||||
} else {
|
||||
mClient->SampleAt(simpleTime, mSimpleDur, repeatIteration);
|
||||
|
@ -251,9 +251,12 @@ protected:
|
||||
*
|
||||
* @see SMILANIM 3.6.8
|
||||
*/
|
||||
nsresult GetNextInterval(const nsSMILTimeValue& aBeginAfter,
|
||||
PRBool aFirstInstance,
|
||||
nsresult GetNextInterval(const nsSMILInterval* aPrevInterval,
|
||||
nsSMILInterval& aResult);
|
||||
PRBool GetNextGreater(const nsTArray<nsSMILInstanceTime>& aList,
|
||||
const nsSMILTimeValue& aBase,
|
||||
PRInt32& aPosition,
|
||||
nsSMILTimeValue& aResult);
|
||||
PRBool GetNextGreaterOrEqual(
|
||||
const nsTArray<nsSMILInstanceTime>& aList,
|
||||
const nsSMILTimeValue& aBase,
|
||||
|
@ -20,6 +20,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
# Daniel Holbert <dholbert@mozilla.com>
|
||||
# Brian Birtles <bbirtles@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -49,6 +50,8 @@ _TEST_FILES = test_smilRestart.xhtml \
|
||||
test_smilSetCurrentTime.xhtml \
|
||||
test_smilSync.xhtml \
|
||||
test_smilSyncTransform.xhtml \
|
||||
test_smilTiming.xhtml \
|
||||
test_smilTimingZeroIntervals.xhtml \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
111
content/smil/test/test_smilTiming.xhtml
Normal file
111
content/smil/test/test_smilTiming.xhtml
Normal file
@ -0,0 +1,111 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Test for SMIL timing</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
|
||||
<circle cx="-100" cy="20" r="15" fill="blue" id="circle"/>
|
||||
</svg>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
/** Test for SMIL timing **/
|
||||
|
||||
/* Global Variables */
|
||||
const svgns="http://www.w3.org/2000/svg";
|
||||
var svg = document.getElementById("svg");
|
||||
var circle = document.getElementById('circle');
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function createAnim() {
|
||||
var anim = document.createElementNS(svgns,'animate');
|
||||
anim.setAttribute('attributeName','cx');
|
||||
anim.setAttribute('from','0');
|
||||
anim.setAttribute('to','100');
|
||||
anim.setAttribute('dur','10s');
|
||||
anim.setAttribute('begin','indefinite');
|
||||
return circle.appendChild(anim);
|
||||
}
|
||||
|
||||
function removeAnim(anim) {
|
||||
anim.parentNode.removeChild(anim);
|
||||
}
|
||||
|
||||
function main() {
|
||||
svg.pauseAnimations();
|
||||
var tests =
|
||||
[ testOffsetStartup,
|
||||
testMultipleBegins,
|
||||
testNegativeBegins,
|
||||
testSorting
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var anim = createAnim();
|
||||
svg.setCurrentTime(0);
|
||||
tests[i](anim);
|
||||
removeAnim(anim);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function checkSample(time, expectedValue) {
|
||||
svg.setCurrentTime(time);
|
||||
is(circle.cx.animVal.value, expectedValue);
|
||||
}
|
||||
|
||||
function testOffsetStartup(anim) {
|
||||
anim.setAttribute('begin', '3s');
|
||||
checkSample(0,-100);
|
||||
checkSample(4,10);
|
||||
}
|
||||
|
||||
function testMultipleBegins(anim) {
|
||||
anim.setAttribute('begin', '2s; 6s');
|
||||
anim.setAttribute('dur', ' 2s');
|
||||
checkSample(0,-100);
|
||||
checkSample(3,50);
|
||||
checkSample(4,-100);
|
||||
checkSample(7,50);
|
||||
checkSample(8,-100);
|
||||
}
|
||||
|
||||
function testNegativeBegins(anim) {
|
||||
anim.setAttribute('begin', '-3s; 1s ; 4s');
|
||||
anim.setAttribute('dur', '2s ');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,-100);
|
||||
checkSample(0.5,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,50);
|
||||
checkSample(3,100);
|
||||
checkSample(5,50);
|
||||
}
|
||||
|
||||
function testSorting(anim) {
|
||||
anim.setAttribute('begin', '-3s; 110s; 1s; 4s; -5s; -10s');
|
||||
anim.setAttribute('end', '111s; -5s; -15s; 6s; -5s; 1.2s');
|
||||
anim.setAttribute('dur', '2s ');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,10);
|
||||
checkSample(4,0);
|
||||
checkSample(5,50);
|
||||
checkSample(109,100);
|
||||
checkSample(110,0);
|
||||
checkSample(112,50);
|
||||
}
|
||||
|
||||
window.addEventListener("load", main, false);
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
271
content/smil/test/test_smilTimingZeroIntervals.xhtml
Normal file
271
content/smil/test/test_smilTimingZeroIntervals.xhtml
Normal file
@ -0,0 +1,271 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Test for SMIL timing with zero-duration intervals</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
|
||||
<circle cx="-100" cy="20" r="15" fill="blue" id="circle"/>
|
||||
</svg>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
/** Test for SMIL timing with zero-duration intervals **/
|
||||
|
||||
/* Global Variables */
|
||||
const svgns="http://www.w3.org/2000/svg";
|
||||
var svg = document.getElementById("svg");
|
||||
var circle = document.getElementById('circle');
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function createAnim() {
|
||||
var anim = document.createElementNS(svgns,'animate');
|
||||
anim.setAttribute('attributeName','cx');
|
||||
anim.setAttribute('from','0');
|
||||
anim.setAttribute('to','100');
|
||||
anim.setAttribute('dur','10s');
|
||||
anim.setAttribute('begin','indefinite');
|
||||
return circle.appendChild(anim);
|
||||
}
|
||||
|
||||
function removeAnim(anim) {
|
||||
anim.parentNode.removeChild(anim);
|
||||
}
|
||||
|
||||
function main() {
|
||||
svg.pauseAnimations();
|
||||
var tests =
|
||||
[ testZeroDurationIntervalsA,
|
||||
testZeroDurationIntervalsB,
|
||||
testZeroDurationIntervalsC,
|
||||
testZeroDurationIntervalsD,
|
||||
testZeroDurationIntervalsE,
|
||||
testZeroDurationIntervalsF,
|
||||
testZeroDurationIntervalsG,
|
||||
testZeroDurationIntervalsH,
|
||||
testZeroDurationIntervalsI,
|
||||
testZeroDurationIntervalsJ,
|
||||
testZeroDurationIntervalsK,
|
||||
testZeroDurationIntervalsL,
|
||||
testZeroDurationIntervalsM,
|
||||
testZeroDurationIntervalsN,
|
||||
testZeroDurationIntervalsO
|
||||
];
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var anim = createAnim();
|
||||
svg.setCurrentTime(0);
|
||||
tests[i](anim);
|
||||
removeAnim(anim);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function checkSample(time, expectedValue) {
|
||||
svg.setCurrentTime(time);
|
||||
is(circle.cx.animVal.value, expectedValue);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsA(anim) {
|
||||
// The zero-duration interval should play, followed by a second interval
|
||||
// starting at the same point. There is no end for the interval
|
||||
// at 4s so it should not play.
|
||||
anim.setAttribute('begin', '1s ;4s');
|
||||
anim.setAttribute('end', '1s; 2s');
|
||||
anim.setAttribute('dur', '2s ');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(1.1,5);
|
||||
checkSample(2,50);
|
||||
checkSample(3,50);
|
||||
checkSample(4,50);
|
||||
checkSample(5,50);
|
||||
checkSample(6,50);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsB(anim) {
|
||||
// This interval should however actually restart as there is a valid end-point
|
||||
anim.setAttribute('begin', '1s ;4s');
|
||||
anim.setAttribute('end', '1.1s; indefinite');
|
||||
anim.setAttribute('dur', '2s ');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(1.1,5);
|
||||
checkSample(2,5);
|
||||
checkSample(4,0);
|
||||
checkSample(5,50);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsC(anim) {
|
||||
// -0.5s has already been used as the endpoint of one interval so don't use it
|
||||
// a second time
|
||||
anim.setAttribute('begin', '-2s; -0.5s');
|
||||
anim.setAttribute('end', '-0.5s; 1s');
|
||||
anim.setAttribute('dur', '2s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,25);
|
||||
checkSample(1.5,75);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsD(anim) {
|
||||
// Two end points that could make a zero-length interval
|
||||
anim.setAttribute('begin', '-2s; -0.5s');
|
||||
anim.setAttribute('end', '-0.5s; -0.5s; 1s');
|
||||
anim.setAttribute('dur', '2s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,25);
|
||||
checkSample(1.5,75);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsE(anim) {
|
||||
// Should give us 1s-1s, 1s-5s
|
||||
anim.setAttribute('begin', '1s');
|
||||
anim.setAttribute('end', '1s; 5s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),1);
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(6,40);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsF(anim) {
|
||||
// Should give us 1s-1s
|
||||
anim.setAttribute('begin', '1s');
|
||||
anim.setAttribute('end', '1s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),1);
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,0);
|
||||
is(anim.getStartTime(),1);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsG(anim) {
|
||||
// Test a non-zero interval after a zero interval
|
||||
// Should give us 1-2s, 3-3s, 3-4s
|
||||
anim.setAttribute('begin', '1s; 3s');
|
||||
anim.setAttribute('end', '3s; 5s');
|
||||
anim.setAttribute('dur', '1s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,100);
|
||||
checkSample(3,0);
|
||||
checkSample(5,100);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsH(anim) {
|
||||
// Test multiple non-adjacent zero-intervals
|
||||
// Should give us 1-1s, 1-2s, 3-3s, 3-4s
|
||||
anim.setAttribute('begin', '1s; 3s');
|
||||
anim.setAttribute('end', '1s; 3s; 5s');
|
||||
anim.setAttribute('dur', '1s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,100);
|
||||
checkSample(3,0);
|
||||
checkSample(5,100);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsI(anim) {
|
||||
// Test skipping values that are the same
|
||||
// Should give us 1-1s, 1-2s
|
||||
anim.setAttribute('begin', '1s; 1s');
|
||||
anim.setAttribute('end', '1s; 1s; 2s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),1);
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,10);
|
||||
checkSample(3,10);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsJ(anim) {
|
||||
// Should give us 0-0.5s, 1-1s, 1-3s
|
||||
anim.setAttribute('begin', '0s; 1s; 1s');
|
||||
anim.setAttribute('end', '1s; 3s');
|
||||
anim.setAttribute('dur', '0.5s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),0);
|
||||
checkSample(0,0);
|
||||
checkSample(0.6,100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,100);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsK(anim) {
|
||||
// Should give us -0.5-1s
|
||||
anim.setAttribute('begin', '-0.5s');
|
||||
anim.setAttribute('end', '-0.5s; 1s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),-0.5);
|
||||
checkSample(0,5);
|
||||
checkSample(1,15);
|
||||
checkSample(2,15);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsL(anim) {
|
||||
// Test that multiple end values are ignored
|
||||
// Should give us 1-1s, 1-3s
|
||||
anim.setAttribute('begin', '1s');
|
||||
anim.setAttribute('end', '1s; 1s; 1s; 3s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),1);
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(2,10);
|
||||
checkSample(4,20);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsM(anim) {
|
||||
// Test 0-duration interval at start
|
||||
anim.setAttribute('begin', '0s');
|
||||
anim.setAttribute('end', '0s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),0);
|
||||
checkSample(0,0);
|
||||
checkSample(1,0);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsN(anim) {
|
||||
// Test 0-active-duration interval at start (different code path to above)
|
||||
anim.setAttribute('begin', '0s');
|
||||
anim.setAttribute('repeatDur', '0s');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),0);
|
||||
checkSample(0,0);
|
||||
checkSample(1,0);
|
||||
}
|
||||
|
||||
function testZeroDurationIntervalsO(anim) {
|
||||
// Make a zero-duration interval by constraining the active duration
|
||||
// We should not loop infinitely but should look for the next begin time after
|
||||
// that (in this case that is 2s, which would otherwise have been skipped
|
||||
// because restart=whenNotActive)
|
||||
// Should give us 1-1s, 2-2s
|
||||
anim.setAttribute('begin', '1s; 2s');
|
||||
anim.setAttribute('repeatDur', '0s');
|
||||
anim.setAttribute('restart', 'whenNotActive');
|
||||
anim.setAttribute('fill', 'freeze');
|
||||
is(anim.getStartTime(),1);
|
||||
checkSample(0,-100);
|
||||
checkSample(1,0);
|
||||
checkSample(1.5,0);
|
||||
checkSample(3,0);
|
||||
is(anim.getStartTime(),2);
|
||||
}
|
||||
|
||||
window.addEventListener("load", main, false);
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user