summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js')
-rw-r--r--testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js193
1 files changed, 193 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js b/testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js
new file mode 100644
index 0000000000..d79cbedefe
--- /dev/null
+++ b/testing/web-platform/tests/css/css-transforms/animation/support/transform-interpolation-reftests.js
@@ -0,0 +1,193 @@
+'use strict';
+
+// Each test is an array of [endpoint, midpoint, endpoint] and tests
+// whether the endpoints interpolate to the same visual state as the midpoint
+const transformTests = {
+ translate: [
+ ['translateX(0px)', 'translateX(25px)', 'translateX(50px)'],
+ ['translateY(0px)', 'translateY(25px)', 'translateY(50px)'],
+ ['translateX(0%)', 'translateX(25%)', 'translateX(50%)'],
+ ['translateY(0%)', 'translateY(25%)', 'translateY(50%)'],
+ ['translateX(50%)', 'translate(25%, 25%)', 'translateY(50%)'],
+ ['translateX(50%)', 'translate(25%, 25px)', 'translateY(50px)'],
+ ['translateX(50px)', 'translateX(calc(25px + 25%))', 'translateX(50%)']
+ ],
+ translateEm: [
+ ['translateX(0em)', 'translateX(2em)', 'translateX(4em)'],
+ ['translateX(-50px)', 'translateX(calc(2em - 25px))', 'translateX(4em)'],
+ ['translateX(50%)', 'translateX(calc(25% - 2em))', 'translateX(-4em)']
+ ],
+ rotate: [
+ // Rotation about named-axis.
+ ['rotate(30deg)', 'rotate(60deg)', 'rotate(90deg)'],
+ ['rotateX(30deg)', 'rotateX(60deg)', 'rotateX(90deg)'],
+ ['rotateY(30deg)', 'rotateY(60deg)', 'rotateY(90deg)'],
+ ['rotate(30deg)', 'rotate(60deg)', 'rotateZ(90deg)'],
+ ['rotate(0deg)', 'rotate(180deg)', 'rotate(360deg)'],
+ // Common axis rotations.
+ ['rotate3d(7, 8, 9, 0deg)', 'rotate3d(7, 8, 9, 45deg)', 'rotate3d(7, 8, 9, 90deg)'],
+ ['rotate3d(1, 2, 3, 0deg)', 'rotate3d(3, 6, 9, 45deg)', 'rotate3d(2, 4, 6, 90deg)'],
+ // Axis is arbitrary if angle is zero. Use non-zero rotation to determine
+ // the rotation axis.
+ ['rotateX(0deg)', 'rotate(45deg)', 'rotate(90deg)'],
+ ['rotateX(90deg)', 'rotateX(45deg)', 'rotate(0deg)']
+ ],
+ rotateSlerp: [
+ // First endpoint is the same rotation as rotateZ(0deg) but triggers SLERP
+ ['rotateX(360deg)', 'rotateZ(45deg)', 'rotateZ(90deg)'],
+ // Interpolation with inverse. Second case is a common-axis case, but
+ // included here to group it with its equivalent SLERP test.
+ ['rotate(45deg)', 'rotate(0deg)', 'rotate3d(0, 0, -1, 45deg)'],
+ ['rotate(45deg)', 'rotate(0deg)', 'rotate(-45deg)'],
+ // Interpolate axis and angle of rotation.
+ // 70.5288deg = acos(1/3).
+ ['rotateX(90deg)', 'rotate3d(1, 1, 0, 70.5288deg)', 'rotateY(90deg)'],
+ // Not nice analytical solution for this last one.
+ // (1, 1, 0, 90deg) --> (x, y, z, w) = (1/2, 1/2, 0, 1/root2)
+ // (0, 1, 1, 180deg) --> (x, y, z, w) = (0, 1/root2, 1/root2, 0)
+ // Trace of the "to" transformation matrix is -1. Requires special handling
+ // to ensure correctness of the quaternion.
+ // SLERP @0.5: (x, y, z, w) = (0.30389062997686395,
+ // 0.7336568918027127,
+ // 0.4297662618258487,
+ // 0.4297662618258487)
+ // --> rotate3d(0.3365568, 0.8125199, 0.4759632, 129.094547486deg)
+ ['rotate3d(1, 1, 0, 90deg)',
+ 'rotate3d(0.3365568, 0.8125199, 0.4759632, 129.094547486deg)',
+ 'rotate3d(0, 1, 1, 180deg)'],
+ ],
+ scale: [
+ ['scaleX(0.5)', 'scaleX(0.75)', 'scaleX(1)'],
+ ['scaleY(0.5)', 'scaleY(0.75)', 'scaleY(1)'],
+ ['scale(0.5)', 'scale(0.75)', 'scale(1)'],
+ ['scaleX(0.5)', 'scale(0.75)', 'scaleY(0.5)'],
+ ['scale3d(0.5, 1, 2)', 'scale3d(0.75, 0.75, 3)', 'scale3d(1, 0.5, 4)']
+ ],
+ skew: [
+ ['skewX(0deg)', 'skewX(30deg)', 'skewX(60deg)'],
+ ['skewY(0deg)', 'skewY(30deg)', 'skewY(60deg)'],
+ ['skew(60deg, 0deg)', 'skew(30deg, 30deg)', 'skew(0deg, 60deg)'],
+ ['skewX(0deg) rotate(0deg)', 'skewX(0deg) rotate(180deg)', 'skewX(0deg) rotate(360deg)'],
+ ['skewX(0deg) rotate(0deg)', 'matrix(1, 0, 0, 1, 0, 0)', 'skewY(0deg) rotate(360deg)']
+ ],
+ matrix: [
+ // matched matrix parameters do not collapse the values after them
+ ['matrix(1,0,0,1,0,0) rotate(0deg)', 'matrix(1.5,0,0,1.5,0,0) rotate(180deg)', 'matrix(2,0,0,2,0,0) rotate(360deg)']
+ ],
+ perspective: [
+ // Since perspective doesn't do anything on its own, we need to
+ // combine it with a transform that does.
+ ['perspective(none) translateZ(15px)', 'perspective(none) translateZ(15px)', 'perspective(none) translateZ(15px)'],
+ ['perspective(100px) translateZ(50px)', 'perspective(200px) translateZ(50px)', 'perspective(none) translateZ(50px)'],
+ ['perspective(none) translateZ(15px)', 'perspective(50px) translateZ(15px)', 'perspective(25px) translateZ(15px)'],
+ ['perspective(100px) translateZ(15px)', 'perspective(40px) translateZ(15px)', 'perspective(25px) translateZ(15px)'],
+
+ // Test that perspective is clamped to 1px.
+ ['perspective(0.1px) translateZ(0.25px)', 'perspective(1px) translateZ(0.25px)', 'perspective(0.1px) translateZ(0.25px)'],
+ ['perspective(0px) translateZ(0.25px)', 'perspective(1px) translateZ(0.25px)', 'perspective(0px) translateZ(0.25px)'],
+ ['perspective(0px) translateZ(0.5px)', 'perspective(1.5px) translateZ(0.5px)', 'perspective(3px) translateZ(0.5px)'],
+ { test: ['perspective(10px) translateZ(0.5px)', 'translateZ(0.5px)', 'perspective(1px) translateZ(0.5px)'], midpoint: -1 },
+ { test: ['perspective(1px) translateZ(0.5px)', 'perspective(1px) translateZ(0.5px)', 'perspective(10px) translateZ(0.5px)'], midpoint: -1 }
+ ]
+};
+
+// Initial setup, which includes properties that will be overridden to
+// test invalidation.
+function initialStyle(div) {
+ div.style.width = '180px';
+ div.style.height = '150px';
+ div.style.margin = '50px';
+ div.style.borderLeft = 'solid 40px blue';
+ div.style.backgroundColor = 'green';
+ div.style.willChange = 'transform';
+ div.style.fontSize = '30px';
+}
+
+function finalStyle(div) {
+ div.style.width = '80px';
+ div.style.height = '80px';
+ div.style.fontSize = '15px';
+}
+
+function styleBody(){
+ let body = document.body;
+ body.style.display = 'flex';
+ body.style.flexDirection = 'row';
+ body.style.flexWrap = 'wrap';
+}
+
+// Simulate a static image at 50% progress with a running animation.
+// The easing curve has zero slope and curvature at its midpoint of 50% -> 50%.
+// The timing values are chosen so as so that a delay of up to 10s will not
+// cause a visual change.
+const duration = 1e9;
+const midpointOptions = {
+ easing: 'cubic-bezier(0,1,1,0)',
+ duration: duration,
+ delay: -duration/2
+};
+
+// Similar to midpointOptions, but to produce the interpolation result
+// at -1 instead of the interpolation result at 0.5. This easing curve
+// has zero slope at its midpoint of -100% (though does have curvature).
+const negoneOptions = {
+ easing: 'cubic-bezier(0,-1,1,-2)',
+ duration: duration,
+ delay: -duration/2
+};
+
+// Indices to unpack a test case, which is in the format
+// [start, midpoint, end]
+const startIndex = 0;
+const midIndex = 1;
+const endIndex = 2;
+
+async function createTests(tests) {
+ styleBody();
+ for (const obj of tests) {
+ let test = ("test" in obj) ? obj.test : obj;
+ let midpoint = ("midpoint" in obj) ? obj.midpoint : 0.5;
+ let options;
+ if (midpoint == 0.5) {
+ options = midpointOptions;
+ } else if (midpoint == -1) {
+ options = negoneOptions;
+ } else {
+ document.appendChild(document.createTextNode("unexpected midpoint " + midpoint));
+ }
+ let div = document.createElement('div');
+ document.body.appendChild(div);
+ initialStyle(div);
+ var anim =
+ div.animate({transform: [test[startIndex], test[endIndex]]}, options);
+ await anim.ready;
+ finalStyle(div); // Change size to test invalidation.
+ }
+
+ await new Promise(requestAnimationFrame);
+ await new Promise(requestAnimationFrame);
+ takeScreenshot();
+}
+
+// Create references using an animation with identical keyframes for start
+// and end so as to avoid rounding and anti-aliasing differences between
+// animated and non-animated pathways.
+async function createRefs(tests) {
+ styleBody();
+ for (const obj of tests) {
+ let test = ("test" in obj) ? obj.test : obj;
+ let div = document.createElement('div');
+ document.body.appendChild(div);
+ initialStyle(div);
+ finalStyle(div);
+ var anim = div.animate(
+ {transform: [test[midIndex], test[midIndex]]},
+ midpointOptions);
+ await anim.ready;
+ }
+
+ await new Promise(requestAnimationFrame);
+ await new Promise(requestAnimationFrame);
+ takeScreenshot();
+}
+