Bug 1343357 - Ignore lower-priority animateMotion if a to-animation is encountered r=dholbert

Current impl at SVGMotionSMILType::Interpolate has some wrong assertions, it's probably caused by overlooking the special behavior of to-animation. These assumptions also lead weird animation in the product build. Now we take to-animation into account, and implement similar behavior as Chrome and Safari.

Differential Revision: https://phabricator.services.mozilla.com/D23095

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-03-15 01:26:13 +00:00
Родитель bdcd004f99
Коммит 71e059e062
3 изменённых файлов: 29 добавлений и 8 удалений

Просмотреть файл

@ -0,0 +1,12 @@
<svg>
<animateMotion to="500,500"></animateMotion>
<animateMotion to="10,40"></animateMotion>
</svg>
<svg width="100" height="100">
<rect width="100%" height="100%" />
<circle r="2" fill="red">
<animateMotion dur="1s" from="50,50" to="80,70" additive="sum"></animateMotion>
<animateMotion dur="1s" from="50,50" to="80,70" additive="sum"></animateMotion>
<animateMotion dur="3s" to="0,80"></animateMotion>
</circle>
</svg>

После

Ширина:  |  Высота:  |  Размер: 444 B

Просмотреть файл

@ -55,6 +55,7 @@ load 849593-1.xhtml
load 1010681-1.svg
load 1322770-1.svg
load 1322849-1.svg
load 1343357-1.html
load 1375596-1.svg
load 1402547-1.html
load 1411963-1.html

Просмотреть файл

@ -363,8 +363,6 @@ nsresult SVGMotionSMILType::Interpolate(const SMILValue& aStartVal,
const MotionSegmentArray& endArr = ExtractMotionSegmentArray(aEndVal);
MotionSegmentArray& resultArr = ExtractMotionSegmentArray(aResult);
MOZ_ASSERT(startArr.Length() <= 1,
"Invalid start-point for animateMotion interpolation");
MOZ_ASSERT(endArr.Length() == 1,
"Invalid end-point for animateMotion interpolation");
MOZ_ASSERT(resultArr.IsEmpty(),
@ -375,17 +373,29 @@ nsresult SVGMotionSMILType::Interpolate(const SMILValue& aStartVal,
"Expecting to be interpolating along a path");
const PathPointParams& endParams = endSeg.mU.mPathPointParams;
// NOTE: path & angle should match between start & end (since presumably
// start & end came from the same <animateMotion> element), unless start is
// empty. (as it would be for pure 'to' animation)
// NOTE: Ususally, path & angle should match between start & end (since
// presumably start & end came from the same <animateMotion> element),
// unless start is empty. (as it would be for pure 'to' animation)
// Notable exception: when a to-animation layers on top of lower priority
// animation(s) -- see comment below.
Path* path = endParams.mPath;
RotateType rotateType = endSeg.mRotateType;
float rotateAngle = endSeg.mRotateAngle;
float startDist;
if (startArr.IsEmpty()) {
if (startArr.IsEmpty() ||
startArr[0].mU.mPathPointParams.mPath != endParams.mPath) {
// When a to-animation follows other lower priority animation(s),
// the endParams will contain a different path from the animation(s)
// that it layers on top of.
// Per SMIL spec, we should interpolate from the value at startArr.
// However, neither Chrome nor Safari implements to-animation that way.
// For simplicity, we use the same behavior as other browsers: override
// previous animations and start at the initial underlying value.
startDist = 0.0f;
} else {
MOZ_ASSERT(startArr.Length() <= 1,
"Invalid start-point for animateMotion interpolation");
const MotionSegment& startSeg = startArr[0];
MOZ_ASSERT(startSeg.mSegmentType == eSegmentType_PathPoint,
"Expecting to be interpolating along a path");
@ -393,8 +403,6 @@ nsresult SVGMotionSMILType::Interpolate(const SMILValue& aStartVal,
MOZ_ASSERT(startSeg.mRotateType == endSeg.mRotateType &&
startSeg.mRotateAngle == endSeg.mRotateAngle,
"unexpected angle mismatch");
MOZ_ASSERT(startParams.mPath == endParams.mPath,
"unexpected path mismatch");
startDist = startParams.mDistToPoint;
}