Bug 651036 - SMIL: Make discrete to-animations behave consistently with discrete from-to animations r=dholbert

This commit is contained in:
Cameron McCormack 2011-04-20 14:05:29 +12:00
parent ff19a13fe9
commit c0000045de
12 changed files with 68 additions and 53 deletions

View File

@ -395,6 +395,10 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
return NS_ERROR_FAILURE;
}
if (IsToAnimation() && aBaseValue.IsNull()) {
return NS_ERROR_FAILURE;
}
// Get the normalised progress through the simple duration.
//
// If we have an indefinite simple duration, just set the progress to be
@ -428,19 +432,15 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
// NS_ABORT_IF_FALSE that tests that intervalProgress is in range will fail.
double intervalProgress = -1.f;
if (IsToAnimation()) {
if (aBaseValue.IsNull()) {
rv = NS_ERROR_FAILURE;
from = &aBaseValue;
to = &aValues[0];
if (calcMode == CALC_PACED) {
// Note: key[Times/Splines/Points] are ignored for calcMode="paced"
intervalProgress = simpleProgress;
} else {
from = &aBaseValue;
to = &aValues[0];
if (calcMode == CALC_PACED) {
// Note: key[Times/Splines/Points] are ignored for calcMode="paced"
intervalProgress = simpleProgress;
} else {
double scaledSimpleProgress =
ScaleSimpleProgress(simpleProgress, calcMode);
intervalProgress = ScaleIntervalProgress(scaledSimpleProgress, 0);
}
double scaledSimpleProgress =
ScaleSimpleProgress(simpleProgress, calcMode);
intervalProgress = ScaleIntervalProgress(scaledSimpleProgress, 0);
}
} else if (calcMode == CALC_PACED) {
rv = ComputePacedPosition(aValues, simpleProgress,
@ -474,13 +474,16 @@ nsSMILAnimationFunction::InterpolateResult(const nsSMILValueArray& aValues,
// Note: If interpolation failed (isn't supported for this type), the SVG
// spec says to force discrete mode.
if (calcMode == CALC_DISCRETE || NS_FAILED(rv)) {
double scaledSimpleProgress =
ScaleSimpleProgress(simpleProgress, CALC_DISCRETE);
if (IsToAnimation()) {
// SMIL 3, 12.6.4: Since a to animation has only 1 value, a discrete to
// animation will simply set the to value for the simple duration.
aResult = aValues[0];
// We don't follow SMIL 3, 12.6.4, where discrete to animations
// are the same as <set> animations. Instead, we treat it as a
// discrete animation with two values (the underlying value and
// the to="" value), and honor keyTimes="" as well.
PRUint32 index = (PRUint32)floor(scaledSimpleProgress * 2);
aResult = index == 0 ? aBaseValue : aValues[0];
} else {
double scaledSimpleProgress =
ScaleSimpleProgress(simpleProgress, CALC_DISCRETE);
PRUint32 index = (PRUint32)floor(scaledSimpleProgress * aValues.Length());
aResult = aValues[index];
}
@ -865,11 +868,9 @@ nsSMILAnimationFunction::CheckKeyTimes(PRUint32 aNumValues)
}
// no. keyTimes == no. values
// For to-animation the number of values is considered to be 2 unless it's
// discrete to-animation in which case either 1 or 2 is acceptable.
PRBool matchingNumOfValues = IsToAnimation() ?
calcMode == CALC_DISCRETE ? numKeyTimes <= 2 : numKeyTimes == 2 :
numKeyTimes == aNumValues;
// For to-animation the number of values is considered to be 2.
PRBool matchingNumOfValues =
numKeyTimes == (IsToAnimation() ? 2 : aNumValues);
if (!matchingNumOfValues) {
SetKeyTimesErrorFlag(PR_TRUE);
return;

View File

@ -152,26 +152,36 @@ function main()
'times': [ [ 2, -100 ] ]
});
// to calcMode=discrete two keyTimes
// (technically, for discrete to-animation there is only ONE animation value
// but we allow two keyTimes to be specified since they're not going to have
// any effect anyway and this part of the spec is somewhat counter-intuitive.
// See bug 544855)
// unfrozen to calcMode=discrete two keyTimes
testCases.push({
'attr' : { 'to': '100',
'calcMode': 'discrete',
'keyTimes': '0.0; 1.0',
'fill': 'remove' },
'times': [ [ 0, -100 ],
[ 7, -100 ],
[ 10, -100 ],
[ 12, -100 ]]
});
// frozen to calcMode=discrete two keyTimes
testCases.push({
'attr' : { 'to': '100',
'calcMode': 'discrete',
'keyTimes': '0.0; 1.0' },
'times': [ [ 0, 100 ],
[ 7, 100 ] ]
'times': [ [ 0, -100 ],
[ 7, -100 ],
[ 10, 100 ],
[ 12, 100 ] ]
});
// to calcMode=discrete one keyTime
// to calcMode=discrete -- bad number of keyTimes (one, expecting two)
testCases.push({
'attr' : { 'to': '100',
'calcMode': 'discrete',
'keyTimes': '0' },
'times': [ [ 0, 100 ],
[ 7, 100 ] ]
'times': [ [ 0, -100 ],
[ 7, -100 ] ]
});
// values calcMode=discrete

View File

@ -3,8 +3,8 @@
class="reftest-wait"
onload="setTimeAndSnapshot(0.0, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="100" fill="blue">
<rect x="15" y="15" width="200" height="200" fill="blue">
<animate attributeName="height" calcMode="discrete"
to="200" dur="2s"/>
to="100" dur="2s"/>
</rect>
</svg>

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

@ -3,8 +3,8 @@
class="reftest-wait"
onload="setTimeAndSnapshot(0.99, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="100" fill="blue">
<rect x="15" y="15" width="200" height="200" fill="blue">
<animate attributeName="height" calcMode="discrete"
to="200" dur="2s"/>
to="100" dur="2s"/>
</rect>
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 387 B

View File

@ -85,10 +85,10 @@
<feComponentTransfer>
<feFuncR type="table" tableValues="0 0 0 0">
<!-- The value should be "0 2 2 0" immediately. -->
<!-- The value should be "0 2 2 0" from 1s onwards. -->
<animate attributeName="tableValues"
calcMode="discrete"
begin="0s" dur="3s"
begin="0s" dur="2s"
to="0 2 2 0"
fill="freeze"/>

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,14 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait" onload="setTimeAndSnapshot(2, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<!-- In this test we will attempt to interpolate since fill is interpolatable
but fail since the base value can't be converted to an RGB color value
and hence should fall back to discrete calcMode which, in the case of
to-animation, sets the to value for the entire simple duration. -->
to-animation, sets the to value for the second half of the simple
duration. -->
<defs>
<linearGradient id="red">
<stop offset="0.0" stop-color="#f00"/>
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#red)">
<animate attributeName="fill" to="lime" dur="500s"/>
<animate attributeName="fill" to="lime" dur="3s"/>
</rect>
</svg>

Before

Width:  |  Height:  |  Size: 594 B

After

Width:  |  Height:  |  Size: 783 B

View File

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg">
<!-- Test that an indefinite to-animation with discrete calcMode still applies
the to-value for the whole time. -->
<rect x="15" y="15" width="200" height="100" fill="blue">
<animate attributeName="height" to="200" dur="indefinite"
<!-- Test that an indefinite to-animation with discrete calcMode applies
the underlying value for the whole time. -->
<rect x="15" y="15" width="200" height="200" fill="blue">
<animate attributeName="height" to="100" dur="indefinite"
calcMode="discrete"/>
</rect>
</svg>

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 335 B

View File

@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg">
<!-- Test that an indefinite to-animation that falls back to discrete calcMode
because the property is not interpolatable, still applies the to-value
because the property is not interpolatable, applies the underlying value
for the whole time. -->
<rect x="15" y="15" width="200" height="200" fill="blue" visibility="hidden">
<animate attributeName="visibility" to="visible" dur="indefinite"/>
<rect x="15" y="15" width="200" height="200" fill="blue" visibility="visible">
<animate attributeName="visibility" to="hidden" dur="indefinite"/>
</rect>
</svg>

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 402 B

View File

@ -302,7 +302,7 @@
">
<animate attributeName="d"
calcMode="discrete"
begin="0s" dur="20s"
begin="0s" dur="2s"
to="M10,10
L40,10
l-30,60

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -65,7 +65,7 @@
points="10,10 70,70 110,10 160,10 210,10">
<animate attributeName="points"
calcMode="discrete"
begin="0s" dur="20s"
begin="0s" dur="2s"
to="10,10 70,10 110,10 160,70 210,10"
fill="freeze"/>
</polygon>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -65,7 +65,7 @@
points="10,10 70,70 110,10 160,10 210,10">
<animate attributeName="points"
calcMode="discrete"
begin="0s" dur="20s"
begin="0s" dur="2s"
to="10,10 70,10 110,10 160,70 210,10"
fill="freeze"/>
</polyline>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -61,10 +61,10 @@
<text transform="translate(320, 20)" rotate="10 20 30">JKL
<!-- The value should be "310 320 330" immediately. -->
<!-- The value should be "310 320 330" at 3s. -->
<animate attributeName="rotate"
calcMode="discrete"
begin="0s" dur="30s"
begin="0s" dur="6s"
to="310 320 330"
fill="freeze"/>

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB