Bug 436418, patch D: SVG/SMIL animateMotion - reftests & mochitests.

--HG--
rename : layout/reftests/svg/smil/lime.svg => layout/reftests/svg/smil/motion/lime.svg
This commit is contained in:
Daniel Holbert 2010-04-28 16:00:54 -07:00
Родитель b3431bf535
Коммит b32821031e
19 изменённых файлов: 1594 добавлений и 3 удалений

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

@ -45,13 +45,18 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
db_smilAnimateMotion.js \
db_smilCSSFromBy.js \
db_smilCSSFromTo.js \
db_smilCSSPaced.js \
db_smilCSSPropertyList.js \
db_smilMappedAttrList.js \
smilAnimateMotionValueLists.js \
smilTestUtils.js \
smilXHR_helper.svg \
test_smilAnimateMotion.xhtml \
test_smilAnimateMotionInvalidValues.xhtml \
test_smilAnimateMotionOverrideRules.xhtml \
test_smilChangeAfterFrozen.xhtml \
test_smilContainerBinding.xhtml \
test_smilCrossContainer.xhtml \

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

@ -0,0 +1,286 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SMIL Test Code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* testcase data for <animateMotion> */
// Fake motion 'attribute', to satisfy testing code that expects an attribute.
var gMotionAttr = new AdditiveAttribute(SMILUtil.getMotionFakeAttributeName(),
"XML", "rect");
// CTM-summary-definitions, for re-use by multiple testcase bundles below.
var _reusedCTMLists = {
pacedBasic: { ctm0: [100, 200, 0],
ctm1_6: [105, 205, 0],
ctm1_3: [110, 210, 0],
ctm2_3: [120, 220, 0],
ctm1: [130, 210, 0]
},
pacedR60: { ctm0: [100, 200, Math.PI/3],
ctm1_6: [105, 205, Math.PI/3],
ctm1_3: [110, 210, Math.PI/3],
ctm2_3: [120, 220, Math.PI/3],
ctm1: [130, 210, Math.PI/3]
},
pacedRAuto: { ctm0: [100, 200, Math.PI/4],
ctm1_6: [105, 205, Math.PI/4],
ctm1_3: [110, 210, Math.PI/4],
ctm2_3: [120, 220, Math.PI/4],
ctm1: [130, 210, -Math.PI/4]
},
pacedRAutoReverse : { ctm0: [100, 200, 5*Math.PI/4],
ctm1_6: [105, 205, 5*Math.PI/4],
ctm1_3: [110, 210, 5*Math.PI/4],
ctm2_3: [120, 220, 5*Math.PI/4],
ctm1: [130, 210, 3*Math.PI/4]
},
discreteBasic : { ctm0: [100, 200, 0],
ctm1_6: [100, 200, 0],
ctm1_3: [120, 220, 0],
ctm2_3: [130, 210, 0],
ctm1: [130, 210, 0]
},
discreteRAuto : { ctm0: [100, 200, Math.PI/4],
ctm1_6: [100, 200, Math.PI/4],
ctm1_3: [120, 220, Math.PI/4],
ctm2_3: [130, 210, -Math.PI/4],
ctm1: [130, 210, -Math.PI/4]
},
justMoveBasic : { ctm0: [40, 80, 0],
ctm1_6: [40, 80, 0],
ctm1_3: [40, 80, 0],
ctm2_3: [40, 80, 0],
ctm1: [40, 80, 0]
},
justMoveR60 : { ctm0: [40, 80, Math.PI/3],
ctm1_6: [40, 80, Math.PI/3],
ctm1_3: [40, 80, Math.PI/3],
ctm2_3: [40, 80, Math.PI/3],
ctm1: [40, 80, Math.PI/3]
},
justMoveRAuto : { ctm0: [40, 80, Math.atan(2)],
ctm1_6: [40, 80, Math.atan(2)],
ctm1_3: [40, 80, Math.atan(2)],
ctm2_3: [40, 80, Math.atan(2)],
ctm1: [40, 80, Math.atan(2)]
},
justMoveRAutoReverse : { ctm0: [40, 80, Math.PI + Math.atan(2)],
ctm1_6: [40, 80, Math.PI + Math.atan(2)],
ctm1_3: [40, 80, Math.PI + Math.atan(2)],
ctm2_3: [40, 80, Math.PI + Math.atan(2)],
ctm1: [40, 80, Math.PI + Math.atan(2)]
},
nullMoveBasic : { ctm0: [0, 0, 0],
ctm1_6: [0, 0, 0],
ctm1_3: [0, 0, 0],
ctm2_3: [0, 0, 0],
ctm1: [0, 0, 0]
},
nullMoveRAutoReverse : { ctm0: [0, 0, Math.PI],
ctm1_6: [0, 0, Math.PI],
ctm1_3: [0, 0, Math.PI],
ctm2_3: [0, 0, Math.PI],
ctm1: [0, 0, Math.PI]
},
};
var gMotionBundles =
[
// Bundle to test basic functionality (using default calcMode='paced')
new TestcaseBundle(gMotionAttr, [
// Basic paced-mode (default) test, with values/mpath/path
new AnimMotionTestcase({ "values": "100, 200; 120, 220; 130, 210" },
_reusedCTMLists.pacedBasic),
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210" },
_reusedCTMLists.pacedBasic),
new AnimMotionTestcase({ "mpath": "M100 200 L120 220 L130 210" },
_reusedCTMLists.pacedBasic),
// ..and now with rotate=constant value in degrees
new AnimMotionTestcase({ "values": "100,200; 120,220; 130, 210",
"rotate": "60" },
_reusedCTMLists.pacedR60),
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210",
"rotate": "60" },
_reusedCTMLists.pacedR60),
new AnimMotionTestcase({ "mpath": "M100 200 L120 220 L130 210",
"rotate": "60" },
_reusedCTMLists.pacedR60),
// ..and now with rotate=constant value in radians
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210",
"rotate": "1.0471975512rad" }, // pi/3
_reusedCTMLists.pacedR60),
// ..and now with rotate=auto
new AnimMotionTestcase({ "values": "100,200; 120,220; 130, 210",
"rotate": "auto" },
_reusedCTMLists.pacedRAuto),
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210",
"rotate": "auto" },
_reusedCTMLists.pacedRAuto),
new AnimMotionTestcase({ "mpath": "M100 200 L120 220 L130 210",
"rotate": "auto" },
_reusedCTMLists.pacedRAuto),
// ..and now with rotate=auto-reverse
new AnimMotionTestcase({ "values": "100,200; 120,220; 130, 210",
"rotate": "auto-reverse" },
_reusedCTMLists.pacedRAutoReverse),
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210",
"rotate": "auto-reverse" },
_reusedCTMLists.pacedRAutoReverse),
new AnimMotionTestcase({ "mpath": "M100 200 L120 220 L130 210",
"rotate": "auto-reverse" },
_reusedCTMLists.pacedRAutoReverse),
]),
// Bundle to test calcMode='discrete'
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "100, 200; 120, 220; 130, 210",
"calcMode": "discrete" },
_reusedCTMLists.discreteBasic),
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210",
"calcMode": "discrete" },
_reusedCTMLists.discreteBasic),
new AnimMotionTestcase({ "mpath": "M100 200 L120 220 L130 210",
"calcMode": "discrete" },
_reusedCTMLists.discreteBasic),
// ..and now with rotate=auto
new AnimMotionTestcase({ "values": "100, 200; 120, 220; 130, 210",
"calcMode": "discrete",
"rotate": "auto" },
_reusedCTMLists.discreteRAuto),
new AnimMotionTestcase({ "path": "M100 200 L120 220 L130 210",
"calcMode": "discrete",
"rotate": "auto" },
_reusedCTMLists.discreteRAuto),
new AnimMotionTestcase({ "mpath": "M100 200 L120 220 L130 210",
"calcMode": "discrete",
"rotate": "auto" },
_reusedCTMLists.discreteRAuto),
]),
// Bundle to test relative units ('em')
new TestcaseBundle(gMotionAttr, [
// First with unitless values from->by...
new AnimMotionTestcase({ "from": "10, 10",
"by": "30, 60" },
{ ctm0: [10, 10, 0],
ctm1_6: [15, 20, 0],
ctm1_3: [20, 30, 0],
ctm2_3: [30, 50, 0],
ctm1: [40, 70, 0]
}),
// ... then add 'em' units (with 1em=10px) on half the values
new AnimMotionTestcase({ "from": "1em, 10",
"by": "30, 6em" },
{ ctm0: [10, 10, 0],
ctm1_6: [15, 20, 0],
ctm1_3: [20, 30, 0],
ctm2_3: [30, 50, 0],
ctm1: [40, 70, 0]
}),
]),
// Bundle to test a path with just a "move" command and nothing else
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "40, 80" },
_reusedCTMLists.justMoveBasic),
new AnimMotionTestcase({ "path": "M40 80" },
_reusedCTMLists.justMoveBasic),
new AnimMotionTestcase({ "mpath": "m40 80" },
_reusedCTMLists.justMoveBasic),
]),
// ... and now with a fixed rotate-angle
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "40, 80",
"rotate": "60" },
_reusedCTMLists.justMoveR60),
new AnimMotionTestcase({ "path": "M40 80",
"rotate": "60" },
_reusedCTMLists.justMoveR60),
new AnimMotionTestcase({ "mpath": "m40 80",
"rotate": "60" },
_reusedCTMLists.justMoveR60),
]),
// ... and now with 'auto' (should use the move itself as
// our tangent angle, I think)
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "40, 80",
"rotate": "auto" },
_reusedCTMLists.justMoveRAuto),
new AnimMotionTestcase({ "path": "M40 80",
"rotate": "auto" },
_reusedCTMLists.justMoveRAuto),
new AnimMotionTestcase({ "mpath": "m40 80",
"rotate": "auto" },
_reusedCTMLists.justMoveRAuto),
]),
// ... and now with 'auto-reverse'
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "40, 80",
"rotate": "auto-reverse" },
_reusedCTMLists.justMoveRAutoReverse),
new AnimMotionTestcase({ "path": "M40 80",
"rotate": "auto-reverse" },
_reusedCTMLists.justMoveRAutoReverse),
new AnimMotionTestcase({ "mpath": "m40 80",
"rotate": "auto-reverse" },
_reusedCTMLists.justMoveRAutoReverse),
]),
// ... and now with a null move to make sure 'auto'/'auto-reverse' don't
// blow up
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "0, 0",
"rotate": "auto" },
_reusedCTMLists.nullMoveBasic),
]),
new TestcaseBundle(gMotionAttr, [
new AnimMotionTestcase({ "values": "0, 0",
"rotate": "auto-reverse" },
_reusedCTMLists.nullMoveRAutoReverse),
]),
];
// XXXdholbert Add more tests:
// - keyPoints/keyTimes
// - paths with curves
// - Control path with from/by/to

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

@ -0,0 +1,124 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SMIL Test Code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Lists of valid & invalid values for the various <animateMotion> attributes */
const gValidValues = [
"10 10",
" 10 10em ",
"1 2 ; 3,4",
"1,2;3,4",
"0 0",
"0,0",
];
const gInvalidValues = [
"10 10;", // We treat semicolon-terminated value-lists as failure cases
"1 2 3",
"1 2 3 4",
"1,2;3,4 ,",
",", ";", "a", "", " ",
];
const gInvalidValuesTodo = [
"1,2;3,4,",
"1,,2",
",1,2",
];
const gValidRotate = [
"10",
"20.1",
"30.5deg",
"0.5rad",
"auto",
"auto-reverse"
];
const gInvalidRotate = [
" 10 ",
" 10deg",
"10 deg",
"10deg ",
"10 rad ",
"aaa",
" 10.1 ",
];
const gValidToBy = [
"0 0",
"1em,2",
"50.3em 0.2in"
];
const gInvalidToBy = [
"0 0 0",
"0 0,0",
"0,0,0",
"1emm 2",
"1 2;",
" 1,2 ,",
"abc",
",",
""
];
const gInvalidToByTodo = [
"1,,2",
"1,2,",
" 1,2",
"1 2 "
];
const gValidPath = [
"m0 0 L30 30",
"M20,20L10 10",
"M20,20 L30, 30h20",
"m50 50", "M50 50",
"m0 0", "M0, 0"
];
const gInvalidPath = [
"m0 0 L30,,30",
"M20 20em",
"M20in 20",
"h30",
"L50 50",
"abc",
"M10 10 L50 50 abc",
];

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

@ -39,6 +39,9 @@
// Note: Class syntax roughly based on:
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance
const SVG_NS = "http://www.w3.org/2000/svg";
const XLINK_NS = "http://www.w3.org/1999/xlink";
const MPATH_TARGET_ID = "smilTestUtilsTestingPath";
function extend(child, supertype)
{
@ -85,11 +88,16 @@ var SMILUtil =
getAttributeValue: function(elem, attr)
{
if (attr.attrName == SMILUtil.getMotionFakeAttributeName()) {
// Fake motion "attribute" -- "computed value" is the element's CTM
return elem.getCTM();
}
if (attr.attrType == "CSS") {
return SMILUtil.getComputedStyleWrapper(elem, attr.attrName);
} else if (attr.attrType == "XML") {
}
if (attr.attrType == "XML") {
// XXXdholbert This is appropriate for mapped attributes, but not
// for others.
// for other attributes.
return SMILUtil.getComputedStyleWrapper(elem, attr.attrName);
}
},
@ -168,7 +176,82 @@ var SMILUtil =
child = child.nextSibling;
}
},
getMotionFakeAttributeName : function() {
return "_motion";
},
};
var CTMUtil =
{
CTM_COMPONENTS_ALL : ["a", "b", "c", "d", "e", "f"],
CTM_COMPONENTS_ROTATE : ["a", "b", "c", "d" ],
// Function to generate a CTM Matrix from a "summary"
// (a 3-tuple containing [tX, tY, theta])
generateCTM : function(aCtmSummary)
{
if (!aCtmSummary || aCtmSummary.length != 3) {
ok(false, "Unexpected CTM summary tuple length: " + aCtmSummary.length);
}
var tX = aCtmSummary[0];
var tY = aCtmSummary[1];
var theta = aCtmSummary[2];
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
var newCtm = { a : cosTheta, c: -sinTheta, e: tX,
b : sinTheta, d: cosTheta, f: tY };
return newCtm;
},
/// Helper for isCtmEqual
isWithinDelta : function(aTestVal, aExpectedVal, aErrMsg, aIsTodo) {
var testFunc = aIsTodo ? todo : ok;
const delta = 0.000001; // allowing margin of error = 10^-6
ok(aTestVal >= aExpectedVal - delta &&
aTestVal <= aExpectedVal + delta,
aErrMsg + " | got: " + aTestVal + ", expected: " + aExpectedVal);
},
assertCTMEqual : function(aLeftCtm, aRightCtm, aComponentsToCheck,
aErrMsg, aIsTodo) {
var foundCTMDifference = false;
for (var j in aComponentsToCheck) {
var curComponent = aComponentsToCheck[j];
if (!aIsTodo) {
CTMUtil.isWithinDelta(aLeftCtm[curComponent], aRightCtm[curComponent],
aErrMsg + " | component: " + curComponent, false);
} else if (aLeftCtm[curComponent] != aRightCtm[curComponent]) {
foundCTMDifference = true;
}
}
if (aIsTodo) {
todo(!foundCTMDifference, aErrMsg + " | (currently marked todo)");
}
},
assertCTMNotEqual : function(aLeftCtm, aRightCtm, aComponentsToCheck,
aErrMsg, aIsTodo) {
// CTM should not match initial one
var foundCTMDifference = false;
for (var j in aComponentsToCheck) {
var curComponent = aComponentsToCheck[j];
if (aLeftCtm[curComponent] != aRightCtm[curComponent]) {
foundCTMDifference = true;
break; // We found a difference, as expected. Success!
}
}
if (aIsTodo) {
todo(foundCTMDifference, aErrMsg + " | (currently marked todo)");
} else {
ok(foundCTMDifference, aErrMsg);
}
},
};
// Wrapper for timing information
function SMILTimingData(aBegin, aDur)
@ -685,6 +768,154 @@ AnimTestcasePaced.prototype =
};
extend(AnimTestcasePaced, AnimTestcase);
/*
* A testcase for an <animateMotion> animation.
*
* @param aAttrValueHash A hash-map mapping attribute names to values.
* Should include at least 'path', 'values', 'to'
* or 'by' to describe the motion path.
* @param aCtmMap A hash-map that contains summaries of the expected resulting
* CTM at various points during the animation. The CTM is
* summarized as a tuple of three numbers: [tX, tY, theta]
(indicating a translate(tX,tY) followed by a rotate(theta))
* - ctm0: The CTM summary at the start of the animation
* - ctm1_6: The CTM summary at exactly 1/6 through animation
* - ctm1_3: The CTM summary at exactly 1/3 through animation
* - ctm2_3: The CTM summary at exactly 2/3 through animation
* - ctm1: The CTM summary at the animation endpoint
*
* NOTE: For paced-mode animation (the default for animateMotion), the math
* works out easiest if:
* (a) our motion path has 3 points: vA, vB, vC
* (b) dist(vB, vC) = 2 * dist(vA, vB)
* (See discussion in header comment for AnimTestcasePaced.)
*
* @param aSkipReason If this test-case is known to currently fail, this
* parameter should be a string explaining why.
* Otherwise, this value should be null (or omitted).
*/
function AnimMotionTestcase(aAttrValueHash, aCtmMap, aSkipReason)
{
this.attrValueHash = aAttrValueHash;
this.ctmMap = aCtmMap;
this.skipReason = aSkipReason;
if (this.ctmMap &&
(!this.ctmMap.ctm0 ||
!this.ctmMap.ctm1_6 ||
!this.ctmMap.ctm1_3 ||
!this.ctmMap.ctm2_3 ||
!this.ctmMap.ctm1)) {
ok(false, "This AnimMotionTestcase has an incomplete CTM map");
}
}
AnimMotionTestcase.prototype =
{
// Member variables
_animElementTagName : "animateMotion",
// Implementations of inherited methods that we need to override:
// --------------------------------------------------------------
setupAnimationElement : function(aAnimAttr, aTimeData, aIsFreeze)
{
var animElement = document.createElementNS(SVG_NS,
this._animElementTagName);
animElement.setAttribute("begin", aTimeData.getBeginTime());
animElement.setAttribute("dur", aTimeData.getDur());
if (aIsFreeze) {
animElement.setAttribute("fill", "freeze");
}
for (var attrName in this.attrValueHash) {
if (attrName == "mpath") {
this.createPath(this.attrValueHash[attrName]);
this.createMpath(animElement);
} else {
animElement.setAttribute(attrName, this.attrValueHash[attrName]);
}
}
return animElement;
},
createPath : function(aPathDescription)
{
var path = document.createElementNS(SVG_NS, "path");
path.setAttribute("d", aPathDescription);
path.setAttribute("id", MPATH_TARGET_ID);
return SMILUtil.getSVGRoot().appendChild(path);
},
createMpath : function(aAnimElement)
{
var mpath = document.createElementNS(SVG_NS, "mpath");
mpath.setAttributeNS(XLINK_NS, "href", "#" + MPATH_TARGET_ID);
return aAnimElement.appendChild(mpath);
},
// Override inherited seekAndTest method since...
// (a) it expects a computedValMap and we have a computed-CTM map instead
// and (b) it expects we might have no effect (for non-animatable attrs)
buildSeekList : function(aAnimAttr, aBaseVal, aTimeData, aIsFreeze)
{
var seekList = new Array();
var msgPrefix = "CTM mismatch ";
seekList.push([aTimeData.getBeginTime(),
CTMUtil.generateCTM(this.ctmMap.ctm0),
msgPrefix + "at start of animation"]);
seekList.push([aTimeData.getFractionalTime(1/6),
CTMUtil.generateCTM(this.ctmMap.ctm1_6),
msgPrefix + "1/6 of the way through animation."]);
seekList.push([aTimeData.getFractionalTime(1/3),
CTMUtil.generateCTM(this.ctmMap.ctm1_3),
msgPrefix + "1/3 of the way through animation."]);
seekList.push([aTimeData.getFractionalTime(2/3),
CTMUtil.generateCTM(this.ctmMap.ctm2_3),
msgPrefix + "2/3 of the way through animation."]);
var finalMsg;
var expectedEndVal;
if (aIsFreeze) {
expectedEndVal = CTMUtil.generateCTM(this.ctmMap.ctm1);
finalMsg = aAnimAttr.attrName +
": [freeze-mode] checking that final value is set ";
} else {
expectedEndVal = aBaseVal;
finalMsg = aAnimAttr.attrName +
": [remove-mode] checking that animation is cleared ";
}
seekList.push([aTimeData.getEndTime(),
expectedEndVal, finalMsg + "at end of animation"]);
seekList.push([aTimeData.getEndTime() + aTimeData.getDur(),
expectedEndVal, finalMsg + "after end of animation"]);
return seekList;
},
// Override inherited seekAndTest method
// (Have to use assertCTMEqual() instead of is() for comparison, to check each
// component of the CTM and to allow for a small margin of error.)
seekAndTest : function(aSeekList, aTargetElem, aTargetAttr)
{
var svg = document.getElementById("svg");
for (var i in aSeekList) {
var entry = aSeekList[i];
SMILUtil.getSVGRoot().setCurrentTime(entry[0]);
CTMUtil.assertCTMEqual(aTargetElem.getCTM(), entry[1],
CTMUtil.CTM_COMPONENTS_ALL, entry[2], false);
}
},
// Override "runTest" method so we can remove any <path> element that we
// created at the end of each test.
runTest : function(aTargetElem, aTargetAttr, aTimeData, aIsFreeze)
{
AnimTestcase.prototype.runTest.apply(this,
[aTargetElem, aTargetAttr, aTimeData, aIsFreeze]);
var pathElem = document.getElementById(MPATH_TARGET_ID);
if (pathElem) {
SMILUtil.getSVGRoot().removeChild(pathElem);
}
}
};
extend(AnimMotionTestcase, AnimTestcase);
// MAIN METHOD
function testBundleList(aBundleList, aTimingData)
{

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

@ -0,0 +1,58 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=436418
-->
<head>
<title>Test for animateMotion behavior</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="smilTestUtils.js"></script>
<script type="text/javascript" src="db_smilAnimateMotion.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=436418">Mozilla Bug 436418</a>
<p id="display"></p>
<div id="content" style="visibility: hidden">
<!-- NOTE: Setting font-size so we can test 'em' units -->
<svg xmlns="http://www.w3.org/2000/svg"
width="200px" height="200px" style="font-size: 500px"
onload="this.pauseAnimations()">
<!-- XXXdholbert Right now, 'em' conversions are correct if we set font-size
on rect using the inline style attr. However, if we use 'font-size' attr,
then 'em' units end up using the inherited font-size instead. Bug? -->
<rect x="20" y="20" width="200" height="200" style="font-size: 10px"/>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
function main()
{
if (!SMILUtil.isSMILEnabled()) {
ok(false, "SMIL dosn't seem to be enabled");
SimpleTest.finish();
return;
}
// Start out with document paused
var svg = SMILUtil.getSVGRoot();
ok(svg.animationsPaused(), "should be paused by <svg> load handler");
is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
var timingData = new SMILTimingData(1.0, 6.0);
testBundleList(gMotionBundles, timingData);
SimpleTest.finish();
}
window.addEventListener("load", main, false);
]]>
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,175 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=436418
-->
<head>
<title>Test for animateMotion acceptance of invalid values</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="smilTestUtils.js" />
<script type="text/javascript" src="smilAnimateMotionValueLists.js" />
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=436418">Mozilla Bug 436418</a>
<p id="display"></p>
<div id="content" style="visibility: hidden">
<svg xmlns="http://www.w3.org/2000/svg" id="svg"
width="200px" height="200px"
onload="this.pauseAnimations()">
<rect id="rect" x="20" y="20" width="200" height="200"/>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
// Constant strings (& string-arrays)
const SVGNS = "http://www.w3.org/2000/svg";
const XLINKNS = "http://www.w3.org/1999/xlink";
// Constant objects
const gSvg = document.getElementById("svg");
const gRect = document.getElementById("rect");
const gUnAnimatedCTM = gRect.getCTM();
SimpleTest.waitForExplicitFinish();
function createAnim()
{
var anim = document.createElementNS(SVGNS, "animateMotion");
anim.setAttribute("dur", "2s");
return gRect.appendChild(anim);
}
function removeElem(aElem)
{
aElem.parentNode.removeChild(aElem);
}
function testAttr(aAttrName, aAttrValueArray, aIsValid, aIsTodo)
{
var componentsToCheck;
for (var i in aAttrValueArray) {
var curVal = aAttrValueArray[i];
var anim = createAnim();
anim.setAttribute(aAttrName, curVal);
if (aAttrName == "rotate") {
// Apply a diagonal translation (so rotate='auto' will have an effect)
// and just test the rotation matrix components
anim.setAttribute("values", "0 0; 50 50");
componentsToCheck = CTMUtil.CTM_COMPONENTS_ROTATE;
} else {
// Apply a supplementary rotation to make sure that we don't apply it if
// our value is rejected.
anim.setAttribute("rotate", Math.PI/4);
componentsToCheck = CTMUtil.CTM_COMPONENTS_ALL;
}
var curCTM = gRect.getCTM();
if (aIsValid) {
var errMsg = "CTM should have changed when applying animateMotion " +
"with '" + aAttrName + "' set to valid value '" + curVal + "'";
CTMUtil.assertCTMNotEqual(curCTM, gUnAnimatedCTM, componentsToCheck,
errMsg, aIsTodo);
} else {
var errMsg = "CTM should not have changed when applying animateMotion " +
"with '" + aAttrName + "' set to invalid value '" + curVal + "'";
CTMUtil.assertCTMEqual(curCTM, gUnAnimatedCTM, componentsToCheck,
errMsg, aIsTodo);
}
removeElem(anim);
}
}
function createPath(aPathDescription)
{
var path = document.createElementNS(SVGNS, "path");
path.setAttribute("d", aPathDescription);
path.setAttribute("id", "thePath");
return gSvg.appendChild(path);
}
function createMpath(aAnimElement)
{
var mpath = document.createElementNS(SVGNS, "mpath");
mpath.setAttributeNS(XLINKNS, "href", "#thePath");
return aAnimElement.appendChild(mpath);
}
function testMpathElem(aPathValueArray, aIsValid, aIsTodo)
{
for (var i in aPathValueArray) {
var curVal = aPathValueArray[i];
var anim = createAnim();
var mpath = createMpath(anim);
var path = createPath(curVal);
// Apply a supplementary rotation to make sure that we don't apply it if
// our value is rejected.
anim.setAttribute("rotate", Math.PI/4);
componentsToCheck = CTMUtil.CTM_COMPONENTS_ALL;
if (aIsValid) {
var errMsg = "CTM should have changed when applying animateMotion " +
"with mpath linking to a path with valid value '" + curVal + "'";
CTMUtil.assertCTMNotEqual(gRect.getCTM(), gUnAnimatedCTM,
componentsToCheck, errMsg, aIsTodo);
} else {
var errMsg = "CTM should not have changed when applying animateMotion " +
"with mpath linking to a path with invalid value '" + curVal + "'";
CTMUtil.assertCTMEqual(gRect.getCTM(), gUnAnimatedCTM,
componentsToCheck, errMsg, aIsTodo);
}
removeElem(anim);
removeElem(path);
removeElem(mpath);
}
}
// Main Function
function main()
{
if (!SMILUtil.isSMILEnabled()) {
ok(false, "SMIL dosn't seem to be enabled");
SimpleTest.finish();
return;
}
// Start out with document paused
var svg = SMILUtil.getSVGRoot();
ok(svg.animationsPaused(), "should be paused by <svg> load handler");
is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
testAttr("values", gValidValues, true, false);
testAttr("values", gInvalidValues, false, false);
testAttr("values", gInvalidValuesTodo, false, true);
testAttr("rotate", gValidRotate, true, false);
testAttr("rotate", gInvalidRotate, false, false);
testAttr("to", gValidToBy, true, false);
testAttr("to", gInvalidToBy, false, false);
testAttr("to", gInvalidToByTodo, false, true);
testAttr("by", gValidToBy, true, false);
testAttr("by", gInvalidToBy, false, false);
testAttr("by", gInvalidToByTodo, false, true);
testAttr("path", gValidPath, true, false);
testAttr("path", gInvalidPath, false, false);
testMpathElem(gValidPath, true, false);
testMpathElem(gInvalidPath, false, false);
SimpleTest.finish();
}
window.addEventListener("load", main, false);
]]>
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,222 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=436418
-->
<head>
<title>Test for overriding of path-defining attributes for animateMotion</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="smilTestUtils.js" />
<script type="text/javascript" src="smilAnimateMotionValueLists.js" />
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=436418">Mozilla Bug 436418</a>
<p id="display"></p>
<div id="content" style="visibility: hidden">
<svg xmlns="http://www.w3.org/2000/svg" id="svg"
width="200px" height="200px"
onload="this.pauseAnimations()">
<!-- Paths for mpath to refer to -->
<path id="validPathElem" d="M10 10 h-10"/>
<path id="invalidPathElem" d="abc"/>
<!-- The rect whose motion is animated -->
<rect id="rect" x="20" y="20" width="200" height="200"/>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
// Constant strings (& string-arrays)
const SVGNS = "http://www.w3.org/2000/svg";
const XLINKNS = "http://www.w3.org/1999/xlink";
// Constant objects
const gSvg = document.getElementById("svg");
const gRect = document.getElementById("rect");
const gUnAnimatedCTM = gRect.getCTM();
// Values for path-defining attributes, and their expected
// CTMs halfway through the animation
var gMpathValidTarget = "#validPathElem";
var gMpathCTM = CTMUtil.generateCTM([ 5, 10, 0 ]);
var gMpathInvalidTargetA = "#invalidPathElem";
var gMpathInvalidTargetB = "#nonExistentElem";
var gInvalidAttrValue = "i-am-invalid"; // Invalid for all tested attributes
var gPathValidValue = "M20 20 h10";
var gPathCTM = CTMUtil.generateCTM([ 25, 20, 0 ]);
var gValuesValidValue = "30 30; 40 30"
var gValuesCTM = CTMUtil.generateCTM([ 35, 30, 0 ]);
var gFromValidValue = "50 50";
var gByValidValue = "10 2";
var gPureByCTM = CTMUtil.generateCTM([ 5, 1, 0 ]);
var gFromByCTM = CTMUtil.generateCTM([ 55, 51, 0 ]);
var gToValidValue = "80 60";
var gPureToCTM = CTMUtil.generateCTM([ 40, 30, 0 ]);
var gFromToCTM = CTMUtil.generateCTM([ 65, 55, 0 ]);
SimpleTest.waitForExplicitFinish();
function createAnim()
{
var anim = document.createElementNS(SVGNS, "animateMotion");
return gRect.appendChild(anim);
}
function removeElem(aElem)
{
aElem.parentNode.removeChild(aElem);
}
function createMpath(aAnimElement, aHrefVal)
{
var mpath = document.createElementNS(SVGNS, "mpath");
mpath.setAttributeNS(XLINKNS, "href", aHrefVal);
return aAnimElement.appendChild(mpath);
}
function runTest() {
// Start out with valid values for all path-defining attributes
var attrSettings = {
"mpath" : gMpathValidTarget,
"path" : gPathValidValue,
"values" : gValuesValidValue,
"from" : gFromValidValue,
"to" : gToValidValue,
"by" : gByValidValue,
};
// Test that <mpath> overrides everything below it
testAttrSettings(attrSettings, gMpathCTM,
"<mpath> should win");
var mpathInvalidTargets = [gMpathInvalidTargetA, gMpathInvalidTargetB];
for (var i in mpathInvalidTargets) {
var curInvalidValue = mpathInvalidTargets[i];
attrSettings["mpath"] = curInvalidValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid <mpath> should block animation");
}
delete attrSettings["mpath"];
// Test that 'path' overrides everything below it
testAttrSettings(attrSettings, gPathCTM,
"'path' should win vs all but mpath");
attrSettings["path"] = gInvalidAttrValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid 'path' should block animation vs all but mpath");
delete attrSettings["path"];
// Test that 'values' overrides everything below it
testAttrSettings(attrSettings, gValuesCTM,
"'values' should win vs from/by/to");
attrSettings["values"] = gInvalidAttrValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid 'values' should block animation vs from/by/to");
delete attrSettings["values"];
// Test that 'from' & 'to' overrides 'by'
testAttrSettings(attrSettings, gFromToCTM,
"'from/to' should win vs 'by'");
attrSettings["to"] = gInvalidAttrValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid 'to' should block animation vs 'by'");
delete attrSettings["to"];
// Test that 'from' & 'by' are effective
testAttrSettings(attrSettings, gFromByCTM,
"'from/by' should be visible");
attrSettings["by"] = gInvalidAttrValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid 'by' should block animation");
delete attrSettings["from"];
// REINSERT "to" & fix up "by" so we can test pure-"to" vs pure-"by"
attrSettings["to"] = gToValidValue;
attrSettings["by"] = gByValidValue;
testAttrSettings(attrSettings, gPureToCTM,
"pure-'to' should be effective & beat pure-'by'");
attrSettings["to"] = gInvalidAttrValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid pure-'to' should block animation vs pure-'by'");
delete attrSettings["to"];
// Test that pure-"by" is effective
testAttrSettings(attrSettings, gPureByCTM,
"pure-by should be visible");
attrSettings["by"] = gInvalidAttrValue;
testAttrSettings(attrSettings, gUnAnimatedCTM,
"invalid 'by' should block animation");
delete attrSettings["by"];
// Make sure that our hash is empty now.
for (var unexpectedKey in attrSettings) {
ok(false, "Unexpected mapping remains in attrSettings: " +
unexpectedKey + "-->" + unexpectedValue);
}
}
function testAttrSettings(aAttrValueHash, aExpectedCTM, aErrMsg)
{
var isDebug = false; // XXdholbert
!isDebug || todo(false, "ENTERING testAttrSettings");
// Set up animateMotion element
var animElement = document.createElementNS(SVGNS, "animateMotion");
animElement.setAttribute("dur", "2s");
for (var attrName in aAttrValueHash) {
!isDebug || todo(false, "setting '" + attrName +"' to '" +
aAttrValueHash[attrName] +"'");
if (attrName == "mpath") {
createMpath(animElement, aAttrValueHash[attrName]);
} else {
animElement.setAttribute(attrName, aAttrValueHash[attrName]);
}
}
gRect.appendChild(animElement);
// Seek to halfway through animation
SMILUtil.getSVGRoot().setCurrentTime(1); // Seek halfway through animation
// Check CTM against expected value
CTMUtil.assertCTMEqual(gRect.getCTM(), aExpectedCTM,
CTMUtil.CTM_COMPONENTS_ALL, aErrMsg, false);
// CLEAN UP
SMILUtil.getSVGRoot().setCurrentTime(0);
removeElem(animElement);
}
// Main Function
function main()
{
if (!SMILUtil.isSMILEnabled()) {
ok(false, "SMIL dosn't seem to be enabled");
SimpleTest.finish();
return;
}
// Start out with document paused
var svg = SMILUtil.getSVGRoot();
ok(svg.animationsPaused(), "should be paused by <svg> load handler");
is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
runTest();
SimpleTest.finish();
}
window.addEventListener("load", main, false);
]]>
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,41 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script type="text/javascript">
function doTest() {
setTimeAndSnapshot(1, true);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<!-- Big green background to match lime.svg -->
<rect width="100%" height="100%" fill="lime"/>
<!-- Red "workspace" (should be covered up, if tests pass) -->
<rect x="100" y="100" width="100" height="100" fill="red"/>
<!-- FIRST ROW -->
<!-- Check that 'by' works at all -->
<rect fill="lime" x="0" y="0" width="50" height="50">
<animateMotion by="100, 100" begin="0" dur="1" fill="freeze"/>
</rect>
<!-- Check that 'by' is additive w/ 'by' -->
<rect fill="lime" x="50" y="50" width="50" height="50">
<animateMotion by="60, 75" begin="0" dur="1" fill="freeze"/>
<animateMotion by="40, -25" begin="0" dur="1" fill="freeze"/>
</rect>
<!-- SECOND ROW -->
<!-- Check that 'by' is additive w/ 'to' -->
<rect fill="lime" width="50" height="50">
<animateMotion to="50,100" begin="0" dur="1" fill="freeze"/>
<animateMotion by="50, 50" begin="0" dur="1" fill="freeze"/>
</rect>
<!-- Check that 'from-to' replaces 'by' -->
<rect fill="lime" width="50" height="50">
<animateMotion by="500, 500" begin="0" dur="1" fill="freeze"/>
<animateMotion from="300,300" to="150,150" begin="0" dur="1" fill="freeze"/>
</rect>
</svg>

После

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

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

@ -0,0 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script type="text/javascript">
function doTest() {
setTimeAndSnapshot(1, true);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<!-- Big green background to match lime.svg -->
<rect width="100%" height="100%" fill="lime"/>
<!-- Red "workspace" (should be covered up, if tests pass) -->
<rect x="100" y="100" width="100" height="100" fill="red"/>
<!-- FIRST ROW -->
<!-- Check that 'from' gets applied at begin time -->
<rect fill="lime" x="0" y="0" width="50" height="50">
<animateMotion from="100, 100" to="500, 500" begin="1" dur="1"/>
</rect>
<!-- Check that 'to' gets hit at end time -->
<rect fill="lime" x="0" y="0" width="50" height="50">
<animateMotion from="200,200" to="150,100" begin="0" dur="1" fill="freeze"/>
</rect>
<!-- SECOND ROW -->
<!-- Check that animation effects are removed after end time
(note that fill="remove" is default; just specifying it for clarity -->
<rect fill="lime" x="100" y="150" width="50" height="50">
<animateMotion from="500,500" to="600,600" begin="0" dur="1" fill="remove"/>
</rect>
<rect fill="purple" x="-25" y="-25" width="25" height="25">
<!-- With the purple rect's x/y offsets, this animateMotion path moves us
around the 2nd row, 1st col -->
<animateMotion from="125,175" to="150,175" begin="0" dur="1" fill="remove"/>
</rect>
<!-- Check interpolation halfway through animation -->
<rect fill="lime" width="50" height="50">
<animateMotion from="200,100" to="100,200" begin="0.5" dur="1"/>
</rect>
</svg>

После

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

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

@ -0,0 +1,151 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<style>
.background { fill: lime }
.workspace { fill: red }
.test { fill: lime }
</style>
<defs>
<!-- 'Dummy' path -->
<path id="moveFarAway" d="M300,300 h0"/>
<path id="moveToUpperLeft" d="M100,100 h0"/>
<path id="pathWhoseDAttrChanges" d="M360,360 h0"/>
<!-- The first of these two elems w/ same ID should be used. -->
<path id="moveToMiddleLeft" d="M100,150 h0"/>
<path id="moveToMiddleLeft" d="M350,350 h0"/>
<!-- The first of these two elems w/ same ID initially wins, but then
it gets removed via script. -->
<path id="moveToMiddleCenter" d="M340,340 h0"/>
<path id="moveToMiddleCenter" d="M150,150 h0"/>
<!-- This elem doesn't do what its id would suggest, but we'll use JS to
add an earlier elem with the same ID that *does* do what it says. -->
<path id="moveToMiddleRight" d="M330,330 h0"/>
<path id="moveToLowerLeft" d="M100,200 h0"/>
<path id="moveToLowerCenter" d="M150,200 h0"/>
</defs>
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script type="text/javascript">
const SVGNS = "http://www.w3.org/2000/svg";
const XLINKNS = "http://www.w3.org/1999/xlink";
function insertPathElem(aPathId, aPathSpec) {
var newPath = document.createElementNS(SVGNS, "path");
newPath.setAttribute("id", aPathId);
newPath.setAttribute("d", aPathSpec);
// Insert new path into defs
var defsElem = document.getElementsByTagName("defs")[0];
defsElem.insertBefore(newPath, defsElem.firstChild);
}
function doTest() {
// Seek already, so we'll have sampled the initial 'stale' state
document.documentElement.setCurrentTime(1);
// Make tweaks
var mpathToModify = document.getElementById("modifyMyTarget");
mpathToModify.setAttributeNS(XLINKNS, "href", "#moveToUpperLeft");
var mpathWhoseHrefNeedsClearing = document.getElementById("unsetMyTarget");
mpathWhoseHrefNeedsClearing.removeAttributeNS(XLINKNS, "href");
var pathToTweak = document.getElementById("pathWhoseDAttrChanges");
pathToTweak.setAttribute("d", "M200 100 h0");
var mpathToDelete = document.getElementById("removeMe");
mpathToDelete.parentNode.removeChild(mpathToDelete);
var pathToDelete = document.getElementById("moveToMiddleCenter");
pathToDelete.parentNode.removeChild(pathToDelete);
insertPathElem("moveToMiddleRight", "M200,150 h0");
insertPathElem("moveToLowerRight", "M200,200 h0");
setTimeAndSnapshot(1, true);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<!-- Big green background to match lime.svg -->
<rect class="background" width="100%" height="100%" />
<!-- Red "workspace" (should be covered up, if tests pass) -->
<rect class="workspace" x="100" y="100" width="150" height="150"/>
<!-- FIRST ROW: Test behavior... -->
<!-- ...when mpath's 'xlink:href' attr is modified. -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath id="modifyMyTarget" xlink:href="#moveFarAway"/>
</animateMotion>
</rect>
<!-- ...when mpath's 'xlink:href' is unset. -->
<rect class="test" x="150" y="100" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath id="unsetMyTarget" xlink:href="#moveFarAway"/>
</animateMotion>
</rect>
<!-- ...when the target-path's "d" attr is modified. -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath xlink:href="#pathWhoseDAttrChanges"/>
</animateMotion>
</rect>
<!-- SECOND ROW: Test behavior... -->
<!-- ...when there are two paths with same ID (first should win) -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath xlink:href="#moveToMiddleLeft"/>
</animateMotion>
</rect>
<!-- ...when there are two paths with same ID, and the first is removed. -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath xlink:href="#moveToMiddleCenter"/>
</animateMotion>
</rect>
<!-- ...when an earlier path is added with our target ID. -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath xlink:href="#moveToMiddleRight"/>
</animateMotion>
</rect>
<!-- THIRD ROW: Test behavior... -->
<!-- ...when there are two mpath children (first should win). -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath xlink:href="#moveToLowerLeft"/>
<mpath xlink:href="#moveFarAway"/>
</animateMotion>
</rect>
<!-- ...when there are two mpath children, and the first is removed. -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath id="removeMe" xlink:href="#moveFarAway"/>
<mpath xlink:href="#moveToLowerCenter"/>
</animateMotion>
</rect>
<!-- ...when there's an mpath child that initially matches nothing, until
a node with the right ID is inserted into the DOM. -->
<rect class="test" x="0" y="0" width="50" height="50">
<animateMotion begin="1" dur="1" fill="freeze">
<mpath xlink:href="#moveToLowerRight"/>
</animateMotion>
</rect>
</svg>

После

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

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

@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<style>
.background { fill: lime }
.workspace { fill: red }
.test { fill: lime }
.filler { fill: lime }
</style>
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script type="text/javascript">
function doTest() {
setTimeAndSnapshot(1, true);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<!-- Big green background to match lime.svg -->
<rect class="background" width="100%" height="100%" />
<!-- Red "workspace" (should be covered up, if tests pass) -->
<rect class="workspace" x="100" y="100" width="100" height="100"/>
<!-- FIRST ROW -->
<!-- Check that 'rotate' gets applied at begin time -->
<g>
<animateMotion from="150, 100" to="500, 500" rotate="90"
begin="1" dur="1"/>
<rect class="test" x="0" y="0" width="20" height="50"/>
<rect class="test" x="0" y="0" width="50" height="20"/>
</g>
<rect class="filler" x="100" y="120" width="30" height="30"/>
<!-- Check that 'rotate' gets applied at end time -->
<g>
<animateMotion from="600, 700" to="200, 150" rotate="180" begin="0"
dur="1" fill="freeze"/>
<rect class="test" x="0" y="0" width="20" height="50"/>
<rect class="test" x="0" y="0" width="50" height="20"/>
</g>
<rect class="filler" x="150" y="100" width="30" height="30"/>
<!-- SECOND ROW -->
<!-- Check that rotate combines with existing rotate -->
<g transform="rotate(90)">
<animateMotion from="150,200" to="600,600" rotate="90"
begin="1" dur="1"/>
<rect class="test" x="0" y="0" width="20" height="50"/>
<rect class="test" x="0" y="0" width="50" height="20"/>
</g>
<rect class="filler" x="100" y="150" width="30" height="30"/>
<!-- Check additivity of <animateMotion> "rotate" adds -->
<g>
<animateMotion from="100,100" to="100,200" rotate="90"
begin="0.5" dur="1"/>
<animateMotion by="100,-200" rotate="90"
begin="0.5" dur="1"/>
<rect class="test" x="0" y="0" width="20" height="50"/>
<rect class="test" x="0" y="0" width="50" height="20"/>
</g>
<rect class="filler" x="150" y="150" width="30" height="30"/>
</svg>

После

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

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

@ -0,0 +1,50 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait">
<!-- Tests for rotate="auto" and "auto-reverse" -->
<!-- The idea here is to create positioned red "holes" in the lime
background, and then hopefully use paused <animateMotion> elements to
position other elements exactly on top of the hole. -->
<style>
.background { fill: lime }
.hole { color: red }
.testBegin { color: purple }
.testEnd { color: orange }
.mask { color: lime }
</style>
<defs>
<!-- A 'pin' marker, just offscreen, pointing directly down at 0,0 -->
<!-- NOTE: The lime 2px-wide stroke is a hack to get around "seams" in
SVG when redrawing the same non-pixel-aligned shape on top of itself
in different colors. -->
<path id="marker" d="m0,0 l-10,-30 c-5,-20 25,-20 20,0 z"
style="fill: currentColor; stroke: lime; stroke-width: 2px"/>
</defs>
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script type="text/javascript">
function doTest() {
setTimeAndSnapshot(1, true);
}
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
<!-- Big green background to match lime.svg -->
<rect class="background" width="100%" height="100%" />
<g transform="translate(50,50)">
<!-- Here's the hole -->
<use xlink:href="#marker" class="hole"
transform="translate(20,20) rotate(45)"/>
<!-- And here's a stack of elements animated with 'animateMotion' that
should end up there. -->
<use xlink:href="#marker" class="testBegin">
<animateMotion from="20,20" to="40,40" rotate="auto" begin="1s" dur="1s"/>
</use>
<use xlink:href="#marker" class="testEnd">
<animateMotion by="20,20" rotate="auto" dur="1s" fill="freeze"/>
</use>
<use xlink:href="#marker" class="mask">
<animateMotion by="40,40" rotate="auto" dur="2s"/>
</use>
</g>
</svg>

После

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

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

@ -0,0 +1,38 @@
<svg xmlns="http://www.w3.org/2000/svg">
<!-- First row -->
<g transform="translate(20,20)">
<g>
<rect width="15px" height="15px"/>
</g>
<g transform="translate(50,0)">
<rect x="0" y="10" width="15px" height="15px"/>
</g>
<g transform="translate(100,0)">
<rect x="9" y="10" width="15px" height="15px"/>
</g>
</g>
<!-- Second row -->
<g transform="translate(20,70)">
<g>
<rect x="22.5" y="10" width="15px" height="15px"/>
</g>
<g transform="translate(50,0)">
<rect x="29.7" y="10" width="15px" height="15px"/>
</g>
<g transform="translate(100,0)">
<rect x="45" y="30" width="15px" height="15px"/>
</g>
</g>
<!-- Third row -->
<g transform="translate(20,120)">
<g>
<rect x="48" y="34" width="15px" height="15px"/>
</g>
<g transform="translate(50,0)">
<rect x="60" y="50" width="15px" height="15px"/>
</g>
<g transform="translate(100,0)">
<rect x="60" y="50" width="15px" height="15px"/>
</g>
</g>
</svg>

После

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

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

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="go()">
<!-- Tests for <animateMotion> with 'values' attribute -->
<script xlink:href="../smil-grid.js" type="text/javascript"/>
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script>
function go() {
var animAttrHash = { "values" : "0,10; 30,10; 60,50",
"calcMode" : "linear" };
testAnimatedRectGrid("animateMotion", [animAttrHash]);
}
</script>
</svg>

После

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

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

@ -0,0 +1,38 @@
<svg xmlns="http://www.w3.org/2000/svg">
<!-- First row -->
<g transform="translate(20,20)">
<g>
<rect width="15px" height="15px"/>
</g>
<g transform="translate(50,0)">
<rect x="0" y="10" width="15px" height="15px"/>
</g>
<g transform="translate(100,0)">
<rect x="12" y="10" width="15px" height="15px"/>
</g>
</g>
<!-- Second row -->
<g transform="translate(20,70)">
<g>
<rect x="30" y="10" width="15px" height="15px"/>
</g>
<g transform="translate(50,0)">
<rect x="35.76" y="17.68" width="15px" height="15px"/>
</g>
<g transform="translate(100,0)">
<rect x="48" y="34" width="15px" height="15px"/>
</g>
</g>
<!-- Third row -->
<g transform="translate(20,120)">
<g>
<rect x="50.4" y="37.2" width="15px" height="15px"/>
</g>
<g transform="translate(50,0)">
<rect x="60" y="50" width="15px" height="15px"/>
</g>
<g transform="translate(100,0)">
<rect x="60" y="50" width="15px" height="15px"/>
</g>
</g>
</svg>

После

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

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

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="go()">
<!-- Tests for <animateMotion> with 'values' attribute -->
<script xlink:href="../smil-grid.js" type="text/javascript"/>
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script>
function go() {
var animAttrHash = { "values" : "0,10; 30,10; 60,50"};
testAnimatedRectGrid("animateMotion", [animAttrHash]);
}
</script>
</svg>

После

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

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

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="go()">
<!-- Tests for <animateMotion> with 'values' attribute -->
<script xlink:href="../smil-grid.js" type="text/javascript"/>
<script xlink:href="../smil-util.js" type="text/javascript"/>
<script>
function go() {
var animAttrHash = { "values" : "0,10; 30,10; 60,50",
"calcMode" : "paced" };
testAnimatedRectGrid("animateMotion", [animAttrHash]);
}
</script>
</svg>

После

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

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

@ -0,0 +1,8 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<title>Testcase reference file for generic pass condition</title>
<rect width="100%" height="100%" fill="lime"/>
</svg>

После

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

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

@ -0,0 +1,13 @@
# Tests related to SVG Animation (using SMIL), focusing on the animateMotion
# element.
== animateMotion-by-1.svg lime.svg
== animateMotion-from-to-1.svg lime.svg
== animateMotion-rotate-1.svg lime.svg
== animateMotion-rotate-2.svg lime.svg
== animateMotion-values-linear-1.svg animateMotion-values-linear-1-ref.svg
== animateMotion-values-paced-1a.svg animateMotion-values-paced-1-ref.svg
== animateMotion-values-paced-1b.svg animateMotion-values-paced-1-ref.svg
# Tests involving <mpath> sub-element
== animateMotion-mpath-targetChange-1.svg lime.svg