summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/canvas/element/layers
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/canvas/element/layers')
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.beginLayer-options.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full-expected.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full.html23
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-expected.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside.html23
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside-expected.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths-expected.html14
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow-expected.html17
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.exceptions-are-no-op.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation-expected.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter-expected.html17
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html39
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html39
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html55
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html42
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html55
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html42
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html53
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html40
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-restore.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.endLayer.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-beginLayer-restore.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-endLayer.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.layer-rendering-state-reset-in-layer.html56
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.toBlob.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.createPattern.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.drawImage.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.getImageData.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.putImageData.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.toDataURL.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters-expected.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset-expected.html14
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html25
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-endLayer.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-save.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.restore.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save-beginLayer.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_reset_restore.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_restore.html27
128 files changed, 4068 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic-expected.html
new file mode 100644
index 0000000000..6a6f0f6892
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.isotropic</title>
+<h1>2d.layer.anisotropic-blur.isotropic</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="4 4" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic.html
new file mode 100644
index 0000000000..4e496b7e48
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.isotropic.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.isotropic-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.isotropic</title>
+<h1>2d.layer.anisotropic-blur.isotropic</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x-expected.html
new file mode 100644
index 0000000000..b0473f2ff0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-x</title>
+<h1>2d.layer.anisotropic-blur.mostly-x</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="4 1" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x.html
new file mode 100644
index 0000000000..4217d9fad3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-x.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.mostly-x-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-x</title>
+<h1>2d.layer.anisotropic-blur.mostly-x</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 1] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y-expected.html
new file mode 100644
index 0000000000..43da016eea
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-y</title>
+<h1>2d.layer.anisotropic-blur.mostly-y</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="1 4" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y.html
new file mode 100644
index 0000000000..97a44e9045
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.mostly-y.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.mostly-y-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.mostly-y</title>
+<h1>2d.layer.anisotropic-blur.mostly-y</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [1, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only-expected.html
new file mode 100644
index 0000000000..0b4d269189
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.x-only</title>
+<h1>2d.layer.anisotropic-blur.x-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="4 0" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only.html
new file mode 100644
index 0000000000..fdf604616b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.x-only.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.x-only-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.x-only</title>
+<h1>2d.layer.anisotropic-blur.x-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [4, 0] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only-expected.html
new file mode 100644
index 0000000000..2572386412
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.anisotropic-blur.y-only</title>
+<h1>2d.layer.anisotropic-blur.y-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="0 4" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only.html
new file mode 100644
index 0000000000..c7ceb63a87
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.anisotropic-blur.y-only.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.anisotropic-blur.y-only-expected.html">
+<title>Canvas test: 2d.layer.anisotropic-blur.y-only</title>
+<h1>2d.layer.anisotropic-blur.y-only</h1>
+<p class="desc">Checks that layers allow gaussian blur with separate X and Y components.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: { name: 'gaussianBlur', stdDeviation: [0, 4] }});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.beginLayer-options.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.beginLayer-options.html
new file mode 100644
index 0000000000..658d7e0991
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.beginLayer-options.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.beginLayer-options</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.beginLayer-options</h1>
+<p class="desc">Checks beginLayer works for different option parameter values</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Checks beginLayer works for different option parameter values");
+_addTest(function(canvas, ctx) {
+
+ ctx.beginLayer(); ctx.endLayer();
+ ctx.beginLayer(null); ctx.endLayer();
+ ctx.beginLayer(undefined); ctx.endLayer();
+ ctx.beginLayer([]); ctx.endLayer();
+ ctx.beginLayer({}); ctx.endLayer();
+
+ assert_throws_js(TypeError, function() { ctx.beginLayer(''); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(0); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(1); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(true); });
+ assert_throws_js(TypeError, function() { ctx.beginLayer(false); });
+
+ ctx.beginLayer({filter: null}); ctx.endLayer();
+ ctx.beginLayer({filter: undefined}); ctx.endLayer();
+ ctx.beginLayer({filter: []}); ctx.endLayer();
+ ctx.beginLayer({filter: {}}); ctx.endLayer();
+ ctx.beginLayer({filter: {name: "unknown"}}); ctx.endLayer();
+ ctx.beginLayer({filter: ''}); ctx.endLayer();
+
+ // These cases don't throw TypeError since they can be casted to a
+ // DOMString.
+ ctx.beginLayer({filter: 0}); ctx.endLayer();
+ ctx.beginLayer({filter: 1}); ctx.endLayer();
+ ctx.beginLayer({filter: true}); ctx.endLayer();
+ ctx.beginLayer({filter: false}); ctx.endLayer();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html
new file mode 100644
index 0000000000..6cad180f14
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping-expected.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.no-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.no-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur in="SourceGraphic" stdDeviation="30" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="201" y="50" width="100" height="100" fill="turquoise"/>
+ <rect x="50" y="201" width="100" height="100" fill="indigo"/>
+ <rect x="-101" y="50" width="100" height="100" fill="orange"/>
+ <rect x="50" y="-101" width="100" height="100" fill="brown"/>
+ </g>
+ </svg>`;
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ // No clipping.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping.html
new file mode 100644
index 0000000000..b689ad39fe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.no-clipping.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.blur-from-outside-canvas.no-clipping-expected.html">
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.no-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.no-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [ {name: 'gaussianBlur', stdDeviation: 30} ]});
+
+ ctx.fillStyle = 'turquoise';
+ ctx.fillRect(201, 50, 100, 100);
+ ctx.fillStyle = 'indigo';
+ ctx.fillRect(50, 201, 100, 100);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(-1, 50, -100, 100);
+ ctx.fillStyle = 'brown';
+ ctx.fillRect(50, -1, 100, -100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html
new file mode 100644
index 0000000000..1823f78983
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping-expected.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.with-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.with-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur in="SourceGraphic" stdDeviation="30" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="201" y="50" width="100" height="100" fill="turquoise"/>
+ <rect x="50" y="201" width="100" height="100" fill="indigo"/>
+ <rect x="-101" y="50" width="100" height="100" fill="orange"/>
+ <rect x="50" y="-101" width="100" height="100" fill="brown"/>
+ </g>
+ </svg>`;
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping.html
new file mode 100644
index 0000000000..9e8161019a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.blur-from-outside-canvas.with-clipping.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.blur-from-outside-canvas.with-clipping-expected.html">
+<title>Canvas test: 2d.layer.blur-from-outside-canvas.with-clipping</title>
+<h1>2d.layer.blur-from-outside-canvas.with-clipping</h1>
+<p class="desc">Checks blur leaking inside from drawing outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [ {name: 'gaussianBlur', stdDeviation: 30} ]});
+
+ ctx.fillStyle = 'turquoise';
+ ctx.fillRect(201, 50, 100, 100);
+ ctx.fillStyle = 'indigo';
+ ctx.fillRect(50, 201, 100, 100);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(-1, 50, -100, 100);
+ ctx.fillStyle = 'brown';
+ ctx.fillRect(50, -1, 100, -100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full-expected.html
new file mode 100644
index 0000000000..5a47f8e118
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full-expected.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clearRect.full</title>
+<h1>2d.layer.clearRect.full</h1>
+<p class="desc">clearRect inside a layer can clear all of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full.html
new file mode 100644
index 0000000000..579c6e1053
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.full.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clearRect.full-expected.html">
+<title>Canvas test: 2d.layer.clearRect.full</title>
+<h1>2d.layer.clearRect.full</h1>
+<p class="desc">clearRect inside a layer can clear all of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 50);
+ ctx.fillStyle = 'green';
+ ctx.clearRect(0, 0, 100, 100);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial-expected.html
new file mode 100644
index 0000000000..ac75105cec
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clearRect.partial</title>
+<h1>2d.layer.clearRect.partial</h1>
+<p class="desc">clearRect inside a layer can clear a portion of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 10);
+ ctx.fillRect(20, 60, 80, 10);
+ ctx.fillRect(20, 20, 10, 50);
+ ctx.fillRect(90, 20, 10, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial.html
new file mode 100644
index 0000000000..8323ffb931
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clearRect.partial.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clearRect.partial-expected.html">
+<title>Canvas test: 2d.layer.clearRect.partial</title>
+<h1>2d.layer.clearRect.partial</h1>
+<p class="desc">clearRect inside a layer can clear a portion of the layer content.</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 80, 50);
+ ctx.clearRect(30, 30, 60, 30);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside-expected.html
new file mode 100644
index 0000000000..14e6d56245
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clip-inside-and-outside</title>
+<h1>2d.layer.clip-inside-and-outside</h1>
+<p class="desc">Check clipping set inside and outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+
+ ctx2.beginPath();
+ ctx2.rect(15, 15, 70, 70);
+ ctx2.clip();
+
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(10, 10, 80, 80);
+
+ const canvas3 = new OffscreenCanvas(200, 200);
+ const ctx3 = canvas3.getContext('2d');
+
+ ctx3.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx3.drawImage(canvas2, 0, 0);
+ ctx3.endLayer();
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+ ctx.drawImage(canvas3, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside.html
new file mode 100644
index 0000000000..1a727bbd3c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-and-outside.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clip-inside-and-outside-expected.html">
+<title>Canvas test: 2d.layer.clip-inside-and-outside</title>
+<h1>2d.layer.clip-inside-and-outside</h1>
+<p class="desc">Check clipping set inside and outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-expected.html
new file mode 100644
index 0000000000..281fc1d913
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside-expected.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clip-inside</title>
+<h1>2d.layer.clip-inside</h1>
+<p class="desc">Check clipping set inside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+
+ ctx2.beginPath();
+ ctx2.rect(15, 15, 70, 70);
+ ctx2.clip();
+
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(10, 10, 80, 80);
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx.drawImage(canvas2, 0, 0);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside.html
new file mode 100644
index 0000000000..f3555c8321
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-inside.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clip-inside-expected.html">
+<title>Canvas test: 2d.layer.clip-inside</title>
+<h1>2d.layer.clip-inside</h1>
+<p class="desc">Check clipping set inside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside-expected.html
new file mode 100644
index 0000000000..1b18c2e8a7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside-expected.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.clip-outside</title>
+<h1>2d.layer.clip-outside</h1>
+<p class="desc">Check clipping set outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+
+ ctx2.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx2.fillStyle = 'blue';
+ ctx2.fillRect(10, 10, 80, 80);
+ ctx2.endLayer();
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside.html
new file mode 100644
index 0000000000..bf8e84e3d2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.clip-outside.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.clip-outside-expected.html">
+<title>Canvas test: 2d.layer.clip-outside</title>
+<h1>2d.layer.clip-outside</h1>
+<p class="desc">Check clipping set outside the layer</p>
+<canvas id="canvas" width="100" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginPath();
+ ctx.rect(15, 15, 70, 70);
+ ctx.clip();
+
+ ctx.beginLayer({filter: {name: "gaussianBlur", stdDeviation: 12}});
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(10, 10, 80, 80);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths-expected.html
new file mode 100644
index 0000000000..c394ecdfe3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths-expected.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.cross-layer-paths</title>
+<h1>2d.layer.cross-layer-paths</h1>
+<p class="desc">Checks that path defined in a layer is usable outside.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.moveTo(50, 0); ctx.lineTo(50, 100); ctx.stroke();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths.html
new file mode 100644
index 0000000000..7feebfdce6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.cross-layer-paths.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.cross-layer-paths-expected.html">
+<title>Canvas test: 2d.layer.cross-layer-paths</title>
+<h1>2d.layer.cross-layer-paths</h1>
+<p class="desc">Checks that path defined in a layer is usable outside.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer();
+ ctx.translate(50, 0);
+ ctx.moveTo(0, 0);
+ ctx.endLayer();
+ ctx.lineTo(50, 100);
+ ctx.stroke();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow-expected.html
new file mode 100644
index 0000000000..85503ae33a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow-expected.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.css-filters.blur-and-shadow</title>
+<h1>2d.layer.css-filters.blur-and-shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="5" />
+ <feDropShadow dx="10" dy="10" stdDeviation="5" flood-color="orange" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow.html
new file mode 100644
index 0000000000..08adfa3d74
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-and-shadow.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.css-filters.blur-and-shadow-expected.html">
+<title>Canvas test: 2d.layer.css-filters.blur-and-shadow</title>
+<h1>2d.layer.css-filters.blur-and-shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'blur(5px) drop-shadow(10px 10px 5px orange)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-expected.html
new file mode 100644
index 0000000000..c6131f6c1e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.css-filters.blur</title>
+<h1>2d.layer.css-filters.blur</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feGaussianBlur stdDeviation="10" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur.html
new file mode 100644
index 0000000000..3eb3ab8f9c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.blur.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.css-filters.blur-expected.html">
+<title>Canvas test: 2d.layer.css-filters.blur</title>
+<h1>2d.layer.css-filters.blur</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'blur(10px)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow-expected.html
new file mode 100644
index 0000000000..60f78d8096
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.css-filters.shadow</title>
+<h1>2d.layer.css-filters.shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+
+<svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feDropShadow dx="-10" dy="-10" stdDeviation="5" flood-color="purple" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="100" height="100" fill="teal"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow.html
new file mode 100644
index 0000000000..e6df8a3ac2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.css-filters.shadow.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.css-filters.shadow-expected.html">
+<title>Canvas test: 2d.layer.css-filters.shadow</title>
+<h1>2d.layer.css-filters.shadow</h1>
+<p class="desc">Checks that beginLayer works with a CSS filter string as input.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: 'drop-shadow(-10px -10px 5px purple)'});
+
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.exceptions-are-no-op.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.exceptions-are-no-op.html
new file mode 100644
index 0000000000..7ab2080fca
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.exceptions-are-no-op.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.exceptions-are-no-op</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.exceptions-are-no-op</h1>
+<p class="desc">Checks that the context state is left unchanged if beginLayer throws.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Checks that the context state is left unchanged if beginLayer throws.");
+_addTest(function(canvas, ctx) {
+
+ // Get `beginLayer` to throw while parsing the filter.
+ assert_throws_js(TypeError,
+ () => ctx.beginLayer({filter: {name: 'colorMatrix',
+ values: 'foo'}}));
+ // `beginLayer` shouldn't have opened the layer, so `endLayer` should throw.
+ assert_throws_dom("InvalidStateError", () => ctx.endLayer());
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation-expected.html
new file mode 100644
index 0000000000..532c29576c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<title>Canvas test: 2d.layer.flush-on-frame-presentation</title>
+<h1>2d.layer.flush-on-frame-presentation</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script type="module">
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation.html
new file mode 100644
index 0000000000..c8a118f8a2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.flush-on-frame-presentation.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.flush-on-frame-presentation-expected.html">
+<title>Canvas test: 2d.layer.flush-on-frame-presentation</title>
+<h1>2d.layer.flush-on-frame-presentation</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script type="module">
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ await new Promise(resolve => requestAnimationFrame(resolve));
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter-expected.html
new file mode 100644
index 0000000000..88057fc354
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter-expected.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-filter</title>
+<h1>2d.layer.global-filter</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+<canvas id="canvas" width="150" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillRect(60, 10, 30, 30);
+ ctx.filter = 'blur(5px)'
+ ctx.fillRect(10, 10, 30, 30);
+ ctx.fillRect(110, 10, 30, 30);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter.html
new file mode 100644
index 0000000000..cf46f41b97
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-filter.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-filter-expected.html">
+<title>Canvas test: 2d.layer.global-filter</title>
+<h1>2d.layer.global-filter</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+<canvas id="canvas" width="150" height="100">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.filter = 'blur(5px)'
+
+ ctx.beginLayer();
+ ctx.fillRect(10, 10, 30, 30); // `ctx.filter` applied to draw call.
+ ctx.endLayer();
+
+ ctx.beginLayer();
+ ctx.filter = 'none';
+ ctx.fillRect(60, 10, 30, 30); // Should not be filted by the layer.
+ ctx.endLayer();
+
+ ctx.fillRect(110, 10, 30, 30); // `ctx.filter` is still set.
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html
new file mode 100644
index 0000000000..0666e3098a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha</title>
+<h1>2d.layer.global-states.alpha</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html
new file mode 100644
index 0000000000..8a45027588
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.blending</title>
+<h1>2d.layer.global-states.alpha.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html
new file mode 100644
index 0000000000..8e15a2b936
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.blending</title>
+<h1>2d.layer.global-states.alpha.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
new file mode 100644
index 0000000000..f7b633b35f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html
new file mode 100644
index 0000000000..c8c6d433bc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html
new file mode 100644
index 0000000000..951049e638
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.composite</title>
+<h1>2d.layer.global-states.alpha.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html
new file mode 100644
index 0000000000..1ac6a2cbfe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.composite</title>
+<h1>2d.layer.global-states.alpha.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
new file mode 100644
index 0000000000..0ae93871f5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html
new file mode 100644
index 0000000000..92b8a0d7a7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html
new file mode 100644
index 0000000000..829796acbf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha</title>
+<h1>2d.layer.global-states.alpha</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html
new file mode 100644
index 0000000000..6f764c5001
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.shadow</title>
+<h1>2d.layer.global-states.alpha.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html
new file mode 100644
index 0000000000..a325302b3b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.shadow</title>
+<h1>2d.layer.global-states.alpha.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html
new file mode 100644
index 0000000000..33fdf46a28
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending</title>
+<h1>2d.layer.global-states.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html
new file mode 100644
index 0000000000..7d4d9ae4b5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending</title>
+<h1>2d.layer.global-states.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html
new file mode 100644
index 0000000000..6f969074f9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.shadow</title>
+<h1>2d.layer.global-states.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html
new file mode 100644
index 0000000000..51926d76d8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow</title>
+<h1>2d.layer.global-states.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html
new file mode 100644
index 0000000000..ed7669c4cf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite</title>
+<h1>2d.layer.global-states.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html
new file mode 100644
index 0000000000..898d149924
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite</title>
+<h1>2d.layer.global-states.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html
new file mode 100644
index 0000000000..b687c27f47
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.shadow</title>
+<h1>2d.layer.global-states.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html
new file mode 100644
index 0000000000..c563a57b76
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow</title>
+<h1>2d.layer.global-states.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html
new file mode 100644
index 0000000000..f304700feb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
+<h1>2d.layer.global-states.filter.alpha</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html
new file mode 100644
index 0000000000..7c91ce4229
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
+<h1>2d.layer.global-states.filter.alpha.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
new file mode 100644
index 0000000000..17e0f0c8c5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
+<h1>2d.layer.global-states.filter.alpha.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
new file mode 100644
index 0000000000..62942ffeae
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
new file mode 100644
index 0000000000..ccadfb624b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html
new file mode 100644
index 0000000000..8e0d98648e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
+<h1>2d.layer.global-states.filter.alpha.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
new file mode 100644
index 0000000000..71a27cf710
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
+<h1>2d.layer.global-states.filter.alpha.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
new file mode 100644
index 0000000000..a649972546
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
new file mode 100644
index 0000000000..b2907f02aa
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
new file mode 100644
index 0000000000..5133aa170e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
+<h1>2d.layer.global-states.filter.alpha</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
new file mode 100644
index 0000000000..169baee29b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
new file mode 100644
index 0000000000..6aa8e75a95
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html
new file mode 100644
index 0000000000..f81dcf72dc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.blending</title>
+<h1>2d.layer.global-states.filter.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html
new file mode 100644
index 0000000000..31628812c2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending</title>
+<h1>2d.layer.global-states.filter.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html
new file mode 100644
index 0000000000..91f3725f8e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow</title>
+<h1>2d.layer.global-states.filter.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html
new file mode 100644
index 0000000000..e54cf06d0d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow</title>
+<h1>2d.layer.global-states.filter.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html
new file mode 100644
index 0000000000..97e85a1593
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.composite</title>
+<h1>2d.layer.global-states.filter.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html
new file mode 100644
index 0000000000..d7e365422f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite</title>
+<h1>2d.layer.global-states.filter.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html
new file mode 100644
index 0000000000..4716bb2760
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow</title>
+<h1>2d.layer.global-states.filter.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html
new file mode 100644
index 0000000000..e5c7698634
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow</title>
+<h1>2d.layer.global-states.filter.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html
new file mode 100644
index 0000000000..e56fe0b360
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.no-global-states</title>
+<h1>2d.layer.global-states.filter.no-global-states</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html
new file mode 100644
index 0000000000..68f4d5004a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.no-global-states-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-global-states</title>
+<h1>2d.layer.global-states.filter.no-global-states</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html
new file mode 100644
index 0000000000..13ba2dd4cd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.shadow</title>
+<h1>2d.layer.global-states.filter.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html
new file mode 100644
index 0000000000..9efcd9d4f7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.shadow</title>
+<h1>2d.layer.global-states.filter.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: [
+ {name: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {name: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {name: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]});
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html
new file mode 100644
index 0000000000..b91a2ae8b5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-global-states</title>
+<h1>2d.layer.global-states.no-global-states</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html
new file mode 100644
index 0000000000..d561be2341
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.no-global-states-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-global-states</title>
+<h1>2d.layer.global-states.no-global-states</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html
new file mode 100644
index 0000000000..835e9d420a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.shadow</title>
+<h1>2d.layer.global-states.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html
new file mode 100644
index 0000000000..209316164c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.shadow</title>
+<h1>2d.layer.global-states.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
new file mode 100644
index 0000000000..74e05e1e48
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-reset-endLayer.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.invalid-calls.beginLayer-reset-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.invalid-calls.beginLayer-reset-endLayer</h1>
+<p class="desc">Raises exception on beginLayer() + reset() + endLayer().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Raises exception on beginLayer() + reset() + endLayer().");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.reset();
+ ctx.endLayer();
+ });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-restore.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-restore.html
new file mode 100644
index 0000000000..1979cb6c73
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-restore.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.invalid-calls.beginLayer-restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.invalid-calls.beginLayer-restore</h1>
+<p class="desc">Raises exception on beginLayer() + restore().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Raises exception on beginLayer() + restore().");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.restore();
+ });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html
new file mode 100644
index 0000000000..c635ac75b9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.beginLayer-save-endLayer.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.invalid-calls.beginLayer-save-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.invalid-calls.beginLayer-save-endLayer</h1>
+<p class="desc">Raises exception on beginLayer() + save() + endLayer().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Raises exception on beginLayer() + save() + endLayer().");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.beginLayer();
+ ctx.save();
+ ctx.endLayer();
+ });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.endLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.endLayer.html
new file mode 100644
index 0000000000..c39a352d65
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.endLayer.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.invalid-calls.endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.invalid-calls.endLayer</h1>
+<p class="desc">Raises exception on lone endLayer calls.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Raises exception on lone endLayer calls.");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.endLayer();
+ });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-beginLayer-restore.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-beginLayer-restore.html
new file mode 100644
index 0000000000..e2d4d56589
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-beginLayer-restore.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.invalid-calls.save-beginLayer-restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.invalid-calls.save-beginLayer-restore</h1>
+<p class="desc">Raises exception on save() + beginLayer() + restore().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Raises exception on save() + beginLayer() + restore().");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.save();
+ ctx.beginLayer();
+ ctx.restore();
+ });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-endLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-endLayer.html
new file mode 100644
index 0000000000..f4308e1191
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.invalid-calls.save-endLayer.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.invalid-calls.save-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.invalid-calls.save-endLayer</h1>
+<p class="desc">Raises exception on save() + endLayer().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Raises exception on save() + endLayer().");
+_addTest(function(canvas, ctx) {
+
+ assert_throws_dom("INVALID_STATE_ERR", function() {
+ ctx.save();
+ ctx.endLayer();
+ });
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.layer-rendering-state-reset-in-layer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.layer-rendering-state-reset-in-layer.html
new file mode 100644
index 0000000000..9283fd39b7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.layer-rendering-state-reset-in-layer.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.layer-rendering-state-reset-in-layer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.layer-rendering-state-reset-in-layer</h1>
+<p class="desc">Tests that layers ignore the global context filter.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Tests that layers ignore the global context filter.");
+_addTest(function(canvas, ctx) {
+
+ ctx.globalAlpha = 0.5;
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowColor = '#0000ff';
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 20;
+ ctx.shadowBlur = 30;
+
+ _assertSame(ctx.globalAlpha, 0.5, "ctx.globalAlpha", "0.5");
+ _assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+ _assertSame(ctx.shadowColor, '#0000ff', "ctx.shadowColor", "'#0000ff'");
+ _assertSame(ctx.shadowOffsetX, 10, "ctx.shadowOffsetX", "10");
+ _assertSame(ctx.shadowOffsetY, 20, "ctx.shadowOffsetY", "20");
+ _assertSame(ctx.shadowBlur, 30, "ctx.shadowBlur", "30");
+
+ ctx.beginLayer();
+
+ _assertSame(ctx.globalAlpha, 1.0, "ctx.globalAlpha", "1.0");
+ _assertSame(ctx.globalCompositeOperation, 'source-over', "ctx.globalCompositeOperation", "'source-over'");
+ _assertSame(ctx.shadowColor, 'rgba(0, 0, 0, 0)', "ctx.shadowColor", "'rgba(0, 0, 0, 0)'");
+ _assertSame(ctx.shadowOffsetX, 0, "ctx.shadowOffsetX", "0");
+ _assertSame(ctx.shadowOffsetY, 0, "ctx.shadowOffsetY", "0");
+ _assertSame(ctx.shadowBlur, 0, "ctx.shadowBlur", "0");
+
+ ctx.endLayer();
+
+ _assertSame(ctx.globalAlpha, 0.5, "ctx.globalAlpha", "0.5");
+ _assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+ _assertSame(ctx.shadowColor, '#0000ff', "ctx.shadowColor", "'#0000ff'");
+ _assertSame(ctx.shadowOffsetX, 10, "ctx.shadowOffsetX", "10");
+ _assertSame(ctx.shadowOffsetY, 20, "ctx.shadowOffsetY", "20");
+ _assertSame(ctx.shadowBlur, 30, "ctx.shadowBlur", "30");
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html
new file mode 100644
index 0000000000..f1204aa61b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.createImageBitmap.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations-with-promises.createImageBitmap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations-with-promises.createImageBitmap</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+promise_test(async t => {
+
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
+
+ // Shouldn't throw on its own.
+ await createImageBitmap(canvas);
+ // Make sure the exception isn't caused by calling the function twice.
+ await createImageBitmap(canvas);
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ await promise_rejects_dom(t, 'InvalidStateError', createImageBitmap(canvas));
+
+}, "Check that exceptions are thrown for operations that are malformed while layers are open.");
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.toBlob.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.toBlob.html
new file mode 100644
index 0000000000..6c69bb3784
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations-with-promises.toBlob.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations-with-promises.toBlob</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations-with-promises.toBlob</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+promise_test(async t => {
+
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
+
+ // Shouldn't throw on its own.
+ await new Promise(resolve => canvas.toBlob(resolve));
+ // Make sure the exception isn't caused by calling the function twice.
+ await new Promise(resolve => canvas.toBlob(resolve));
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ await promise_rejects_dom(t, 'InvalidStateError', new Promise(resolve => canvas.toBlob(resolve)));
+
+}, "Check that exceptions are thrown for operations that are malformed while layers are open.");
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.createPattern.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.createPattern.html
new file mode 100644
index 0000000000..f927b96524
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.createPattern.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations.createPattern</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations.createPattern</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
+_addTest(function(canvas, ctx) {
+
+ // Shouldn't throw on its own.
+ ctx.createPattern(canvas, 'repeat');
+ // Make sure the exception isn't caused by calling the function twice.
+ ctx.createPattern(canvas, 'repeat');
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => ctx.createPattern(canvas, 'repeat'));
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.drawImage.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.drawImage.html
new file mode 100644
index 0000000000..8bcc89d38e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.drawImage.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations.drawImage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations.drawImage</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
+_addTest(function(canvas, ctx) {
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+ // Shouldn't throw on its own.
+ ctx2.drawImage(canvas, 0, 0);
+ // Make sure the exception isn't caused by calling the function twice.
+ ctx2.drawImage(canvas, 0, 0);
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => ctx2.drawImage(canvas, 0, 0));
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.getImageData.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.getImageData.html
new file mode 100644
index 0000000000..5dc3fcc017
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.getImageData.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations.getImageData</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations.getImageData</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
+_addTest(function(canvas, ctx) {
+
+ // Shouldn't throw on its own.
+ ctx.getImageData(0, 0, 200, 200);
+ // Make sure the exception isn't caused by calling the function twice.
+ ctx.getImageData(0, 0, 200, 200);
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => ctx.getImageData(0, 0, 200, 200));
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.putImageData.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.putImageData.html
new file mode 100644
index 0000000000..fd4fc262c2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.putImageData.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations.putImageData</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations.putImageData</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
+_addTest(function(canvas, ctx) {
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d')
+ const data = ctx2.getImageData(0, 0, 1, 1);
+ // Shouldn't throw on its own.
+ ctx.putImageData(data, 0, 0);
+ // Make sure the exception isn't caused by calling the function twice.
+ ctx.putImageData(data, 0, 0);
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => ctx.putImageData(data, 0, 0));
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.toDataURL.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.toDataURL.html
new file mode 100644
index 0000000000..c9bb4f3875
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.malformed-operations.toDataURL.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.malformed-operations.toDataURL</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.malformed-operations.toDataURL</h1>
+<p class="desc">Check that exceptions are thrown for operations that are malformed while layers are open.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="200" height="200"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Check that exceptions are thrown for operations that are malformed while layers are open.");
+_addTest(function(canvas, ctx) {
+
+ // Shouldn't throw on its own.
+ canvas.toDataURL();
+ // Make sure the exception isn't caused by calling the function twice.
+ canvas.toDataURL();
+ // Calling again inside a layer should throw.
+ ctx.beginLayer();
+ assert_throws_dom("InvalidStateError",
+ () => canvas.toDataURL());
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html
new file mode 100644
index 0000000000..65525d4d6a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+
+ ctx2.globalAlpha = 0.5;
+
+ canvas3 = document.createElement("canvas");
+ ctx3 = canvas3.getContext("2d");
+
+ ctx3.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx3.fillRect(50, 50, 75, 50);
+ ctx3.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx3.fillRect(70, 70, 75, 50);
+
+ ctx2.drawImage(canvas3, 0, 0);
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters-expected.html
new file mode 100644
index 0000000000..8b53e2dc76
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters-expected.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.nested-filters</title>
+<h1>2d.layer.nested-filters</h1>
+<p class="desc">Checks that nested layers work properly when both apply filters.</p>
+<canvas id="canvas" width="400" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(20, 20, 100, 100);
+ ctx.fillRect(30, 30, 100, 100);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(40, 40, 100, 100);
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(280, 80, 100, 100);
+ ctx.fillRect(270, 70, 100, 100);
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(260, 60, 100, 100);
+ ctx.fillStyle = 'red';
+ ctx.fillRect(250, 50, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters.html
new file mode 100644
index 0000000000..333de67ac9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-filters.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.nested-filters-expected.html">
+<title>Canvas test: 2d.layer.nested-filters</title>
+<h1>2d.layer.nested-filters</h1>
+<p class="desc">Checks that nested layers work properly when both apply filters.</p>
+<canvas id="canvas" width="400" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -20, dy: -20,
+ stdDeviation: 0, floodColor: 'yellow'}});
+ ctx.beginLayer({filter: 'drop-shadow(-10px -10px 0 blue)'});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 50, 100, 100);
+
+ ctx.endLayer();
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'drop-shadow(20px 20px 0 blue)'});
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: 10, dy: 10,
+ stdDeviation: 0, floodColor: 'yellow'}});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(250, 50, 100, 100);
+
+ ctx.endLayer();
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html
new file mode 100644
index 0000000000..a508d8e5c8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.nested-expected.html">
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas-expected.html
new file mode 100644
index 0000000000..89c85de1e5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.opaque-canvas</title>
+<h1>2d.layer.opaque-canvas</h1>
+<p class="desc">Checks that layer blending works inside opaque canvas</p>
+<canvas id="canvas" width="300" height="300">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 300, 300);
+
+ ctx.fillStyle = 'black';
+ ctx.fillRect(0, 0, 200, 200);
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(10, 10, 100, 100);
+
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'green';
+ ctx2.fillRect(50, 50, 100, 100);
+ ctx2.globalAlpha = 0.8;
+ ctx2.fillStyle = 'yellow';
+ ctx2.fillRect(75, 25, 100, 100);
+
+ ctx.shadowColor = 'rgba(200, 100, 50, 0.5)';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas.html
new file mode 100644
index 0000000000..be8b088fbb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.opaque-canvas.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.opaque-canvas-expected.html">
+<title>Canvas test: 2d.layer.opaque-canvas</title>
+<h1>2d.layer.opaque-canvas</h1>
+<p class="desc">Checks that layer blending works inside opaque canvas</p>
+<canvas id="canvas" width="300" height="300">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const canvas2 = document.createElement('canvas');
+ canvas2.width = 200;
+ canvas2.height = 200;
+ const ctx2 = canvas2.getContext('2d', {alpha: false});
+
+ ctx2.fillStyle = 'purple';
+ ctx2.fillRect(10, 10, 100, 100);
+
+ ctx2.beginLayer({filter: {name: 'dropShadow', dx: -10, dy: 10,
+ stdDeviation: 0,
+ floodColor: 'rgba(200, 100, 50, 0.5)'}});
+ ctx2.fillStyle = 'green';
+ ctx2.fillRect(50, 50, 100, 100);
+ ctx2.globalAlpha = 0.8;
+ ctx2.fillStyle = 'yellow';
+ ctx2.fillRect(75, 25, 100, 100);
+ ctx2.endLayer();
+
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 300, 300);
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset-expected.html
new file mode 100644
index 0000000000..93131dca9c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset-expected.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.reset</title>
+<h1>2d.layer.reset</h1>
+<p class="desc">Checks that reset discards any pending layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillRect(10, 10, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset.html
new file mode 100644
index 0000000000..9ad779abfd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.reset.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.reset-expected.html">
+<title>Canvas test: 2d.layer.reset</title>
+<h1>2d.layer.reset</h1>
+<p class="desc">Checks that reset discards any pending layers.</p>
+<canvas id="canvas" width="100" height="50">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ // Global states:
+ ctx.globalAlpha = 0.3;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -3;
+ ctx.shadowOffsetY = 3;
+ ctx.shadowColor = 'rgba(0, 30, 0, 0.3)';
+ ctx.shadowBlur = 3;
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -3, dy: 3}});
+
+ // Layer states:
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -6;
+ ctx.shadowOffsetY = 6;
+ ctx.shadowColor = 'rgba(0, 60, 0, 0.6)';
+ ctx.shadowBlur = 3;
+
+ ctx.reset();
+
+ ctx.fillRect(10, 10, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html
new file mode 100644
index 0000000000..1d0ac3558d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+ ctx.drawImage(canvas2, 0, 0);
+
+ ctx.fillRect(70, 70, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html
new file mode 100644
index 0000000000..2537f409d6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.restore-style-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-950">
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0,0,255,1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(70, 70, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html
new file mode 100644
index 0000000000..ef46f69e2a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+ ctx.shadowBlur = 3;
+
+ var canvas2 = [5];
+ var ctx2 = [5];
+
+ for (let i = 0; i < 5; i++) {
+ canvas2[i] = document.createElement("canvas");
+ ctx2[i] = canvas2[i].getContext("2d");
+ ctx2[i].fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2[i].fillRect(60, 40, 75, 50);
+ ctx2[i].fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2[i].fillRect(80, 60, 75, 50);
+
+ ctx.drawImage(canvas2[i], i, i);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html
new file mode 100644
index 0000000000..cff0c123ef
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.several-complex-expected.html">
+<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-6318">
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+ ctx.shadowBlur = 3
+
+ for (let i = 0; i < 5; i++) {
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60 + i, 40 + i, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(80 + i, 60 + i, 75, 50);
+
+ ctx.endLayer();
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html
new file mode 100644
index 0000000000..cc10684a9b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ // No clipping.
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html
new file mode 100644
index 0000000000..377dd55ef6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html
new file mode 100644
index 0000000000..88a3a67c7b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance-with-clipping.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.long-distance-with-clipping-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance.html
new file mode 100644
index 0000000000..8ade08bec5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.long-distance.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.long-distance-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.long-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.long-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 10000;
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html
new file mode 100644
index 0000000000..8980708dd1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-expected.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ // No clipping.
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html
new file mode 100644
index 0000000000..024fc8c9a4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html
new file mode 100644
index 0000000000..7ced448144
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance-with-clipping.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.short-distance-with-clipping-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance-with-clipping</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ const clipRegion = new Path2D();
+ clipRegion.rect(20, 20, 160, 160);
+ ctx.clip(clipRegion);
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance.html
new file mode 100644
index 0000000000..37398400d1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.shadow-from-outside-canvas.short-distance.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.shadow-from-outside-canvas.short-distance-expected.html">
+<title>Canvas test: 2d.layer.shadow-from-outside-canvas.short-distance</title>
+<h1>2d.layer.shadow-from-outside-canvas.short-distance</h1>
+<p class="desc">Checks shadow produced by object drawn outside the canvas</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const delta = 1;
+
+ // No clipping.
+
+ ctx.beginLayer({filter: [
+ {name: 'dropShadow', dx: -(200 + delta),
+ dy: -(200 + delta), stdDeviation: 0,
+ floodColor: 'green'},
+ ]});
+
+ ctx.fillStyle = 'red';
+ ctx.fillRect(200 + delta, 200 + delta, 100, 100);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-endLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-endLayer.html
new file mode 100644
index 0000000000..609cb19a7d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-endLayer.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.beginLayer-endLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.beginLayer-endLayer</h1>
+<p class="desc">No exception raised on beginLayer() + endLayer().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on beginLayer() + endLayer().");
+_addTest(function(canvas, ctx) {
+
+ ctx.beginLayer();
+ ctx.save();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-save.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-save.html
new file mode 100644
index 0000000000..9658040296
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer-save.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.beginLayer-save</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.beginLayer-save</h1>
+<p class="desc">No exception raised on beginLayer() + save().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on beginLayer() + save().");
+_addTest(function(canvas, ctx) {
+
+ ctx.beginLayer();
+ ctx.save();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer.html
new file mode 100644
index 0000000000..0556683331
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.beginLayer.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.beginLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.beginLayer</h1>
+<p class="desc">No exception raised on lone beginLayer() calls.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on lone beginLayer() calls.");
+_addTest(function(canvas, ctx) {
+
+ ctx.beginLayer();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.restore.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.restore.html
new file mode 100644
index 0000000000..b7a370306f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.restore.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.restore</h1>
+<p class="desc">No exception raised on lone restore() calls.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on lone restore() calls.");
+_addTest(function(canvas, ctx) {
+
+ ctx.restore();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save-beginLayer.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save-beginLayer.html
new file mode 100644
index 0000000000..816398c7fc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save-beginLayer.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.save-beginLayer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.save-beginLayer</h1>
+<p class="desc">No exception raised on save() + beginLayer().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on save() + beginLayer().");
+_addTest(function(canvas, ctx) {
+
+ ctx.save();
+ ctx.beginLayer();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save.html
new file mode 100644
index 0000000000..d8df8cedce
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.save</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.save</h1>
+<p class="desc">No exception raised on lone save() calls.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on lone save() calls.");
+_addTest(function(canvas, ctx) {
+
+ ctx.save();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_reset_restore.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_reset_restore.html
new file mode 100644
index 0000000000..4c733263a6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_reset_restore.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.save_reset_restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.save_reset_restore</h1>
+<p class="desc">No exception raised on save() + reset() + restore().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on save() + reset() + restore().");
+_addTest(function(canvas, ctx) {
+
+ ctx.save();
+ ctx.reset();
+ ctx.restore();
+
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_restore.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_restore.html
new file mode 100644
index 0000000000..27ae70278e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.valid-calls.save_restore.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.valid-calls.save_restore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.layer.valid-calls.save_restore</h1>
+<p class="desc">No exception raised on save() + restore().</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("No exception raised on save() + restore().");
+_addTest(function(canvas, ctx) {
+
+ ctx.save();
+ ctx.restore();
+
+});
+</script>
+