summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-masking/animations
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-masking/animations
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-masking/animations')
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/clip-interpolation.html117
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/clip-path-composition.html189
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-001.html141
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-002.html221
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-shape.html170
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-xywh-rect.html169
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/mask-image-interpolation.html110
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/mask-no-interpolation.html17
-rw-r--r--testing/web-platform/tests/css/css-masking/animations/mask-position-interpolation.html146
9 files changed, 1280 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-masking/animations/clip-interpolation.html b/testing/web-platform/tests/css/css-masking/animations/clip-interpolation.html
new file mode 100644
index 0000000000..322ebd724e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/clip-interpolation.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>clip interpolation</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#clip-property">
+<meta name="assert" content="clip supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.container {
+ width: 80px;
+ height: 80px;
+ background: black;
+ display: inline-block;
+ padding: 5px;
+}
+
+.container:nth-child(2n) {
+ background: green;
+}
+
+.parent {
+ clip: rect(100px, 0px, 100px, 0px);
+}
+
+.target {
+ width: 80px;
+ height: 80px;
+ display: inline-block;
+ position: absolute;
+ background: white;
+ clip: rect(0px, 100px, 0px, 100px);
+}
+</style>
+
+<body>
+<template id="target-template">
+<div class="container"><div class="target"></div></div>
+</template>
+<script>
+test_interpolation({
+ property: 'clip',
+ from: neutralKeyframe,
+ to: 'rect(20px, 20px, 20px, 20px)',
+}, [
+ {at: -1, expect: 'rect(-20px 180px -20px 180px)'},
+ {at: 0, expect: 'rect(0px 100px 0px 100px)'},
+ {at: 0.25, expect: 'rect(5px 80px 5px 80px)'},
+ {at: 0.75, expect: 'rect(15px 40px 15px 40px)'},
+ {at: 1, expect: 'rect(20px 20px 20px 20px)'},
+ {at: 2, expect: 'rect(40px -60px 40px -60px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'initial',
+ to: 'rect(20px, 20px, 20px, 20px)',
+});
+
+test_interpolation({
+ property: 'clip',
+ from: 'inherit',
+ to: 'rect(20px, 20px, 20px, 20px)',
+}, [
+ {at: -1, expect: 'rect(180px -20px 180px -20px)'},
+ {at: 0, expect: 'rect(100px 0px 100px 0px)'},
+ {at: 0.25, expect: 'rect(80px 5px 80px 5px)'},
+ {at: 0.75, expect: 'rect(40px 15px 40px 15px)'},
+ {at: 1, expect: 'rect(20px 20px 20px 20px)'},
+ {at: 2, expect: 'rect(-60px 40px -60px 40px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'unset',
+ to: 'rect(20px, 20px, 20px, 20px)',
+});
+
+test_interpolation({
+ property: 'clip',
+ from: 'rect(0px, 75px, 80px, 10px)',
+ to: 'rect(0px, 100px, 90px, 5px)'
+}, [
+ {at: -1, expect: 'rect(0px, 50px, 70px, 15px)'},
+ {at: 0, expect: 'rect(0px, 75px, 80px, 10px)'},
+ {at: 0.25, expect: 'rect(0px, 81.25px, 82.5px, 8.75px)'},
+ {at: 0.75, expect: 'rect(0px, 93.75px, 87.5px, 6.25px)'},
+ {at: 1, expect: 'rect(0px, 100px, 90px, 5px)'},
+ {at: 2, expect: 'rect(0px, 125px, 100px, 0px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'rect(auto, auto, auto, 10px)',
+ to: 'rect(20px, 50px, 50px, auto)'
+});
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'rect(auto, 0px, auto, 10px)',
+ to: 'rect(auto, 50px, 50px, auto)'
+});
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'auto',
+ to: 'rect(0px, 50px, 50px, 0px)'
+});
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'rect(0px, 50px, 50px, 0px)',
+ to: 'auto'
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-masking/animations/clip-path-composition.html b/testing/web-platform/tests/css/css-masking/animations/clip-path-composition.html
new file mode 100644
index 0000000000..42c5988e04
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/clip-path-composition.html
@@ -0,0 +1,189 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>clip-path composition</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-clip-path">
+<meta name="assert" content="clip-path supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<body>
+<script>
+test_composition({
+ property: 'clip-path',
+ underlying: 'circle(100px at 25px 25%)',
+ addFrom: 'circle(10px at 25px 75%)',
+ addTo: 'circle(50px at 50px center)',
+}, [
+ {at: -0.3, expect: 'circle(98px at 42.5px 107.5%)'},
+ {at: 0, expect: 'circle(110px at 50px 100%)'},
+ {at: 0.3, expect: 'circle(122px at 57.5px 92.5%)'},
+ {at: 0.6, expect: 'circle(134px at 65px 85%)'},
+ {at: 1, expect: 'circle(150px at 75px 75%)'},
+ {at: 1.5, expect: 'circle(170px at 87.5px 62.5%)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'circle(100px at 20px 20%)',
+ addFrom: 'circle(50px at 50px 50%)',
+ replaceTo: 'circle(50% at 150px 150%)',
+}, [
+ {at: -0.3, expect: 'circle(calc(195px + -15%) at 46px 46%)'},
+ {at: 0, expect: 'circle(calc(150px + 0%) at 70px 70%)'},
+ {at: 0.3, expect: 'circle(calc(105px + 15%) at 94px 94%)'},
+ {at: 0.6, expect: 'circle(calc(60px + 30%) at 118px 118%)'},
+ {at: 1, expect: 'circle(50% at 150px 150%)'},
+ {at: 1.5, expect: 'circle(calc(-75px + 75%) at 190px 190%)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'circle(farthest-side at 25px 75%)',
+ addFrom: 'circle(farthest-side at 25px 75%)',
+ addTo: 'circle(farthest-side at 50px center)',
+}, [
+ {at: 0.25, expect: 'circle(farthest-side at 25px 75%)'},
+ {at: 0.75, expect: 'circle(farthest-side at 50px 50%)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'circle(50px at 10px 20px)',
+ addFrom: 'circle(50px at 10px 20px)',
+ addTo: 'circle(farthest-side at 30px 40px)',
+}, [
+ {at: 0.25, expect: 'circle(100px at 20px 40px)'},
+ {at: 0.75, expect: 'circle(farthest-side at 30px 40px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'ellipse(10px 20px at 30px 40px)',
+ addFrom: 'ellipse(40px 30px at 20px 10px)',
+ addTo: 'ellipse(140px 130px at 120px 110px)',
+}, [
+ {at: -0.3, expect: 'ellipse(20px 20px at 20px 20px)'},
+ {at: 0, expect: 'ellipse(50px 50px at 50px 50px)'},
+ {at: 0.3, expect: 'ellipse(80px 80px at 80px 80px)'},
+ {at: 0.6, expect: 'ellipse(110px 110px at 110px 110px)'},
+ {at: 1, expect: 'ellipse(150px 150px at 150px 150px)'},
+ {at: 1.5, expect: 'ellipse(200px 200px at 200px 200px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'ellipse(10px 20px at 30px 40px)',
+ replaceFrom: 'ellipse(40px 30px at 20px 10px)',
+ addTo: 'ellipse(40px 30px at 20px 10px)',
+}, [
+ {at: -0.3, expect: 'ellipse(37px 24px at 11px -2px)'},
+ {at: 0, expect: 'ellipse(40px 30px at 20px 10px)'},
+ {at: 0.3, expect: 'ellipse(43px 36px at 29px 22px)'},
+ {at: 0.6, expect: 'ellipse(46px 42px at 38px 34px)'},
+ {at: 1, expect: 'ellipse(50px 50px at 50px 50px)'},
+ {at: 1.5, expect: 'ellipse(55px 60px at 65px 70px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'ellipse(25px 75%)',
+ addFrom: 'ellipse()',
+ addTo: 'ellipse(closest-side farthest-side)',
+}, [
+ {at: 0.25, expect: 'ellipse()'},
+ {at: 0.75, expect: 'ellipse(closest-side farthest-side)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'inset(20px)',
+ addFrom: 'inset(20px)',
+ addTo: 'inset(40%)',
+}, [
+ {at: -0.3, expect: 'inset(calc(46px + -12%))'},
+ {at: 0, expect: 'inset(calc(40px + 0%))'},
+ {at: 0.3, expect: 'inset(calc(34px + 12%))'},
+ {at: 0.6, expect: 'inset(calc(28px + 24%))'},
+ {at: 1, expect: 'inset(calc(20px + 40%))'},
+ {at: 1.5, expect: 'inset(calc(10px + 60%))'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)',
+ addFrom: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)',
+ replaceTo: 'inset(102px 104px 106px 108px round 120px 140px 160px 180px / 200px 220px 240px 260px)',
+}, [
+ {at: -0.3, expect: 'inset(-28px -26px -24px -22px round 0px 10px 30px 50px / 70px 90px 110px 130px)'},
+ {at: 0, expect: 'inset(2px 4px 6px 8px round 20px 40px 60px 80px / 100px 120px 140px 160px)'},
+ {at: 0.25, expect: 'inset(27px 29px 31px 33px round 45px 65px 85px 105px / 125px 145px 165px 185px)'},
+ {at: 0.75, expect: 'inset(77px 79px 81px 83px round 95px 115px 135px 155px / 175px 195px 215px 235px)'},
+ {at: 1, expect: 'inset(102px 104px 106px 108px round 120px 140px 160px 180px / 200px 220px 240px 260px)'},
+ {at: 1.5, expect: 'inset(152px 154px 156px 158px round 170px 190px 210px 230px / 250px 270px 290px 310px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'inset(1px 2px round 100px 200px)',
+ addFrom: 'inset(1px 2px round 100px 200px)',
+ addTo: 'inset(101px 102px 101px 102px)',
+}, [
+ {at: -0.3, expect: 'inset(-28px -26px round 230px 460px)'},
+ {at: 0, expect: 'inset(2px 4px round 200px 400px)'},
+ {at: 0.3, expect: 'inset(32px 34px round 170px 340px)'},
+ {at: 0.6, expect: 'inset(62px 64px round 140px 280px)'},
+ {at: 1, expect: 'inset(102px 104px round 100px 200px)'},
+ {at: 1.5, expect: 'inset(152px 154px round 50px 100px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'polygon(10px 20%, 30px 40%)',
+ addFrom: 'polygon(10px 20%, 30px 40%)',
+ addTo: 'polygon(110px 120%, 130px 140%)',
+}, [
+ {at: -0.3, expect: 'polygon(-10px 10%, 30px 50%)'},
+ {at: 0, expect: 'polygon(20px 40%, 60px 80%)'},
+ {at: 0.3, expect: 'polygon(50px 70%, 90px 110%)'},
+ {at: 0.6, expect: 'polygon(80px 100%, 120px 140%)'},
+ {at: 1, expect: 'polygon(120px 140%, 160px 180%)'},
+ {at: 1.5, expect: 'polygon(170px 190%, 210px 230%)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'polygon(evenodd, 10px 20px)',
+ addFrom: 'polygon(evenodd, 10px 20px)',
+ addTo: 'polygon(evenodd, 110px 120px)',
+}, [
+ {at: -0.3, expect: 'polygon(evenodd, -10px 10px)'},
+ {at: 0, expect: 'polygon(evenodd, 20px 40px)'},
+ {at: 0.3, expect: 'polygon(evenodd, 50px 70px)'},
+ {at: 0.6, expect: 'polygon(evenodd, 80px 100px)'},
+ {at: 1, expect: 'polygon(evenodd, 120px 140px)'},
+ {at: 1.5, expect: 'polygon(evenodd, 170px 190px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'polygon(evenodd, 10px 20px)',
+ addFrom: 'polygon(evenodd, 10px 20px)',
+ addTo: 'polygon(nonzero, 30px 40px)',
+}, [
+ {at: 0.25, expect: 'polygon(evenodd, 20px 40px)'},
+ {at: 0.75, expect: 'polygon(30px 40px)'},
+]);
+
+test_composition({
+ property: 'clip-path',
+ underlying: 'polygon(10px 20px, 30px 40px)',
+ addFrom: 'polygon(10px 20px, 30px 40px)',
+ addTo: 'polygon(30px 40px)',
+}, [
+ {at: 0.25, expect: 'polygon(20px 40px, 60px 80px)'},
+ {at: 0.75, expect: 'polygon(30px 40px)'},
+]);
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-001.html b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-001.html
new file mode 100644
index 0000000000..21c34f1f2b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-001.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>clip-path interpolation</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-clip-path">
+<meta name="assert" content="clip-path supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.parent {
+ clip-path: circle(80% at 30% 10%);
+}
+
+.target {
+ clip-path: circle(60% at 10% 30%);
+}
+</style>
+<body>
+<script>
+test_interpolation({
+ property: 'clip-path',
+ from: neutralKeyframe,
+ to: 'circle(40% at 20% 20%)',
+}, [
+ {at: -0.3, expect: 'circle(66% at 7% 33%)'},
+ {at: 0, expect: 'circle(60% at 10% 30%)'},
+ {at: 0.3, expect: 'circle(54% at 13% 27%)'},
+ {at: 0.6, expect: 'circle(48% at 16% 24%)'},
+ {at: 1, expect: 'circle(40% at 20% 20%)'},
+ {at: 1.5, expect: 'circle(30% at 25% 15%)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'initial',
+ to: 'circle(40% at 20% 20%)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inherit',
+ to: 'circle(40% at 20% 20%)',
+}, [
+ {at: -0.3, expect: 'circle(92% at 33% 7%)'},
+ {at: 0, expect: 'circle(80% at 30% 10%)'},
+ {at: 0.3, expect: 'circle(68% at 27% 13%)'},
+ {at: 0.6, expect: 'circle(56% at 24% 16%)'},
+ {at: 1, expect: 'circle(40% at 20% 20%)'},
+ {at: 1.5, expect: 'circle(20% at 15% 25%)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'unset',
+ to: 'circle(40% at 20% 20%)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'circle(100% at 0% 0%)',
+ to: 'circle(50% at 25% 25%)',
+}, [
+ {at: -0.3, expect: 'circle(115% at -7.5% -7.5%)'},
+ {at: 0, expect: 'circle(100% at 0% 0%)'},
+ {at: 0.3, expect: 'circle(85% at 7.5% 7.5%)'},
+ {at: 0.6, expect: 'circle(70% at 15% 15%)'},
+ {at: 1, expect: 'circle(50% at 25% 25%)'},
+ {at: 1.5, expect: 'circle(25% at 37.5% 37.5%)'}
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'ellipse(100% 100% at 0% 0%)',
+ to: 'ellipse(50% 50% at 25% 25%)',
+}, [
+ {at: -0.3, expect: 'ellipse(115% 115% at -7.5% -7.5%)'},
+ {at: 0, expect: 'ellipse(100% 100% at 0% 0%)'},
+ {at: 0.3, expect: 'ellipse(85% 85% at 7.5% 7.5%)'},
+ {at: 0.6, expect: 'ellipse(70% 70% at 15% 15%)'},
+ {at: 1, expect: 'ellipse(50% 50% at 25% 25%)'},
+ {at: 1.5, expect: 'ellipse(25% 25% at 37.5% 37.5%)'}
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'polygon(nonzero, 0px 0px, 25px 25px, 50px 50px)',
+ to: 'polygon(nonzero, 25px 25px, 50px 50px, 75px 75px)',
+}, [
+ {at: -0.3, expect: 'polygon(nonzero, -7.5px -7.5px, 17.5px 17.5px, 42.5px 42.5px)'},
+ {at: 0, expect: 'polygon(nonzero, 0px 0px, 25px 25px, 50px 50px)'},
+ {at: 0.3, expect: 'polygon(nonzero, 7.5px 7.5px, 32.5px 32.5px, 57.5px 57.5px)'},
+ {at: 0.6, expect: 'polygon(nonzero, 15px 15px, 40px 40px, 65px 65px)'},
+ {at: 1, expect: 'polygon(nonzero, 25px 25px, 50px 50px, 75px 75px)'},
+ {at: 1.5, expect: 'polygon(nonzero, 37.5px 37.5px, 62.5px 62.5px, 87.5px 87.5px)'}
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'polygon(evenodd, 0px 0px, 25px 25px, 50px 50px)',
+ to: 'polygon(nonzero, 25px 25px, 50px 50px, 75px 75px)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inset(100%)',
+ to: 'inset(120%)',
+}, [
+ {at: -0.3, expect: 'inset(94%)'},
+ {at: 0, expect: 'inset(100%)'},
+ {at: 0.3, expect: 'inset(106%)'},
+ {at: 0.6, expect: 'inset(112%)'},
+ {at: 1, expect: 'inset(120%)'},
+ {at: 1.5, expect: 'inset(130%)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'none',
+ to: 'ellipse(100% 100% at 0% 0%)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'circle(25% at right 5% bottom 15px)',
+ to: 'circle(45% at right 25% bottom 35px)',
+}, [
+ {at: 0.25, expect: 'circle(30% at 90% calc(-20px + 100%))'},
+ {at: 0.5, expect: 'circle(35% at 85% calc(-25px + 100%))'},
+ {at: 0.75, expect: 'circle(40% at 80% calc(-30px + 100%))'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'url("/clip-source")',
+ to: 'ellipse(100% 100% at 0% 0%)',
+});
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-002.html b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-002.html
new file mode 100644
index 0000000000..88e34b3864
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-002.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<meta charset="UTF-8">
+<title>clip-path-interpolation</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-clip-path">
+<meta name="assert" content="clip-path supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.parent {
+ clip-path: inset(10px);
+ padding: 10px;
+}
+
+.target {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ background-color: black;
+ clip-path: inset(10px);
+}
+
+.expected {
+ background-color: green;
+}
+</style>
+<body>
+<script>
+test_interpolation({
+ property: 'clip-path',
+ from: neutralKeyframe,
+ to: 'inset(20px)',
+}, [
+ {at: -0.3, expect: 'inset(7px)'},
+ {at: 0, expect: 'inset(10px)'},
+ {at: 0.3, expect: 'inset(13px)'},
+ {at: 0.6, expect: 'inset(16px)'},
+ {at: 1, expect: 'inset(20px)'},
+ {at: 1.5, expect: 'inset(25px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'initial',
+ to: 'inset(20px)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inherit',
+ to: 'inset(20px)',
+}, [
+ {at: -0.3, expect: 'inset(7px)'},
+ {at: 0, expect: 'inset(10px)'},
+ {at: 0.3, expect: 'inset(13px)'},
+ {at: 0.6, expect: 'inset(16px)'},
+ {at: 1, expect: 'inset(20px)'},
+ {at: 1.5, expect: 'inset(25px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'unset',
+ to: 'inset(20px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'none',
+ to: 'circle(3px at 1px 2px)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'circle(10px at 25px 75%)',
+ to: 'circle(50px at 50px center)'
+}, [
+ {at: -0.3, expect: 'circle(0px at 17.5px 82.5%)'}, // radius can't be negative
+ {at: 0, expect: 'circle(10px at 25px 75%)'},
+ {at: 0.3, expect: 'circle(22px at 32.5px 67.5%)'},
+ {at: 0.6, expect: 'circle(34px at 40px 60%)'},
+ {at: 1, expect: 'circle(50px at 50px 50%)'},
+ {at: 1.5, expect: 'circle(70px at 62.5px 37.5%)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'circle(farthest-side at 25px 75%)',
+ to: 'circle(farthest-side at 50px center)'
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'circle(closest-side at 10px 20px)',
+ to: 'circle(farthest-side at 30px 40px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'circle(50px at 10px 20px)',
+ to: 'circle(farthest-side at 30px 40px)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'ellipse(10px 20px at 25px 75px)',
+ to: 'ellipse(50px 100px at 50px 50px)',
+}, [
+ {at: -0.3, expect: 'ellipse(0px 0px at 17.5px 82.5px)'}, // radius can't be negative
+ {at: 0, expect: 'ellipse(10px 20px at 25px 75px)'},
+ {at: 0.3, expect: 'ellipse(22px 44px at 32.5px 67.5px)'},
+ {at: 0.6, expect: 'ellipse(34px 68px at 40px 60px)'},
+ {at: 1, expect: 'ellipse(50px 100px at 50px 50px)'},
+ {at: 1.5, expect: 'ellipse(70px 140px at 62.5px 37.5px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'ellipse(closest-side farthest-side at 25px 75%)',
+ to: 'ellipse(closest-side farthest-side at 50px center)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'ellipse(closest-side farthest-side at 10px 20px)',
+ to: 'ellipse(farthest-side closest-side at 30px 40px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'ellipse(50px closest-side at 10px 20px)',
+ to: 'ellipse(150px farthest-side at 30px 40px)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inset(20px)',
+ to: 'inset(40%)',
+}, [
+ {at: -0.3, expect: 'inset(calc(26px + -12%))'},
+ {at: 0, expect: 'inset(calc(20px + 0%))'},
+ {at: 0.3, expect: 'inset(calc(14px + 12%))'},
+ {at: 0.6, expect: 'inset(calc(8px + 24%))'},
+ {at: 1, expect: 'inset(40%)'},
+ {at: 1.5, expect: 'inset(calc(-10px + 60%))'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)',
+ to: 'inset(101px 102px 103px 104px round 110px 120px 130px 140px / 150px 160px 170px 180px)',
+}, [
+ {at: -0.3, expect: 'inset(-29px -28px -27px -26px round 0px 0px 0px 10px / 20px 30px 40px 50px)'},
+ {at: 0, expect: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)'},
+ {at: 0.3, expect: 'inset(31px 32px 33px 34px round 40px 50px 60px 70px / 80px 90px 100px 110px)'},
+ {at: 0.6, expect: 'inset(61px 62px 63px 64px round 70px 80px 90px 100px / 110px 120px 130px 140px)'},
+ {at: 1, expect: 'inset(101px 102px 103px 104px round 110px 120px 130px 140px / 150px 160px 170px 180px)'},
+ {at: 1.5, expect: 'inset(151px 152px 153px 154px round 160px 170px 180px 190px / 200px 210px 220px 230px)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inset(1px 2px round 100px 200px)',
+ to: 'inset(101px 102px 101px 102px)',
+}, [
+ {at: -0.3, expect: 'inset(-29px -28px round 130px 260px)'},
+ {at: 0, expect: 'inset(1px 2px round 100px 200px)'},
+ {at: 0.3, expect: 'inset(31px 32px round 70px 140px)'},
+ {at: 0.6, expect: 'inset(61px 62px round 40px 80px)'},
+ {at: 1, expect: 'inset(101px 102px)'},
+ {at: 1.5, expect: 'inset(151px 152px)'}, // border radius can't be negative
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'polygon(10px 20%, 30px 40%)',
+ to: 'polygon(110px 120%, 130px 140%)',
+}, [
+ {at: -0.3, expect: 'polygon(-20px -10%, 0px 10%)'},
+ {at: 0, expect: 'polygon(10px 20%, 30px 40%)'},
+ {at: 0.3, expect: 'polygon(40px 50%, 60px 70%)'},
+ {at: 0.6, expect: 'polygon(70px 80%, 90px 100%)'},
+ {at: 1, expect: 'polygon(110px 120%, 130px 140%)'},
+ {at: 1.5, expect: 'polygon(160px 170%, 180px 190%)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'polygon(evenodd, 10px 20px)',
+ to: 'polygon(evenodd, 110px 120px)',
+}, [
+ {at: -0.3, expect: 'polygon(evenodd, -20px -10px)'},
+ {at: 0, expect: 'polygon(evenodd, 10px 20px)'},
+ {at: 0.3, expect: 'polygon(evenodd, 40px 50px)'},
+ {at: 0.6, expect: 'polygon(evenodd, 70px 80px)'},
+ {at: 1, expect: 'polygon(evenodd, 110px 120px)'},
+ {at: 1.5, expect: 'polygon(evenodd, 160px 170px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'polygon(evenodd, 10px 20px)',
+ to: 'polygon(nonzero, 110px 120px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'polygon(evenodd, 10px 20px)',
+ to: 'polygon(110px 120px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'polygon(10px 20px, 30px 40px)',
+ to: 'polygon(110px 120px)',
+});
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-shape.html b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-shape.html
new file mode 100644
index 0000000000..ad3e2a0bdb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-shape.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<meta charset="UTF-8">
+<title>clip-path-interpolation</title>
+<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-clip-path">
+<meta name="assert" content="clip-path supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+html {
+ font-size: 16px;
+ font-family: Ahem;
+}
+
+.parent {
+ clip-path: shape(from -5px 5px, move to 5% 1px);
+ padding: 10px;
+}
+
+.target {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ background-color: black;
+ clip-path: shape(from 5px 5px, line to 10px 10%);
+}
+
+.expected {
+ background-color: green;
+}
+</style>
+<body>
+<script>
+test_interpolation({
+ property: 'clip-path',
+ from: neutralKeyframe,
+ to: 'shape(from -5px 5px, line to 20px 20%)',
+}, [
+ {at: -0.3, expect: 'shape(from 8px 5px, line to 7px 7%)'},
+ {at: 0, expect: 'shape(from 5px 5px, line to 10px 10%)'},
+ {at: 0.6, expect: 'shape(from -1px 5px, line to 16px 16%)'},
+ {at: 1, expect: 'shape(from -5px 5px, line to 20px 20%)'},
+ {at: 1.5, expect: 'shape(from -10px 5px, line to 25px 25%)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'initial',
+ to: 'shape(from 8px 5px, line to 7px 7%)',
+});
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inherit',
+ to: 'shape(from 15% 15px, move to 20% -10px)',
+}, [
+ {at: -0.3, expect: 'shape(from calc(-4.5% - 6.5px) 2px, move to 0.5% 4.3px)'},
+ {at: 0, expect: 'shape(from calc(0% - 5px) 5px, move to 5% 1px)'},
+ {at: 0.5, expect: 'shape(from calc(7.5% - 2.5px) 10px, move to 12.5% -4.5px)'},
+ {at: 1, expect: 'shape(from 15% 15px, move to 20% -10px'},
+ {at: 1.5, expect: 'shape(from calc(22.5% + 2.5px) 20px, move to 27.5% -15.5px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'unset',
+ to: 'shape(from 10px 10px, close)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'none',
+ to: 'shape(from 10px 10px, close)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 10px 10px, move to 10% 10%)',
+ to: 'shape(from 10px 10px, close)',
+});
+
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5% 5px, hline to 5%, vline to -5px, close)',
+ to: 'shape(from 15% 15px, hline to 25%, vline to -15px, close)',
+}, [
+ {at: -0.3, expect: 'shape(from 2% 2px, hline to -1%, vline to -2px, close)'},
+ {at: 0, expect: 'shape(from 5% 5px, hline to 5%, vline to -5px, close)'},
+ {at: 0.5, expect: 'shape(from 10% 10px, hline to 15% , vline to -10px, close)'},
+ {at: 1, expect: 'shape(from 15% 15px, hline to 25%, vline to -15px, close)'},
+ {at: 1.5, expect: 'shape(from 20% 20px, hline to 35%, vline to -20px, close)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5% 5px, curve to 10% 10px via 0% 80px, curve to 30% 20px via 20% 50px 25% 70px)',
+ to: 'shape(from 15% 15px, curve to 20% 0px via 10% 60px, curve to 20% 30px via 30% 40px -5% 100px)',
+}, [
+ {at: -0.3, expect: 'shape(from 2% 2px, curve to 7% 13px via -3% 86px, curve to 33% 17px via 17% 53px 34% 61px)'},
+ {at: 0, expect: 'shape(from 5% 5px, curve to 10% 10px via 0% 80px, curve to 30% 20px via 20% 50px 25% 70px)'},
+ {at: 0.5, expect: 'shape(from 10% 10px, curve to 15% 5px via 5% 70px, curve to 25% 25px via 25% 45px 10% 85px)'},
+ {at: 1, expect: 'shape(from 15% 15px, curve to 20% 0px via 10% 60px, curve to 20% 30px via 30% 40px -5% 100px)'},
+ {at: 1.5, expect: 'shape(from 20% 20px, curve to 25% -5px via 15% 50px, curve to 15% 35px via 35% 35px -20% 115px)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5% 5px, curve by 10% 10px via 0% 80px, curve by 30% 20px via 20% 50px 25% 70px)',
+ to: 'shape(from 15% 15px, curve by 20% 0px via 10% 60px, curve by 20% 30px via 30% 40px -5% 100px)',
+}, [
+ {at: -0.3, expect: 'shape(from 2% 2px, curve by 7% 13px via -3% 86px, curve by 33% 17px via 17% 53px 34% 61px)'},
+ {at: 0, expect: 'shape(from 5% 5px, curve by 10% 10px via 0% 80px, curve by 30% 20px via 20% 50px 25% 70px)'},
+ {at: 0.5, expect: 'shape(from 10% 10px, curve by 15% 5px via 5% 70px, curve by 25% 25px via 25% 45px 10% 85px)'},
+ {at: 1.5, expect: 'shape(from 20% 20px, curve by 25% -5px via 15% 50px, curve by 15% 35px via 35% 35px -20% 115px)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5% 5px, smooth to 10% 10px via 0% 80px, smooth to 30% 20px)',
+ to: 'shape(from 15% 15px, smooth to 20% 0px via 10% 60px, smooth to 20% 30px)',
+}, [
+ {at: -0.3, expect: 'shape(from 2% 2px, smooth to 7% 13px via -3% 86px, smooth to 33% 17px)'},
+ {at: 0, expect: 'shape(from 5% 5px, smooth to 10% 10px via 0% 80px, smooth to 30% 20px)'},
+ {at: 0.5, expect: 'shape(from 10% 10px, smooth to 15% 5px via 5% 70px, smooth to 25% 25px)'},
+ {at: 1.5, expect: 'shape(from 20% 20px, smooth to 25% -5px via 15% 50px, smooth to 15% 35px)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5% 5px, smooth by 10% 10px via 0% 80px, smooth by 30% 20px)',
+ to: 'shape(from 15% 15px, smooth by 20% 0px via 10% 60px, smooth by 20% 30px)',
+}, [
+ {at: -0.3, expect: 'shape(from 2% 2px, smooth by 7% 13px via -3% 86px, smooth by 33% 17px)'},
+ {at: 0, expect: 'shape(from 5% 5px, smooth by 10% 10px via 0% 80px, smooth by 30% 20px)'},
+ {at: 0.5, expect: 'shape(from 10% 10px, smooth by 15% 5px via 5% 70px, smooth by 25% 25px)'},
+ {at: 1.5, expect: 'shape(from 20% 20px, smooth by 25% -5px via 15% 50px, smooth by 15% 35px)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)',
+ to: 'shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px cw rotate 270deg small, arc to 25% 20px of 10px 5px small cw)'
+}, [
+ {at: -0.3, expect: 'shape(from 2% 2px, arc to 18% -12px of 7px 17px ccw small, arc by 12% -2px of 33px 33px rotate -42deg cw large , arc to 25% 20px of 10px 5px ccw small)'},
+ {at: 0, expect: 'shape(from 5% 5px, arc to 15% -15px of 10px 20px, arc by 15% -5px of 30px cw rotate 30deg large, arc to 25% 20px of 10px 5px small)'},
+ {at: 0.3, expect: 'shape(from 8% 8px, arc to 12% -18px of 13px 23px ccw small, arc by 18% -8px of 27px 27px rotate 102deg cw large, arc to 25% 20px of 10px 5px ccw small )'},
+ {at: 0.5, expect: 'shape(from 10% 10px, arc to 10% -20px of 15px 25px ccw small, arc by 20% -10px of 25px rotate 150deg cw small, arc to 25% 20px of 10px 5px cw small)'},
+ {at: 1, expect: 'shape(from 15% 15px, arc to 5% -25px of 20px 30px, arc by 25% -15px of 20px rotate 270deg cw small, arc to 25% 20px of 10px 5px cw small)'},
+ {at: 1.5, expect: 'shape(from 20% 20px, arc to 0% -30px of 25px 35px ccw small, arc by 30% -20px of 15px rotate 390deg cw small, arc to 25% 20px of 10px 5px cw small)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'shape(from 5px -5%, hline to 10px, vline by 10rem, hline by 1vh, close, vline by 3pt)',
+ to: 'shape(from -5px 5px, hline to 20px, vline by 10%, hline by 1em, close, vline by 6pt)',
+}, [
+ {at: -0.3, expect: 'shape(from 8px calc(-6.5% - 1.5px), hline to 7px, vline by calc(-3% + 208px), hline by 5.92px, close, vline by 2.8px)'},
+ {at: 0, expect: 'shape(from 5px -5%, hline to 10px, vline by calc(0% + 160px), hline by 8.25px, close, vline by 4px)'},
+ {at: 0.6, expect: 'shape(from -1px calc(-2% + 3px), hline to 16px, vline by calc(6% + 64px), hline by 12.9px, close ,vline by 6.4px)'},
+ {at: 1, expect: 'shape(from -5px calc(0% + 5px), hline to 20px, vline by 10%, hline by 16px, close, vline by 8px)'},
+ {at: 1.5, expect: 'shape(from -10px calc(2.5% + 7.5px), hline to 25px, vline by calc(15% - 80px), hline by 19.88px, close, vline by 10px)'},
+]);
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-xywh-rect.html b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-xywh-rect.html
new file mode 100644
index 0000000000..8d35c2e9b0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/clip-path-interpolation-xywh-rect.html
@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>clip-path-interpolation for basic-shape-rect, xywh and rect</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-clip-path">
+<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-xywh">
+<link rel="help" href="https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-rect">
+<meta name="assert" content="clip-path supports animation for xywh() and rect()">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.parent {
+ clip-path: inset(10px);
+ padding: 10px;
+}
+
+.target {
+ display: inline-block;
+ width: 100px;
+ height: 100px;
+ background-color: black;
+ clip-path: inset(10px);
+}
+
+.expected {
+ background-color: green;
+}
+</style>
+<body>
+<script>
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'initial',
+ to: 'xywh(10px 10px 100px 100px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'unset',
+ to: 'xywh(10px 10px 100px 100px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'initial',
+ to: 'rect(10px 100px 100px 10px)',
+});
+
+test_no_interpolation({
+ property: 'clip-path',
+ from: 'unset',
+ to: 'rect(10px 100px 100px 10px)',
+});
+
+// Note: it's fine to use "rect()"/"xywh()" in "expect" because we always
+// convert it into `inset()` when we compare it with the actual animation value.
+test_interpolation({
+ property: 'clip-path',
+ from: 'xywh(5px 5px 150% 150%)',
+ to: 'xywh(10px 10px 100% 100%)'
+}, [
+ {at: -1, expect: 'xywh(0px 0px 200% 200%)'},
+ {at: 0, expect: 'xywh(5px 5px 150% 150%)'},
+ {at: 0.125, expect: 'xywh(5.63px 5.63px 143.75% 143.75%)'},
+ {at: 0.875, expect: 'xywh(9.38px 9.38px 106.25% 106.25%)'},
+ {at: 1, expect: 'xywh(10px 10px 100% 100%)'},
+ {at: 2, expect: 'xywh(15px 15px 50% 50%)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'rect(10px 100px 50% 10%)',
+ to: 'rect(50px 200px 90% 50%)'
+}, [
+ {at: -1, expect: 'rect(-30px 0px 10% -30%)'},
+ {at: 0, expect: 'rect(10px 100px 50% 10%)'},
+ {at: 0.125, expect: 'rect(15px 112.5px 55% 15%)'},
+ {at: 0.875, expect: 'rect(45px 187.5px 85% 45%)'},
+ {at: 1, expect: 'rect(50px 200px 90% 50%)'},
+ {at: 2, expect: 'rect(90px 300px 130% 90%)'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'rect(auto auto auto auto)',
+ to: 'rect(80% 20% 20% 80%)'
+}, [
+ {at: -1, expect: 'inset(-80%)'},
+ {at: 0, expect: 'inset(0%)'},
+ {at: 0.125, expect: 'inset(10%)'},
+ {at: 0.875, expect: 'inset(70%)'},
+ {at: 1, expect: 'inset(80%)'},
+ {at: 2, expect: 'inset(160%)'},
+]);
+
+// All <basic-shape-rect>s compute to the equivalent inset() function, so they
+// interpolatable.
+// https://drafts.csswg.org/css-shapes-1/#basic-shape-computed-values
+test_interpolation({
+ property: 'clip-path',
+ from: neutralKeyframe,
+ // inset(50px calc(80% - 70px) calc(0% - 50px) 20%).
+ to: 'xywh(20% 50px 70px 100%)',
+}, [
+ {at: -1, expect: 'inset(-30px calc(-80% + 90px) calc(0% + 70px) calc(-20% + 20px)'},
+ {at: 0, expect: 'inset(10px calc(0% + 10px) calc(0% + 10px))'},
+ {at: 0.125, expect: 'inset(15px 10% calc(0% + 2.5px) calc(2.5% + 8.75px))'},
+ {at: 0.875, expect: 'inset(45px calc(70% - 60px) calc(0% - 42.5px) calc(17.5% + 1.25px))'},
+ {at: 1, expect: 'inset(50px calc(80% - 70px) calc(0% - 50px) 20%)'},
+ {at: 2, expect: 'inset(90px calc(160% - 150px) calc(0% - 110px) calc(40% - 10px))'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: neutralKeyframe,
+ // inset(50px calc(100% - 70px) 20% 20%).
+ to: 'rect(50px 70px 80% 20%)',
+}, [
+ {at: -1, expect: 'inset(-30px calc(-100% + 90px) calc(-20% + 20px) calc(-20% + 20px)'},
+ {at: 0, expect: 'inset(10px calc(0% + 10px) calc(0% + 10px))'},
+ {at: 0.125, expect: 'inset(15px 12.5% calc(2.5% + 8.75px) calc(2.5% + 8.75px))'},
+ {at: 0.875, expect: 'inset(45px calc(87.5% - 60px) calc(17.5% + 1.25px) calc(17.5% + 1.25px))'},
+ {at: 1, expect: 'inset(50px calc(100% - 70px) 20% 20%)'},
+ {at: 2, expect: 'inset(90px calc(200% - 150px) calc(40% - 10px) calc(40% - 10px))'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inherit',
+ to: 'xywh(20% 50px 70px 100%)',
+}, [
+ {at: -1, expect: 'inset(-30px calc(-80% + 90px) calc(0% + 70px) calc(-20% + 20px)'},
+ {at: 0, expect: 'inset(10px calc(0% + 10px) calc(0% + 10px))'},
+ {at: 0.125, expect: 'inset(15px 10% calc(0% + 2.5px) calc(2.5% + 8.75px))'},
+ {at: 0.875, expect: 'inset(45px calc(70% - 60px) calc(0% - 42.5px) calc(17.5% + 1.25px))'},
+ {at: 1, expect: 'inset(50px calc(80% - 70px) calc(0% - 50px) 20%)'},
+ {at: 2, expect: 'inset(90px calc(160% - 150px) calc(0% - 110px) calc(40% - 10px))'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'inherit',
+ to: 'rect(50px 70px 80% 20%)',
+}, [
+ {at: -1, expect: 'inset(-30px calc(-100% + 90px) calc(-20% + 20px) calc(-20% + 20px)'},
+ {at: 0, expect: 'inset(10px calc(0% + 10px) calc(0% + 10px))'},
+ {at: 0.125, expect: 'inset(15px 12.5% calc(2.5% + 8.75px) calc(2.5% + 8.75px))'},
+ {at: 0.875, expect: 'inset(45px calc(87.5% - 60px) calc(17.5% + 1.25px) calc(17.5% + 1.25px))'},
+ {at: 1, expect: 'inset(50px calc(100% - 70px) 20% 20%)'},
+ {at: 2, expect: 'inset(90px calc(200% - 150px) calc(40% - 10px) calc(40% - 10px))'},
+]);
+
+test_interpolation({
+ property: 'clip-path',
+ from: 'xywh(0px 10% 100px 40% round 20px)',
+ to: 'rect(20% 50% 200px 20px)',
+}, [
+ {at: -1, expect: 'inset(0% calc(150% - 200px) calc(0% + 200px) -20px round 40px'},
+ {at: 0, expect: 'inset(10% calc(100% - 100px) 50% 0px round 20px)'},
+ {at: 0.125, expect: 'inset(11.25% calc(93.75% - 87.5px) calc(56.25% - 25px) 2.5px round 17.5px)'},
+ {at: 0.875, expect: 'inset(18.75% calc(56.25% - 12.5px) calc(93.75% - 175px) 17.5px round 2.5px)'},
+ {at: 1, expect: 'inset(20% 50% calc(100% - 200px) 20px)'},
+ {at: 2, expect: 'inset(30% calc(0% + 100px) calc(150% - 400px) 40px)'},
+]);
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/css-masking/animations/mask-image-interpolation.html b/testing/web-platform/tests/css/css-masking/animations/mask-image-interpolation.html
new file mode 100644
index 0000000000..ac6b266992
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/mask-image-interpolation.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>mask-image-interpolation</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-mask-image">
+<meta name="assert" content="mask-image supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.parent {
+ mask-image: url(../resources/blue-20.png);
+}
+.target {
+ width: 20px;
+ height: 20px;
+ display: inline-block;
+ background-color: black;
+ mask-image: url(../resources/stripes-20.png);
+}
+.expected {
+ background-color: green;
+ margin-right: 10px;
+}
+</style>
+
+<body>
+<script>
+// neutral
+test_no_interpolation({
+ property: 'mask-image',
+ from: neutralKeyframe,
+ to: 'url(../resources/green-20.png)',
+});
+
+// initial
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'initial',
+ to: 'url(../resources/green-20.png)',
+});
+
+// inherit
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'inherit',
+ to: 'url(../resources/green-20.png)',
+});
+
+// unset
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'unset',
+ to: 'url(../resources/stripes-20.png)',
+});
+
+// Image to image
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'url(../resources/stripes-20.png)',
+ to: 'url(../resources/blue-20.png)',
+});
+
+//Image to gradient
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'url(../resources/stripes-20.png)',
+ to: 'linear-gradient(45deg, blue, transparent)'
+});
+
+// Keyword to image
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'none',
+ to: 'url(../resources/green-20.png)',
+});
+
+// Multiple to multiple
+var fromA = 'url(../resources/stripes-20.png)';
+var fromB = 'linear-gradient(-45deg, blue, transparent)';
+var toA = 'url(../resources/blue-20.png)';
+var toB = 'url(../resources/stripes-20.png)';
+var from = fromA + ', ' + fromB;
+var to = toA + ', ' + toB;
+test_no_interpolation({
+ property: 'mask-image',
+ from: from,
+ to: to,
+});
+
+// Single to multiple
+from = 'url(../resources/blue-20.png)';
+toA = 'url(../resources/stripes-20.png)';
+toB = 'url(../resources/blue-20.png)';
+to = toA + ', ' + toB;
+test_no_interpolation({
+ property: 'mask-image',
+ from: from,
+ to: to,
+});
+
+// Multiple mismatched types
+test_no_interpolation({
+ property: 'mask-image',
+ from: 'url(../resources/blue-20.png), none',
+ to: 'url(../resources/stripes-20.png), url(../resources/blue-20.png)',
+});
+</script>
+</body>
diff --git a/testing/web-platform/tests/css/css-masking/animations/mask-no-interpolation.html b/testing/web-platform/tests/css/css-masking/animations/mask-no-interpolation.html
new file mode 100644
index 0000000000..1275340ea8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/mask-no-interpolation.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://drafts.fxtf.org/css-masking/#the-mask">
+<link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
+<link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<body>
+<script>
+test_no_interpolation({
+ property: 'mask',
+ from: 'none',
+ to: 'url(mask.png)'
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-masking/animations/mask-position-interpolation.html b/testing/web-platform/tests/css/css-masking/animations/mask-position-interpolation.html
new file mode 100644
index 0000000000..d832048ca3
--- /dev/null
+++ b/testing/web-platform/tests/css/css-masking/animations/mask-position-interpolation.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<meta charset="UTF-8">
+<title>mask-position-interpolation</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#the-mask-position">
+<meta name="assert" content="mask-position supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.container {
+ display: inline-block;
+ border: 2px solid black;
+}
+.parent {
+ mask-position: 30px 10px;
+}
+.target {
+ width: 120px;
+ height: 120px;
+ mask-position: 10px 30px;
+}
+</style>
+
+<body>
+<template id="target-template">
+ <div class="container">
+ <div class="target"></div>
+ </div>
+</template>
+<script>
+// neutral
+test_interpolation({
+ property: 'mask-position',
+ from: neutralKeyframe,
+ to: '20px 20px',
+}, [
+ {at: -0.25, expect: '7.5px 32.5px'},
+ {at: 0, expect: '10px 30px'},
+ {at: 0.25, expect: '12.5px 27.5px'},
+ {at: 0.5, expect: '15px 25px'},
+ {at: 0.75, expect: '17.5px 22.5px'},
+ {at: 1, expect: '20px 20px'},
+ {at: 1.25, expect: '22.5px 17.5px'},
+]);
+
+// initial
+test_interpolation({
+ property: 'mask-position',
+ from: 'initial',
+ to: '20px 20px',
+}, [
+ {at: -0.25, expect: 'calc(0% - 5px) calc(0% - 5px)'},
+ {at: 0, expect: '0% 0%'},
+ {at: 0.25, expect: 'calc(0% + 5px) calc(0% + 5px)'},
+ {at: 0.5, expect: 'calc(0% + 10px) calc(0% + 10px)'},
+ {at: 0.75, expect: 'calc(0% + 15px) calc(0% + 15px)'},
+ {at: 1, expect: 'calc(0% + 20px) calc(0% + 20px)'},
+ {at: 1.25, expect:'calc(0% + 25px) calc(0% + 25px)'},
+]);
+
+// inherit
+test_interpolation({
+ property: 'mask-position',
+ from: 'inherit',
+ to: '20px 20px',
+}, [
+ {at: -0.25, expect: '32.5px 7.5px'},
+ {at: 0, expect: '30px 10px'},
+ {at: 0.25, expect: '27.5px 12.5px'},
+ {at: 0.5, expect: '25px 15px'},
+ {at: 0.75, expect: '22.5px 17.5px'},
+ {at: 1, expect: '20px 20px'},
+ {at: 1.25, expect: '17.5px 22.5px'},
+]);
+
+// unset
+test_interpolation({
+ property: 'mask-position',
+ from: 'unset',
+ to: '20px 20px',
+}, [
+ {at: -0.25, expect: 'calc(0% - 5px) calc(0% - 5px)'},
+ {at: 0, expect: '0% 0%'},
+ {at: 0.25, expect: 'calc(0% + 5px) calc(0% + 5px)'},
+ {at: 0.5, expect: 'calc(0% + 10px) calc(0% + 10px)'},
+ {at: 0.75, expect: 'calc(0% + 15px) calc(0% + 15px)'},
+ {at: 1, expect: 'calc(0% + 20px) calc(0% + 20px)'},
+ {at: 1.25, expect:'calc(0% + 25px) calc(0% + 25px)'},
+]);
+
+// Test equal number of position values as background images.
+test_interpolation({
+ property: 'mask-position',
+ from: '0px 0px, 0px 0px, 0px 0px, 0px 0px',
+ to: '80px 80px, 80px 80px, 80px 80px, 80px 80px',
+}, [
+ {at: -0.25, expect: '-20px -20px, -20px -20px, -20px -20px, -20px -20px'},
+ {at: 0, expect: ' 0px 0px, 0px 0px, 0px 0px, 0px 0px'},
+ {at: 0.25, expect: ' 20px 20px, 20px 20px, 20px 20px, 20px 20px'},
+ {at: 0.5, expect: ' 40px 40px, 40px 40px, 40px 40px, 40px 40px'},
+ {at: 0.75, expect: ' 60px 60px, 60px 60px, 60px 60px, 60px 60px'},
+ {at: 1, expect: ' 80px 80px, 80px 80px, 80px 80px, 80px 80px'},
+ {at: 1.25, expect: '100px 100px, 100px 100px, 100px 100px, 100px 100px'},
+]);
+
+// Test single position value repeated over background images.
+test_interpolation({
+ property: 'mask-position',
+ from: 'top 0px left 0px',
+ to: 'left 80px top 80px',
+}, [
+ {at: -0.25, expect: '-20px -20px'},
+ {at: 0, expect: ' 0px 0px'},
+ {at: 0.25, expect: ' 20px 20px'},
+ {at: 0.5, expect: ' 40px 40px'},
+ {at: 0.75, expect: ' 60px 60px'},
+ {at: 1, expect: ' 80px 80px'},
+ {at: 1.25, expect: '100px 100px'},
+]);
+
+// Test mismatched numbers of position values.
+test_interpolation({
+ property: 'mask-position',
+ from: '0px 0px, 80px 0px',
+ to: '40px 40px, 80px 80px, 0px 80px',
+}, [
+ {at: -0.25, expect:
+ '-10px -10px, 80px -20px, 0px -20px, 90px -10px, -20px -20px, 100px -20px'},
+ {at: 0, expect:
+ ' 0px 0px, 80px 0px, 0px 0px, 80px 0px, 0px 0px, 80px 0px'},
+ {at: 0.25, expect:
+ ' 10px 10px, 80px 20px, 0px 20px, 70px 10px, 20px 20px, 60px 20px'},
+ {at: 0.5, expect:
+ ' 20px 20px, 80px 40px, 0px 40px, 60px 20px, 40px 40px, 40px 40px'},
+ {at: 0.75, expect:
+ ' 30px 30px, 80px 60px, 0px 60px, 50px 30px, 60px 60px, 20px 60px'},
+ {at: 1, expect:
+ ' 40px 40px, 80px 80px, 0px 80px, 40px 40px, 80px 80px, 0px 80px'},
+ {at: 1.25, expect:
+ ' 50px 50px, 80px 100px, 0px 100px, 30px 50px, 100px 100px, -20px 100px'},
+]);
+</script>
+</body>